summaryrefslogtreecommitdiffstats
path: root/scripts/build-theme-info.js
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/build-theme-info.js')
-rw-r--r--scripts/build-theme-info.js97
1 files changed, 97 insertions, 0 deletions
diff --git a/scripts/build-theme-info.js b/scripts/build-theme-info.js
new file mode 100644
index 000000000..4058be942
--- /dev/null
+++ b/scripts/build-theme-info.js
@@ -0,0 +1,97 @@
1/**
2 * Script to get information on which selectors use the brand color.
3 * This is needed to provide the accent color feature - the feature will create CSS rules
4 * to overwrite the color of these selectors.
5 */
6const css = require('css');
7const fs = require('fs-extra');
8const path = require('path');
9const theme = require('@meetfranz/theme');
10
11// Colors that should be replaced with the accent color
12const accentColors = [
13 theme.DEFAULT_ACCENT_COLOR.toLowerCase(),
14 '#7367f0',
15 '#5e50ee',
16];
17
18const cssFile = path.join(__dirname, '..', '..', 'build', 'styles', 'main.css');
19const outputFile = path.join(__dirname, '..', 'assets', 'themeInfo.json');
20
21// Parse and extract the rules from a CSS stylesheet file
22async function getRulesFromCssFile(file) {
23 const cssSrc = (await fs.readFile(file)).toString();
24 const cssTree = css.parse(cssSrc);
25
26 return cssTree.stylesheet.rules;
27}
28
29/**
30 * Get all selectors from a list of parsed CSS rules that set any property to one of the specified
31 * values.
32 *
33 * This function will output an object in this format:
34 * {
35 * 'property-name': [ array of selectors ]
36 * }
37 *
38 * e.g.
39 * {
40 * 'background-color': [
41 * '.background',
42 * '.input-dark'
43 * ]
44 * }
45 *
46 * @param {Array} rules Rules as outputted by the `css` module
47 * @param {Array} values Array of values that should be searched for
48 */
49function getSelectorsDeclaringValues(rules, values) {
50 const output = {};
51
52 rules.forEach((rule) => {
53 if (rule.declarations) {
54 rule.declarations.forEach((declaration) => {
55 if (declaration.type === 'declaration'
56 && values.includes(declaration.value.toLowerCase())) {
57 if (!output[declaration.property]) {
58 output[declaration.property] = [];
59 }
60 output[declaration.property] = output[declaration.property].concat(rule.selectors);
61 }
62 });
63 }
64 });
65
66 return output;
67}
68
69async function generateThemeInfo() {
70 if (!await fs.pathExists(cssFile)) {
71 console.log('Please make sure to build the project first.');
72 return;
73 }
74
75 // Read and parse css bundle
76 const rules = await getRulesFromCssFile(cssFile);
77
78 console.log(`Found ${rules.length} rules`);
79
80 // Get rules specifying the brand colors
81 const brandRules = getSelectorsDeclaringValues(rules, accentColors);
82
83 console.log(`Found ${Object.keys(brandRules).join(', ')} properties that set color to brand color`);
84
85 // Join array of declarations into a single string
86 Object.keys(brandRules).forEach((rule) => {
87 brandRules[rule] = brandRules[rule].join(', ');
88 });
89
90 // Write object with theme info to file
91 fs.writeFile(
92 outputFile,
93 JSON.stringify(brandRules),
94 );
95}
96
97generateThemeInfo();