Skip to content

Commit 3c9b071

Browse files
committed
Add a type that is an union of all the avalaible classes
1 parent 150155e commit 3c9b071

File tree

4 files changed

+123
-0
lines changed

4 files changed

+123
-0
lines changed

src/bin/css_to_ts/classNames.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { getRulesByBreakpoint } from "./breakpoints";
2+
import memoize from "memoizee";
3+
import { objectKeys } from "tsafe/objectKeys";
4+
5+
export const parseClassNames = memoize((rawCssCode: string): string[] => {
6+
const rulesByBreakpoint = getRulesByBreakpoint(rawCssCode);
7+
8+
const classes = new Set<string>();
9+
10+
objectKeys(rulesByBreakpoint).forEach(breakpoint => {
11+
const rules = rulesByBreakpoint[breakpoint];
12+
13+
rules.forEach(({ selectors }) => {
14+
selectors.forEach(selector => {
15+
const matchArr = selector.match(/^(\.fr-[a-zA-Z0-9_-]+)/);
16+
17+
if (matchArr === null) {
18+
return;
19+
}
20+
21+
classes.add(matchArr[1]);
22+
});
23+
});
24+
});
25+
26+
return Array.from(classes);
27+
});
28+
29+
export function generateClassNamesTsCode(rawCssCode: string): string {
30+
const classNames = parseClassNames(rawCssCode);
31+
32+
return [
33+
`export const frClassNames= ${JSON.stringify(classNames, null, 4)} as const;`,
34+
``,
35+
`export type FrClassName = typeof frClassNames[number];`,
36+
``
37+
].join("\n");
38+
}

src/bin/css_to_ts/css_to_ts.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { generateGetColorOptionsTsCode } from "./colorOptions";
44
import { getProjectRoot } from "../tools/getProjectRoot";
55
import { generateTypographyTsCode } from "./typography";
66
import { generateSpacingTsCode } from "./spacing";
7+
import { generateClassNamesTsCode } from "./classNames";
78
import * as fs from "fs";
89
import { join as pathJoin, basename as pathBasename, relative as pathRelative } from "path";
910

@@ -81,3 +82,8 @@ fs.writeFileSync(
8182
pathJoin(generatedDirPath, "spacing.ts"),
8283
Buffer.from([warningMessage, ``, generateSpacingTsCode(rawCssCode), ``].join("\n"), "utf8")
8384
);
85+
86+
fs.writeFileSync(
87+
pathJoin(generatedDirPath, "classNames.ts"),
88+
Buffer.from([warningMessage, ``, generateClassNamesTsCode(rawCssCode), ``].join("\n"), "utf8")
89+
);
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { it, expect } from "vitest";
2+
import { generateClassNamesTsCode } from "../../../../src/bin/css_to_ts/classNames";
3+
4+
it("Generation of TS code for fr class names", () => {
5+
const input = `
6+
.fr-text--light {
7+
font-weight: 300 !important;
8+
}
9+
10+
.fr-text--xl,
11+
.fr-text--lead {
12+
font-size: 1.25rem !important;
13+
line-height: 2rem !important;
14+
margin: var(--text-spacing);
15+
}
16+
17+
.fr-grid-row--gutters > [class^=fr-col-],
18+
.fr-grid-row--gutters > [class*=" fr-col-"],
19+
.fr-grid-row--gutters > .fr-col {
20+
padding: 0.5rem;
21+
}
22+
23+
@media (min-width: 36em) { }
24+
@media (min-width: 48em) { }
25+
@media (min-width: 62em) { }
26+
@media (min-width: 78em) { }
27+
28+
`;
29+
30+
const expected = `
31+
export const frClassNames= [
32+
".fr-text--light",
33+
".fr-text--xl",
34+
".fr-text--lead",
35+
".fr-grid-row--gutters"
36+
] as const;
37+
38+
export type FrClassName = typeof frClassNames[number];
39+
`.replace(/^\n/, "");
40+
41+
const got = generateClassNamesTsCode(input);
42+
43+
expect(got).toBe(expected);
44+
});
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { it, expect } from "vitest";
2+
import { parseClassNames } from "../../../../src/bin/css_to_ts/classNames";
3+
4+
it("Parsing of fr classnames", () => {
5+
const input = `
6+
.fr-text--light {
7+
font-weight: 300 !important;
8+
}
9+
10+
.fr-text--xl,
11+
.fr-text--lead {
12+
font-size: 1.25rem !important;
13+
line-height: 2rem !important;
14+
margin: var(--text-spacing);
15+
}
16+
17+
.fr-grid-row--gutters > [class^=fr-col-],
18+
.fr-grid-row--gutters > [class*=" fr-col-"],
19+
.fr-grid-row--gutters > .fr-col {
20+
padding: 0.5rem;
21+
}
22+
23+
@media (min-width: 36em) { }
24+
@media (min-width: 48em) { }
25+
@media (min-width: 62em) { }
26+
@media (min-width: 78em) { }
27+
28+
`;
29+
30+
const expected = [".fr-text--light", ".fr-text--xl", ".fr-text--lead", ".fr-grid-row--gutters"];
31+
32+
const got = parseClassNames(input);
33+
34+
expect(got).toStrictEqual(expected);
35+
});

0 commit comments

Comments
 (0)