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
|
/**
* Script to get information on which selectors use the brand color.
* This is needed to provide the accent color feature - the feature will create CSS rules
* to overwrite the color of these selectors.
*/
const css = require('css');
const fs = require('fs-extra');
const path = require('path');
// Colors that should be replaced with the accent color
const accentColors = [
'#7367f0',
'#7266F0',
'#5e50ee',
];
const cssFile = path.join(__dirname, '../../', 'build', 'styles', 'main.css');
const outputFile = path.join(__dirname, '../', 'assets', 'themeInfo.json');
// Parse and extract the rules from a CSS stylesheet file
async function getRulesFromCssFile(file) {
const cssSrc = (await fs.readFile(file)).toString();
const cssTree = css.parse(cssSrc);
return cssTree.stylesheet.rules;
}
/**
* Get all selectors from a list of parsed CSS rules that set any property to one of the specified
* values.
*
* This function will output an object in this format:
* {
* 'property-name': [ array of selectors ]
* }
*
* e.g.
* {
* 'background-color': [
* '.background',
* '.input-dark'
* ]
* }
*
* @param {Array} rules Rules as outputted by the `css` module
* @param {Array} values Array of values that should be searched for
*/
function getSelectorsDeclaringValues(rules, values) {
const output = {};
rules.forEach((rule) => {
if (rule.declarations) {
rule.declarations.forEach((declaration) => {
if (declaration.type === 'declaration'
&& values.includes(declaration.value.toLowerCase())) {
if (!output[declaration.property]) {
output[declaration.property] = [];
}
output[declaration.property] = output[declaration.property].concat(rule.selectors);
}
});
}
});
return output;
}
async function generateThemeInfo() {
if (!await fs.pathExists(cssFile)) {
console.log('Please make sure to build the project first.');
return;
}
// Read and parse css bundle
const rules = await getRulesFromCssFile(cssFile);
console.log(`Found ${rules.length} rules`);
// Get rules specifying the brand colors
const brandRules = getSelectorsDeclaringValues(rules, accentColors);
console.log(`Found ${Object.keys(brandRules).join(', ')} properties that set color to brand color`);
// Join array of declarations into a single string
Object.keys(brandRules).forEach((rule) => {
brandRules[rule] = brandRules[rule].join(', ');
});
// Write object with theme info to file
fs.writeFile(
outputFile,
JSON.stringify(brandRules),
);
}
generateThemeInfo();
|