Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add maths calc function to post-process-css #378

Draft
wants to merge 2 commits into
base: beta
Choose a base branch
from
Draft
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
228 changes: 228 additions & 0 deletions scripts/post-process-css/formatters/maths-calc/maths-calc.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
import { expect } from "chai";
import { BrandTokens } from "../../brand-tokens";
import { ScreenSizeTokens } from "../../screen-size-tokens";
import { MathsCalc } from "./maths-calc";

describe("MathsCalc", () => {
const mathsCalc = new MathsCalc();

describe("mathsCalc", () => {
it("should format tokens as expected", () => {
const tokens = new BrandTokens([
new ScreenSizeTokens(
[
{ name: "--global-prop1", value: "value1" },
{ name: "--global-prop2", value: "value1 value2" },
{ name: "--global-prop3", value: "value1 * value2" },
{ name: "--global-prop4", value: "value1 / value2" },
{ name: "--global-prop5", value: "value1 + value2" },
{ name: "--global-prop6", value: "value1 - value2" },
{ name: "--global-prop7", value: "value1 * value2 + value3" },
{ name: "--global-prop8", value: "value1 * value2 value3" },
{ name: "--global-prop9", value: "(value1 + value2) * value3" },
{ name: "--global-prop10", value: "(value1 + value2) * (value3 - value4)" },
{ name: "--global-prop11", value: "(value1 + value2) * (value3 - value4) value5 - value6" },
{ name: "--global-typography1", value: "900 clamp(2.1588rem, 1.7083rem + 2.2525vw, 4.4113rem)/1.25 'Sage Headline'"},
{ name: "--global-typography2", value: "400 20px/1 sage-icons"},
],
[],
[],
{
badge: [
{
name: "--badge-prop1",
value: "var(--global-prop1)",
},
{
name: "--badge-prop2",
value: "var(--global-prop1) * 2",
},
{
name: "--badge-prop3",
value: "var(--global-prop1) / 2",
},
{
name: "--badge-prop4",
value: "var(--global-prop1) + 2",
},
{
name: "--badge-prop5",
value: "var(--global-prop1) - 2",
},
{
name: "--badge-prop6",
value: "var(--global-prop1) - var(--global-prop2)",
},
{
name: "--badge-prop7",
value: "(var(--global-prop1) - var(--global-prop2)) * var(--global-prop3)",
},
],
}
),
new ScreenSizeTokens(
[
{ name: "--global-size-breakpoint-min-width", value: "1024px" },
{ name: "--global-prop1", value: "value1" },
{ name: "--global-prop2", value: "value1 value2" },
{ name: "--global-prop3", value: "value1 * value2" },
{ name: "--global-prop4", value: "value1 / value2" },
{ name: "--global-prop5", value: "value1 + value2" },
{ name: "--global-prop6", value: "value1 - value2" },
{ name: "--global-prop7", value: "value1 * value2 + value3" },
{ name: "--global-prop8", value: "value1 * value2 value3" },
{ name: "--global-prop9", value: "(value1 + value2) * value3" },
{ name: "--global-prop10", value: "(value1 + value2) * (value3 - value4)" },
{ name: "--global-prop11", value: "(value1 + value2) * (value3 - value4) value5 - value6" },
{ name: "--global-typography1", value: "900 clamp(2.1588rem, 1.7083rem + 2.2525vw, 4.4113rem)/1.25 'Sage Headline'"},
{ name: "--global-typography2", value: "400 20px/1 sage-icons"},
],
[],
[],
{
badge: [
{
name: "--badge-prop1",
value: "var(--global-prop1)",
},
{
name: "--badge-prop2",
value: "var(--global-prop1) * 2",
},
{
name: "--badge-prop3",
value: "var(--global-prop1) / 2",
},
{
name: "--badge-prop4",
value: "var(--global-prop1) + 2",
},
{
name: "--badge-prop5",
value: "var(--global-prop1) - 2",
},
{
name: "--badge-prop6",
value: "var(--global-prop1) - var(--global-prop2)",
},
{
name: "--badge-prop7",
value: "(var(--global-prop1) - var(--global-prop2)) * var(--global-prop3)",
},
],
}
),
]);

const result = mathsCalc.formatTokens(tokens);
expect(result).to.deep.equal({
screenSizes: [
{
global: [
{ name: "--global-prop1", value: "value1" },
{ name: "--global-prop2", value: "value1 value2" },
{ name: "--global-prop3", value: "calc(value1 * value2)" },
{ name: "--global-prop4", value: "calc(value1 / value2)" },
{ name: "--global-prop5", value: "calc(value1 + value2)" },
{ name: "--global-prop6", value: "calc(value1 - value2)" },
{ name: "--global-prop7", value: "calc(value1 * value2 + value3)" },
{ name: "--global-prop8", value: "calc(value1 * value2) value3" },
{ name: "--global-prop9", value: "calc((value1 + value2) * value3)" },
{ name: "--global-prop10", value: "calc((value1 + value2) * (value3 - value4))" },
{ name: "--global-prop11", value: "calc((value1 + value2) * (value3 - value4)) calc(value5 - value6)" },
{ name: "--global-typography1", value: "900 clamp(2.1588rem, 1.7083rem + 2.2525vw, 4.4113rem)/1.25 'Sage Headline'"},
{ name: "--global-typography2", value: "400 20px/1 sage-icons"},
],
light: [],
dark: [],
components: {
badge: [
{
name: "--badge-prop1",
value: "var(--global-prop1)",
},
{
name: "--badge-prop2",
value: "calc(var(--global-prop1) * 2)",
},
{
name: "--badge-prop3",
value: "calc(var(--global-prop1) / 2)",
},
{
name: "--badge-prop4",
value: "calc(var(--global-prop1) + 2)",
},
{
name: "--badge-prop5",
value: "calc(var(--global-prop1) - 2)",
},
{
name: "--badge-prop6",
value: "calc(var(--global-prop1) - var(--global-prop2))",
},
{
name: "--badge-prop7",
value: "calc((var(--global-prop1) - var(--global-prop2)) * var(--global-prop3))",
},
],
},
minBreakpoint: 0,
},
{
global: [
{ name: "--global-prop1", value: "value1" },
{ name: "--global-prop2", value: "value1 value2" },
{ name: "--global-prop3", value: "calc(value1 * value2)" },
{ name: "--global-prop4", value: "calc(value1 / value2)" },
{ name: "--global-prop5", value: "calc(value1 + value2)" },
{ name: "--global-prop6", value: "calc(value1 - value2)" },
{ name: "--global-prop7", value: "calc(value1 * value2 + value3)" },
{ name: "--global-prop8", value: "calc(value1 * value2) value3" },
{ name: "--global-prop9", value: "calc((value1 + value2) * value3)" },
{ name: "--global-prop10", value: "calc((value1 + value2) * (value3 - value4))" },
{ name: "--global-prop11", value: "calc((value1 + value2) * (value3 - value4)) calc(value5 - value6)" },
{ name: "--global-typography1", value: "900 clamp(2.1588rem, 1.7083rem + 2.2525vw, 4.4113rem)/1.25 'Sage Headline'"},
{ name: "--global-typography2", value: "400 20px/1 sage-icons"},
],
light: [],
dark: [],
components: {
badge: [
{
name: "--badge-prop1",
value: "var(--global-prop1)",
},
{
name: "--badge-prop2",
value: "calc(var(--global-prop1) * 2)",
},
{
name: "--badge-prop3",
value: "calc(var(--global-prop1) / 2)",
},
{
name: "--badge-prop4",
value: "calc(var(--global-prop1) + 2)",
},
{
name: "--badge-prop5",
value: "calc(var(--global-prop1) - 2)",
},
{
name: "--badge-prop6",
value: "calc(var(--global-prop1) - var(--global-prop2))",
},
{
name: "--badge-prop7",
value: "calc((var(--global-prop1) - var(--global-prop2)) * var(--global-prop3))",
},
],
},
minBreakpoint: 1024,
},
],
});
});
});
});
74 changes: 74 additions & 0 deletions scripts/post-process-css/formatters/maths-calc/maths-calc.ts
Copy link
Contributor

