Skip to content

Commit 028ab47

Browse files
committed
parseColorDecision
1 parent b84eceb commit 028ab47

File tree

4 files changed

+139
-15
lines changed

4 files changed

+139
-15
lines changed

src/bin/css_to_ts/colorDecisions.ts

Lines changed: 82 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ import { states } from "./colorOptions";
33
import { id } from "tsafe/id";
44
import { assert } from "tsafe/assert";
55
import { capitalize } from "tsafe/capitalize";
6+
import css from "css";
7+
import { exclude } from "tsafe/exclude";
8+
import { is } from "tsafe/is";
9+
import { parseColorOptionName, getThemePath as getColorOptionThemePath } from "./colorOptions";
610

711
const contexts = ["background", "text", "border", "artwork"] as const;
812

@@ -31,26 +35,26 @@ export function createParseColorDecisionName(params: {
3135

3236
function parseColorDecisionName(colorDecisionName: `--${string}`): ParsedColorDecisionName {
3337
/*
34-
colorDecisionName:
35-
--background-default-grey-hover
36-
--background-default-grey
37-
--border-action-low-orange-terre-battue
38-
--background-alt-raised-grey-hover
39-
--background-contrast-overlap-grey
40-
*/
38+
colorDecisionName:
39+
--background-default-grey-hover
40+
--background-default-grey
41+
--border-action-low-orange-terre-battue
42+
--background-alt-raised-grey-hover
43+
--background-contrast-overlap-grey
44+
*/
4145

4246
const parsedColorDecisionName: ParsedColorDecisionName = {} as any;
4347

4448
let arr = colorDecisionName.replace(/^--/, "").split("-");
4549

4650
/*
47-
arr:
48-
[ "background", "default", "grey", "hover" ]
49-
[ "background", "default", "grey" ]
50-
[ "border", "action-low", "orange", "terre", "battue"]
51-
[ "background", "alt", "raised", "grey", "hover" ]
52-
[ "background", "contrast-overlap", "grey" ]
53-
*/
51+
arr:
52+
[ "background", "default", "grey", "hover" ]
53+
[ "background", "default", "grey" ]
54+
[ "border", "action-low", "orange", "terre", "battue"]
55+
[ "background", "alt", "raised", "grey", "hover" ]
56+
[ "background", "contrast-overlap", "grey" ]
57+
*/
5458

5559
//parse context
5660
{
@@ -144,3 +148,67 @@ export function getThemePath(parsedColorDecisionName: ParsedColorDecisionName) {
144148
parsedColorDecisionName.state ?? "default"
145149
];
146150
}
151+
152+
export type ColorDecision = {
153+
themePath: string[];
154+
optionThemePath: string[];
155+
};
156+
157+
export function createParseColorDecision(params: {
158+
/** Like [ "grey", "blueFrance", ... ]
159+
* All the the color name in camel case that we deduce from Options
160+
* it help parsing without making assumption on what is a valid Usage
161+
*/
162+
colorNames: string[];
163+
/** ["--grey-1000-50-hover", "--grey-1000-50", ... ] */
164+
colorOptionNames: `--${string}`[];
165+
}) {
166+
const { colorNames, colorOptionNames } = params;
167+
168+
const { parseColorDecisionName } = createParseColorDecisionName({ colorNames });
169+
170+
function parseColorDecision(rawCssCode: string): ColorDecision[] {
171+
const parsedCss = css.parse(rawCssCode);
172+
173+
const { declarations } = (() => {
174+
const node = parsedCss.stylesheet?.rules.find(
175+
rule => rule.type === "rule" && (rule as any)?.selectors?.[0] === ":root"
176+
);
177+
178+
assert(node !== undefined);
179+
180+
const { declarations } = node as any;
181+
182+
return { declarations };
183+
})();
184+
185+
return declarations
186+
.map(({ property, value }: { property: string; value: string }) => {
187+
const mathArray = value.match(/^var\((--[^)]+)\)$/);
188+
189+
if (mathArray === null) {
190+
return undefined;
191+
}
192+
193+
const colorOptionName = mathArray[1];
194+
195+
assert(is<`--${string}`>(colorOptionName));
196+
197+
if (!id<string[]>(colorOptionNames).includes(colorOptionName)) {
198+
return undefined;
199+
}
200+
201+
assert(is<`--${string}`>(property));
202+
203+
return {
204+
"themePath": getThemePath(parseColorDecisionName(property)),
205+
"optionThemePath": getColorOptionThemePath(
206+
parseColorOptionName(colorOptionName)
207+
)
208+
};
209+
})
210+
.filter(exclude(undefined));
211+
}
212+
213+
return { parseColorDecision };
214+
}

src/bin/css_to_ts/colorOptions.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ export declare namespace ParsedColorOptionName {
4646
};
4747
}
4848

49-
/** Exported only for tests */
5049
export function parseColorOptionName(colorOptionName: `--${string}`): ParsedColorOptionName {
5150
const parsedColorOptionName: ParsedColorOptionName.Variadic = {
5251
"colorName": "",
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
import "./parseColorDecisionName.test";
2+
import "./parseColorDecision.test";
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { createParseColorDecision } from "../../../bin/css_to_ts/colorDecisions";
2+
import type { ColorDecision } from "../../../bin/css_to_ts/colorDecisions";
3+
import { assert } from "tsafe/assert";
4+
import { same } from "evt/tools/inDepth/same";
5+
6+
console.log(`Running test ${__filename}`);
7+
8+
const { parseColorDecision } = createParseColorDecision({
9+
"colorNames": ["grey", "orangeTerreBattue"],
10+
"colorOptionNames": [
11+
"--grey-1000-50-hover",
12+
"--grey-1000-50",
13+
"--orange-terre-battue-850-200",
14+
"--grey-975-100-hover",
15+
"--grey-950-150"
16+
]
17+
});
18+
19+
const rawCssCode = `
20+
:root {
21+
--background-default-grey-hover: var(--grey-1000-50-hover);
22+
--background-default-grey: var(--grey-1000-50);
23+
--border-action-low-orange-terre-battue: var(--orange-terre-battue-850-200);
24+
--background-alt-raised-grey-hover: var(--grey-975-100-hover);
25+
--background-contrast-overlap-grey: var(--grey-950-150);
26+
}
27+
`;
28+
29+
const got = parseColorDecision(rawCssCode);
30+
31+
const expected: ColorDecision[] = [
32+
{
33+
"themePath": ["background", "default", "normal", "grey", "hover"],
34+
"optionThemePath": ["grey", "_1000_50", "hover"]
35+
},
36+
{
37+
"themePath": ["background", "default", "normal", "grey", "default"],
38+
"optionThemePath": ["grey", "_1000_50", "default"]
39+
},
40+
{
41+
"themePath": ["border", "action", "low", "orangeTerreBattue", "default"],
42+
"optionThemePath": ["orangeTerreBattue", "_850_200", "default"]
43+
},
44+
{
45+
"themePath": ["background", "altRaised", "normal", "grey", "hover"],
46+
"optionThemePath": ["grey", "_975_100", "hover"]
47+
},
48+
{
49+
"themePath": ["background", "contrastOverlap", "normal", "grey", "default"],
50+
"optionThemePath": ["grey", "_950_150", "default"]
51+
}
52+
];
53+
54+
assert(same(got, expected));
55+
56+
console.log("PASS");

0 commit comments

Comments
 (0)