diff --git a/lib/generate-icon-set-from-css.js b/lib/generate-icon-set-from-css.js index 399b9e6..2c5ef16 100644 --- a/lib/generate-icon-set-from-css.js +++ b/lib/generate-icon-set-from-css.js @@ -1,57 +1,55 @@ -/** - * @providesModule generateIconSetFromCss - */ -'use strict'; -var _ = require('lodash'); -var fs = require('fs'); +const _ = require('lodash'); +const fs = require('fs'); function extractGlyphMapFromCss(files, selectorPattern) { - var styleRulePattern = '(\\.[A-Za-z0-9_.:, \\n\\t-]+)\\{[^}]*content: ?["\\\'](?:\\\\([A-Fa-f0-9]+)|([^"\\\']+))["\\\'][^}]*\\}'; - var allStyleRules = new RegExp(styleRulePattern, 'g'); - var singleStyleRules = new RegExp(styleRulePattern); - var allSelectors = new RegExp(selectorPattern, 'g'); - var singleSelector = new RegExp(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); - var glyphMap = {}; - if(typeof files === 'string') { - files = [files]; - } - - files.forEach(function(fileName) { - var contents = fs.readFileSync(fileName, { encoding: 'utf8' }); - var rules = contents.match(allStyleRules); - if(rules) { - rules.forEach(function(rule) { - var ruleParts = rule.match(singleStyleRules); - var hexCharCode = ruleParts[2], actualChar = ruleParts[3]; - var charCode = hexCharCode ? parseInt(hexCharCode, 16) : (actualChar.length > 1 ? actualChar : actualChar.charCodeAt()); - var selectors = ruleParts[1].match(allSelectors); - if(selectors) { - selectors.forEach(function(selector) { - var name = selector.match(singleSelector)[1]; - glyphMap[name] = charCode; - }); - } - }); + 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]; } - }); - return glyphMap; -}; + // String value in CSS that we'll convert to a charcode + return ruleParts[3].charCodeAt(); + }; -function escapeRegExp(str) { - return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); + 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 generateIconSetFromCss(cssFiles, selectorPrefix, template, data) { - var glyphMap = extractGlyphMapFromCss(cssFiles, escapeRegExp(selectorPrefix) + '([A-Za-z0-9_-]+):before'); - var content = JSON.stringify(glyphMap, null, ' '); - if(template) { - var compiled = _.template(template); - data = data || {}; - data.glyphMap = content; - content = compiled(data); +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;