1 | const _ = require('lodash');
|
2 | const fs = require('fs');
|
3 |
|
4 | function extractGlyphMapFromCss(files, selectorPattern) {
|
5 | const styleRulePattern =
|
6 | '(\\.[A-Za-z0-9_.:, \\n\\t-]+)\\{[^}]*content: ?["\\\'](?:\\\\([A-Fa-f0-9]+)|([^"\\\']+))["\\\'][^}]*\\}';
|
7 | const allStyleRules = new RegExp(styleRulePattern, 'g');
|
8 | const singleStyleRules = new RegExp(styleRulePattern);
|
9 | const allSelectors = new RegExp(selectorPattern, 'g');
|
10 | const singleSelector = new RegExp(selectorPattern);
|
11 |
|
12 | const extractGlyphFromRule = rule => {
|
13 | const ruleParts = rule.match(singleStyleRules);
|
14 | if (ruleParts[2]) {
|
15 |
|
16 | return parseInt(ruleParts[2], 16);
|
17 | }
|
18 | if (ruleParts[3].length > 1) {
|
19 |
|
20 | return ruleParts[3];
|
21 | }
|
22 |
|
23 | return ruleParts[3].charCodeAt();
|
24 | };
|
25 |
|
26 | const extractSelectorsFromRule = rule => {
|
27 | const ruleParts = rule.match(singleStyleRules);
|
28 | const selectors = ruleParts[1].match(allSelectors) || [];
|
29 | return selectors.map(selector => selector.match(singleSelector)[1]);
|
30 | };
|
31 |
|
32 | return (typeof files === 'string' ? [files] : files)
|
33 | .map(fileName => fs.readFileSync(fileName, { encoding: 'utf8' }))
|
34 | .map(contents => contents.match(allStyleRules) || [])
|
35 | .reduce((acc, rules) => acc.concat(rules), [])
|
36 | .map(rule => {
|
37 | const glyph = extractGlyphFromRule(rule);
|
38 | const selectors = extractSelectorsFromRule(rule);
|
39 | return selectors.map(selector => [selector, glyph]);
|
40 | })
|
41 | .reduce((acc, glyphs) => Object.assign(acc, _.fromPairs(glyphs)), {});
|
42 | }
|
43 |
|
44 | function escapeRegExp(str) {
|
45 | return str.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&');
|
46 | }
|
47 |
|
48 | function generateIconSetFromCss(cssFiles, selectorPrefix, template, data = {}) {
|
49 | const glyphMap = extractGlyphMapFromCss(
|
50 | cssFiles,
|
51 | `${escapeRegExp(selectorPrefix)}([A-Za-z0-9_-]+)::?before`
|
52 | );
|
53 | const content = JSON.stringify(glyphMap, null, ' ');
|
54 | if (template) {
|
55 | return _.template(template)({ glyphMap: content, ...data });
|
56 | }
|
57 | return content;
|
58 | }
|
59 |
|
60 | module.exports = generateIconSetFromCss;
|