-
Notifications
You must be signed in to change notification settings - Fork 249
/
theming.mjs
98 lines (88 loc) · 3.19 KB
/
theming.mjs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import DEFAULT_THEME from "./default-theme.mjs";
import { attributizeObject } from "./module-utl.mjs";
import { has, get } from "#utl/object-util.mjs";
function matchesRE(pValue, pRE) {
const lMatchResult = pValue.match && pValue.match(pRE);
return Boolean(lMatchResult) && lMatchResult.length > 0;
}
function matchesCriterion(pModuleKey, pCriterion) {
return pModuleKey === pCriterion || matchesRE(pModuleKey, pCriterion);
}
function moduleOrDependencyMatchesCriteria(pSchemeEntry, pModule) {
return Object.keys(pSchemeEntry.criteria).every((pKey) => {
// the keys can have paths in them like {"rules[0].severity": "info"}
// To get the criterion treat that key as a string and not as a path
// eslint-disable-next-line security/detect-object-injection
const lCriterion = pSchemeEntry.criteria[pKey];
// we use a bespoke 'get' here because in the criteria you can enter
// nested keys like "rules[0].severity" : "error", and that function
// handles those for us
const lModuleKey = get(pModule, pKey);
if (!(lModuleKey || has(pModule, pKey))) {
return false;
}
if (Array.isArray(lModuleKey)) {
if (Array.isArray(lCriterion)) {
return lCriterion.some((pCriterionEntry) =>
lModuleKey.some((pModuleKeyEntry) =>
matchesCriterion(pModuleKeyEntry, pCriterionEntry),
),
);
} else {
return lModuleKey.some((pModuleKeyEntry) =>
matchesCriterion(pModuleKeyEntry, lCriterion),
);
}
}
if (Array.isArray(lCriterion)) {
return lCriterion.some((pCriterionEntry) =>
matchesCriterion(lModuleKey, pCriterionEntry),
);
}
return matchesCriterion(lModuleKey, lCriterion);
});
}
export function getThemeAttributes(pModuleOrDependency, pAttributeCriteria) {
return (pAttributeCriteria || [])
.filter((pSchemeEntry) =>
moduleOrDependencyMatchesCriteria(pSchemeEntry, pModuleOrDependency),
)
.map((pSchemeEntry) => pSchemeEntry.attributes)
.reduce((pAll, pCurrent) => ({ ...pCurrent, ...pAll }), {});
}
export function normalizeTheme(pTheme) {
let lReturnValue = structuredClone(DEFAULT_THEME);
if (pTheme) {
if (pTheme.replace) {
lReturnValue = pTheme;
} else {
lReturnValue.graph = { ...DEFAULT_THEME.graph, ...pTheme.graph };
lReturnValue.node = { ...DEFAULT_THEME.node, ...pTheme.node };
lReturnValue.edge = { ...DEFAULT_THEME.edge, ...pTheme.edge };
lReturnValue.modules = (pTheme.modules || []).concat(
DEFAULT_THEME.modules,
);
lReturnValue.dependencies = (pTheme.dependencies || []).concat(
DEFAULT_THEME.dependencies,
);
}
}
return lReturnValue;
}
export function applyTheme(pTheme) {
return (pModule) => ({
...pModule,
dependencies: pModule.dependencies
.map((pDependency) => ({
...pDependency,
themeAttrs: attributizeObject(
getThemeAttributes(pDependency, pTheme.dependencies),
),
}))
.map((pDependency) => ({
...pDependency,
hasExtraAttributes: Boolean(pDependency.rule || pDependency.themeAttrs),
})),
themeAttrs: attributizeObject(getThemeAttributes(pModule, pTheme.modules)),
});
}