Choose a reason for hiding this comment

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

As discussed - change will need to be made to all CSS files in dist directory rather than only the all.css file.

Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { BrandTokens } from "../../brand-tokens";
import { Decorator } from "../decorator";

interface IPartConditions {
isLeft: boolean
isMath: boolean
isMiddle: boolean
isRight: boolean
part: string
}

export class MathsCalc extends Decorator {
private readonly mathChars = ['+', '-', '*', '/'];
/**
*
* @param tokens Tokens to format.
* @returns Formatted tokens.
*/
public override formatTokens(tokens: BrandTokens) {

tokens.screenSizes.forEach((screenSize) => {

screenSize.global.forEach((token) => token.value = this.formatTokenValue(token.value));
screenSize.light.forEach((token) => token.value = this.formatTokenValue(token.value));
screenSize.dark.forEach((token) => token.value = this.formatTokenValue(token.value));

Object.keys(screenSize.components).forEach((component) => {
if (screenSize.components[component]) {
screenSize.components[component].forEach((token) => token.value = this.formatTokenValue(token.value));
}
});
})

return super.formatTokens(tokens);
}

private formatTokenValue(value: string): string {
const hasClamp = /clamp\s*\(.*\)/

if (hasClamp.test(value)) return value

const valueParts = value.split(' ');

const valueConditions = this.checkConditions(valueParts)

valueConditions.forEach((item, i) => {
if (item.isLeft && !item.isMiddle) valueParts[i] = `calc(${item.part}`
if (item.isRight && !item.isMiddle) valueParts[i] = `${item.part})`
})

return valueParts.join(' ')
}

private checkConditions(valueParts: string[]): IPartConditions[] {
const partConditions: IPartConditions[] = []

valueParts.forEach((part, i) => {
const left = i > 0 ? valueParts[i - 1] : '';
const right = valueParts[i + 1] ?? '';

const conditions = {
part,
isMath: this.mathChars.includes(part),
isLeft: this.mathChars.includes(right),
isRight: this.mathChars.includes(left),
isMiddle: this.mathChars.includes(right) && this.mathChars.includes(left),
}

partConditions.push(conditions)
});

return partConditions
}
}
Loading