Skip to content

Commit 403891d

Browse files
authored
Web components: file organization at project root (uswds#182)
* move storybook server script * format comment for build helpers * add internals directory and organize * extract token naming logic to helper function and clean up style-dictionary config * add types * get test coverage for transformer * use site margins token in test use site margins token in test * clean up test import * add test for transform * update path to storybook
1 parent 434fa08 commit 403891d

File tree

10 files changed

+166
-48
lines changed

10 files changed

+166
-48
lines changed
Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
import { describe, it, expect } from "vitest";
2-
import {
3-
mapEntryToLimit,
4-
type Entry,
5-
mapEntryToTuple,
6-
mapEntriesToKeyValue,
7-
} from "./build-helpers";
2+
import { mapEntryToLimit, type Entry, mapEntriesToKeyValue } from "./index";
83

94
describe("mapEntryToLimit", () => {
105
it("should correctly transform an entry to a Limit object", () => {
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ export type Entry = { name: string; path: string; sizeLimit: string };
77
* the properties to adhere to the `Limit` type structure.
88
*
99
* @param {Entry} entry - The input object containing information about the entry.
10-
* @returns {Limit} - A transformed object with details about the limit, including
11-
* the updated name, size limit, and compression mode.
10+
* @return {Limit} - A transformed object with details about the limit, including
11+
* the updated name, size limit, and compression mode.
1212
*/
1313
export const mapEntryToLimit = (entry: Entry): Limit => {
1414
return {
@@ -23,7 +23,7 @@ export const mapEntryToLimit = (entry: Entry): Limit => {
2323
* is used as the key and its path is used as the value.
2424
*
2525
* @param {Entry[]} entries - The array of Entry objects to be mapped into key-value pairs.
26-
* @return {Record<string, string>} An object representing the key-value pairs derived from the entries,
26+
* @return {Record<string, string>} - An object representing the key-value pairs derived from the entries,
2727
* where the key is the entry's name and the value is the entry's path.
2828
*/
2929
export function mapEntriesToKeyValue(entries: Entry[]): Record<string, string> {
Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,9 @@ const __dirname = path.dirname(__filename);
99
const app = express();
1010
const PORT = process.env.PORT || 3000;
1111

12-
console.log(path.join(__dirname, "..", "storybook-static"));
13-
1412
// Serve static files from storybook-static directory
1513
app.use(
16-
serveStatic(path.join(__dirname, "..", "storybook-static"), {
14+
serveStatic(path.join(__dirname, "..", "..", "storybook-static"), {
1715
index: ["index.html"],
1816
}),
1917
);
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
import { describe, it, expect } from "vitest";
2+
import type { TransformedToken, PlatformConfig } from "style-dictionary/types";
3+
import { generateTokenName, getTokenValueWithUnit } from "./index";
4+
5+
describe("generateTokenName", () => {
6+
const token: TransformedToken = {
7+
$value: { value: "75", unit: "rem" },
8+
filePath: "tokens/dimension/breakpoints.json",
9+
isSource: true,
10+
$type: "dimension",
11+
key: "{breakpoint.desktop-lg}",
12+
original: {
13+
$value: { value: "75", unit: "rem" },
14+
$type: "dimension",
15+
key: "{breakpoint.desktop-lg}",
16+
},
17+
name: "desktop-lg",
18+
attributes: {},
19+
path: ["breakpoint", "desktop-lg"],
20+
};
21+
22+
const options: PlatformConfig = {
23+
prefix: "usa",
24+
transforms: [],
25+
buildPath: "",
26+
files: [],
27+
log: {},
28+
actions: [],
29+
};
30+
31+
it("should generate token name for breakpoint prefix", () => {
32+
const result = generateTokenName(token, options);
33+
expect(result).toBe("usa-breakpoint-desktop-lg");
34+
});
35+
36+
it("should generate token name for spacing prefix", () => {
37+
const spacingToken: TransformedToken = {
38+
...token,
39+
path: ["site-margins", "width"],
40+
};
41+
const result = generateTokenName(spacingToken, options);
42+
expect(result).toBe("usa-site-margins-width");
43+
});
44+
45+
it("should generate token name for color directory with single path key", () => {
46+
const colorTokenSingle: TransformedToken = {
47+
...token,
48+
filePath: "tokens/color/primary.json",
49+
path: ["black"],
50+
};
51+
const result = generateTokenName(colorTokenSingle, options);
52+
expect(result).toBe("usa-color-black");
53+
});
54+
55+
it("should generate token name for color directory with multiple path keys", () => {
56+
const colorTokenMulti: TransformedToken = {
57+
...token,
58+
filePath: "tokens/color/primary.json",
59+
path: ["primary", "light"],
60+
};
61+
const result = generateTokenName(colorTokenMulti, options);
62+
expect(result).toBe("usa-color-primary-light");
63+
});
64+
65+
it("should generate token name fallback for other cases", () => {
66+
const otherToken: TransformedToken = {
67+
...token,
68+
path: ["font", "base-size"],
69+
};
70+
const result = generateTokenName(otherToken, options);
71+
expect(result).toBe("usa-font-base-size");
72+
});
73+
});
74+
75+
describe("getTokenValueWithUnit", () => {
76+
const defaultToken: TransformedToken = {
77+
$value: { value: "75", unit: "rem" },
78+
$type: "dimension",
79+
isSource: true,
80+
key: "desktop-lg",
81+
name: "desktop-lg",
82+
attributes: {},
83+
path: ["breakpoint", "desktop-lg"],
84+
original: {
85+
$value: { value: "75", unit: "rem" },
86+
$type: "dimension",
87+
key: "desktop-lg",
88+
},
89+
};
90+
91+
it("should return value + unit for dimension tokens with object value", () => {
92+
const result = getTokenValueWithUnit(defaultToken);
93+
expect(result).toBe("75rem");
94+
});
95+
96+
it("should return value string when unit is missing in dimension object", () => {
97+
const token = {
98+
...defaultToken,
99+
$value: { value: "30" },
100+
};
101+
const result = getTokenValueWithUnit(token);
102+
expect(result).toBe("30");
103+
});
104+
105+
it("should return raw value if token type is not dimension", () => {
106+
const token = {
107+
$value: "#fff2f5",
108+
$type: "color",
109+
};
110+
const result = getTokenValueWithUnit(token);
111+
expect(result).toBe("#fff2f5");
112+
});
113+
});

internals/token-helpers/index.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import type { TransformedToken, PlatformConfig } from "style-dictionary/types";
2+
3+
export const generateTokenName = (
4+
token: TransformedToken,
5+
options: PlatformConfig,
6+
) => {
7+
if (token.path[0] === "spacing") {
8+
return `${options.prefix}-spacing-${token.path[1]}`;
9+
}
10+
11+
if (token.path[0] === "breakpoint") {
12+
return `${options.prefix}-breakpoint-${token.path[1]}`;
13+
}
14+
15+
const isFromColorDirectory =
16+
token.filePath && token.filePath.includes("tokens/color/");
17+
18+
if (isFromColorDirectory) {
19+
if (
20+
token.path.length === 1 &&
21+
["transparent", "black", "white"].includes(token.path[0])
22+
) {
23+
return `${options.prefix}-color-${token.path[0]}`;
24+
} else {
25+
return `${options.prefix}-color-${token.path.join("-")}`;
26+
}
27+
}
28+
29+
return `${options.prefix}-${token.path.join("-")}`;
30+
};
31+
32+
export const getTokenValueWithUnit = (token: TransformedToken) => {
33+
if (token.$type === "dimension" && typeof token.$value === "object") {
34+
return token.$value.value + (token.$value.unit || "");
35+
}
36+
return token.$value;
37+
};

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"files": [
77
".storybook",
88
"storybook",
9-
"scripts",
9+
"internals/scripts",
1010
"dist",
1111
"src"
1212
],
@@ -33,7 +33,7 @@
3333
"storybook:build": "storybook build",
3434
"storybook": "storybook dev -p 8008",
3535
"prestorybook:serve": "npm run storybook:build --quiet",
36-
"storybook:serve": "node server/index.mjs",
36+
"storybook:serve": "node internals/scripts/serve-storybook.js",
3737
"stylelint": "stylelint './src/components/**/*.{css,css.js,css.ts}'",
3838
"stylelint:fix": "stylelint './src/components/**/*.{css,css.js,css.ts}' --fix",
3939
"manifest:build": "npx cem analyze --litelement",

style-dictionary.config.js

Lines changed: 6 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,19 @@
11
import StyleDictionary from "style-dictionary";
2+
import {
3+
generateTokenName,
4+
getTokenValueWithUnit,
5+
} from "./internals/token-helpers/index.ts";
26

37
StyleDictionary.registerTransform({
48
name: "name/uswds-theme",
59
type: "name",
6-
transform: function (token, options) {
7-
if (token.path[0] === "spacing") {
8-
return `${options.prefix}-spacing-${token.path[1]}`;
9-
}
10-
11-
if (token.path[0] === "breakpoint") {
12-
return `${options.prefix}-breakpoint-${token.path[1]}`;
13-
}
14-
15-
const isFromColorDirectory =
16-
token.filePath && token.filePath.includes("tokens/color/");
17-
18-
if (isFromColorDirectory) {
19-
if (
20-
token.path.length === 1 &&
21-
["transparent", "black", "white"].includes(token.path[0])
22-
) {
23-
return `${options.prefix}-color-${token.path[0]}`;
24-
} else {
25-
return `${options.prefix}-color-${token.path.join("-")}`;
26-
}
27-
}
28-
29-
return `${options.prefix}-${token.path.join("-")}`;
30-
},
10+
transform: generateTokenName,
3111
});
3212

3313
StyleDictionary.registerTransform({
3414
name: "value/uswds-units",
3515
type: "value",
36-
transform: function (token) {
37-
if (token.$type === "dimension" && typeof token.$value === "object") {
38-
return token.$value.value + (token.$value.unit || "");
39-
}
40-
return token.$value;
41-
},
16+
transform: getTokenValueWithUnit,
4217
});
4318

4419
const outputs = [

vite.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
type Entry,
99
mapEntriesToKeyValue,
1010
mapEntryToLimit,
11-
} from "./utils/build-helpers";
11+
} from "./internals/build-helpers";
1212

1313
const entries: Array<Entry> = [
1414
{

vitest.config.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ export default defineConfig({
66
include: [
77
"src/**/*.spec.{js,ts}",
88
"src/**/*.test.{js,ts}",
9-
"utils/**/*.spec.{js,ts}",
10-
"utils/**/*.test.{js,ts}",
9+
"internals/**/*.spec.{js,ts}",
10+
"internals/**/*.test.{js,ts}",
1111
],
1212
},
1313
});

0 commit comments

Comments
 (0)