60 lines
2.1 KiB
JavaScript
60 lines
2.1 KiB
JavaScript
|
const _ = require('lodash');
|
||
|
const fs = require('fs');
|
||
|
|
||
|
function extractGlyphMapFromCss(files, selectorPattern) {
|
||
|
const styleRulePattern =
|
||
|
'(\\.[A-Za-z0-9_.:, \\n\\t-]+)\\{[^}]*content: ?["\\\'](?:\\\\([A-Fa-f0-9]+)|([^"\\\']+))["\\\'][^}]*\\}';
|
||
|
const allStyleRules = new RegExp(styleRulePattern, 'g');
|
||
|
const singleStyleRules = new RegExp(styleRulePattern);
|
||
|
const allSelectors = new RegExp(selectorPattern, 'g');
|
||
|
const singleSelector = new RegExp(selectorPattern);
|
||
|
|
||
|
const extractGlyphFromRule = rule => {
|
||
|
const ruleParts = rule.match(singleStyleRules);
|
||
|
if (ruleParts[2]) {
|
||
|
// Hex value in CSS
|
||
|
return parseInt(ruleParts[2], 16);
|
||
|
} else if (ruleParts[3].length > 1) {
|
||
|
// String value in CSS that we'll keep as a string because it's not a single character
|
||
|
return ruleParts[3];
|
||
|
}
|
||
|
// String value in CSS that we'll convert to a charcode
|
||
|
return ruleParts[3].charCodeAt();
|
||
|
};
|
||
|
|
||
|
const extractSelectorsFromRule = rule => {
|
||
|
const ruleParts = rule.match(singleStyleRules);
|
||
|
const selectors = ruleParts[1].match(allSelectors) || [];
|
||
|
return selectors.map(selector => selector.match(singleSelector)[1]);
|
||
|
};
|
||
|
|
||
|
return (typeof files === 'string' ? [files] : files)
|
||
|
.map(fileName => fs.readFileSync(fileName, { encoding: 'utf8' }))
|
||
|
.map(contents => contents.match(allStyleRules) || [])
|
||
|
.reduce((acc, rules) => acc.concat(rules), [])
|
||
|
.map(rule => {
|
||
|
const glyph = extractGlyphFromRule(rule);
|
||
|
const selectors = extractSelectorsFromRule(rule);
|
||
|
return selectors.map(selector => [selector, glyph]);
|
||
|
})
|
||
|
.reduce((acc, glyphs) => Object.assign(acc, _.fromPairs(glyphs)), {});
|
||
|
}
|
||
|
|
||
|
function escapeRegExp(str) {
|
||
|
return str.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&');
|
||
|
}
|
||
|
|
||
|
function generateIconSetFromCss(cssFiles, selectorPrefix, template, data = {}) {
|
||
|
const glyphMap = extractGlyphMapFromCss(
|
||
|
cssFiles,
|
||
|
`${escapeRegExp(selectorPrefix)}([A-Za-z0-9_-]+):before`
|
||
|
);
|
||
|
const content = JSON.stringify(glyphMap, null, ' ');
|
||
|
if (template) {
|
||
|
return _.template(template)(Object.assign({ glyphMap: content }, data));
|
||
|
}
|
||
|
return content;
|
||
|
}
|
||
|
|
||
|
module.exports = generateIconSetFromCss;
|