Skip to content

Commit

Permalink
Convert to TypeScript. Generate CSS with prefix option.
Browse files Browse the repository at this point in the history
  • Loading branch information
origami-z committed Jan 31, 2024
1 parent 7fd5fb0 commit fd449be
Show file tree
Hide file tree
Showing 10 changed files with 635 additions and 65 deletions.
19 changes: 17 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions packages/export-variables-rest-api/package.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
{
"name": "figma-variables-rest-api",
"type": "module",
"version": "0.0.1",
"description": "Script to export Figma variables using REST API",
"main": "dist/index.js",
"module": "src/index.ts",
"scripts": {
"dev": "node src/index.js",
"dev": "vite-node src/index.ts",
"clean": "rimraf build tokens",
"test": "vitest run",
"test:watch": "vitest watch",
Expand All @@ -26,6 +25,7 @@
"proxy-agent": "^6.3.1",
"rimraf": "^5.0.5",
"style-dictionary": "^3.9.1",
"style-dictionary-utils": "^2.0.7"
"style-dictionary-utils": "^2.0.7",
"zod": "^3.22.4"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ describe("updateApiResponse", () => {
codeSyntax: {},
},
},
};
} as const;
expect(
Object.values(input.variableCollections).every((c) => c.remote === false)
).toBeFalsy();
Expand Down Expand Up @@ -176,7 +176,7 @@ describe("updateApiResponse", () => {
codeSyntax: {},
},
},
};
} as const;
expect(input.variables["VariableID:1"].variableCollectionId).toEqual(
input.variables["VariableID:2"].variableCollectionId
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { describe, expect, test } from "vitest";
import { parseTokenObject, generateCssFromJson } from "../tokenUtils";

const sampleValidColorToken = {
a: { with6DigitHex: { $type: "color", $value: "#123456" } },
b: { withAlphaHex: { $type: "color", $value: "#12345678" } },
c: { withReferenceValue: { $type: "color", $value: "{a.with6DigitHex}" } },
};

const sampleValidNumberToken = {
a: { number: { $type: "number", $value: 1 } },
c: { withReferenceValue: { $type: "color", $value: "{a.number}" } },
};

describe("validateTokenObject", () => {
test("valid color tokens", () => {
expect(parseTokenObject(sampleValidColorToken).success).toBe(true);
});
test("invalid color tokens", () => {
expect(
parseTokenObject({
a: { with5DigitHex: { $type: "color", $value: "#12345" } },
b: { with7DigitHex: { $type: "color", $value: "#1234567" } },
}).success
).toBe(false);
});
test("valid number tokens", () => {
expect(parseTokenObject(sampleValidNumberToken).success).toBe(true);
});
test("invalid number tokens", () => {
expect(
parseTokenObject({
a: { notNumber: { $type: "color", $value: "string" } },
}).success
).toBe(false);
});
test("unsupported token types", () => {
expect(
parseTokenObject({
a: { otherTypes: { $type: "other", $value: "string" } },
}).success
).toBe(false);
});
});

describe("generateCssFromJson", () => {
describe("color tokens", () => {
test("generates css", () => {
const generatedCss = generateCssFromJson(
JSON.stringify(sampleValidColorToken)
);
expect(generatedCss).toEqual(
`--a-with6DigitHex: #123456;
--b-withAlphaHex: #12345678;
--c-withReferenceValue: var(--a-with6DigitHex);`
);
});

test("generates css with prefix when provided", () => {
const generatedCss = generateCssFromJson(
JSON.stringify(sampleValidColorToken),
{ prefix: "prefix" }
);
expect(generatedCss).toEqual(
`--prefix-a-with6DigitHex: #123456;
--prefix-b-withAlphaHex: #12345678;
--prefix-c-withReferenceValue: var(--prefix-a-with6DigitHex);`
);
});
});

describe("number tokens", () => {
test("generates css", () => {
const generatedCss = generateCssFromJson(
JSON.stringify(sampleValidNumberToken)
);
expect(generatedCss).toEqual(
`--a-number: 1px;
--c-withReferenceValue: var(--a-number);`
);
});
test("generates css with prefix when provided", () => {
const generatedCss = generateCssFromJson(
JSON.stringify(sampleValidNumberToken),
{ prefix: "prefix" }
);
expect(generatedCss).toEqual(
`--prefix-a-number: 1px;
--prefix-c-withReferenceValue: var(--prefix-a-number);`
);
});
});
});
36 changes: 36 additions & 0 deletions packages/export-variables-rest-api/src/colorUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Color } from "./types";

function toHex(value: number) {
const hex = Math.round(value * 255).toString(16);
return hex.length === 1 ? "0" + hex : hex;
}

/**
* Converts RGB[A] color to hex value
* @link https://design-tokens.github.io/community-group/format/#color
*/
export function stringifyRGBA(color: Color) {
if ("a" in color) {
const { r, g, b, a } = color; // To HEX
if (a !== 1) {
return `#${[toHex(r), toHex(g), toHex(b), toHex(a)].join("")}`;
} else {
const hex = [toHex(r), toHex(g), toHex(b)].join("");
return `#${hex}`;
}
}
const { r, g, b } = color; // To HEX
const hex = [toHex(r), toHex(g), toHex(b)].join("");
return `#${hex}`;

// According https://design-tokens.github.io/community-group/format/#color
// Should only use hex
// // To RGBA
// if (a !== 1) {
// return `rgba(${[r, g, b]
// .map((n) => Math.round(n * 255))
// .join(", ")}, ${a.toFixed(4)})`;
// }
// // To RGB
// return `rgb(${[r, g, b].map((n) => Math.round(n * 255)).join(", ")})`;
}
Loading

0 comments on commit fd449be

Please sign in to comment.