UNPKG

generator-react-native-vector-icons

Version:

Generates React Native vector icons font library

81 lines (80 loc) 3.09 kB
import fs from 'node:fs'; import postcss from 'postcss'; import parser from 'postcss-selector-parser'; const extractGlyphMapFromCodepoints = (fileName) => { const codepoints = fs.readFileSync(fileName, { encoding: 'utf8' }).split('\n'); const glyphMap = {}; codepoints.forEach((point) => { const parts = point.split(' '); if (parts[0] && parts[1]) { glyphMap[parts[0].replace(/_/g, '-')] = Number.parseInt(parts[1], 16); } }); return glyphMap; }; const extractGlyphMapFromCss = (fileName, selectorPrefix) => { const css = fs.readFileSync(fileName, 'utf-8'); const glyphMap = {}; const selectorPattern = `${escapeRegExp(selectorPrefix)}([A-Za-z0-9_-]+)::?before`; postcss.parse(css).walkRules((rule) => { const iconNames = []; const transform = (selectors) => { selectors.walk((selector) => { const md = selector.toString().match(selectorPattern); if (md?.[1]) { iconNames.push(md[1]); } }); }; parser(transform).processSync(rule.selector); const contents = []; rule.walkDecls('content', (decl) => { const content = decl.value.replace(/['"]/g, ''); // Remove quotes contents.push(content); }); const content = contents[0]; if (!content || content === 'var(--fa)') { return; } const codePoint = Number.parseInt(content.slice(1), 16); iconNames.forEach((iconName) => { glyphMap[iconName] = codePoint; }); }); // TODO: Quick hack for fontawesome - refactor this to be more general const selectorPatternFA = `${escapeRegExp(selectorPrefix)}([A-Za-z0-9_-]+)$`; postcss.parse(css).walkRules((rule) => { const iconNames = []; const transform = (selectors) => { selectors.walk((selector) => { const md = selector.toString().match(selectorPatternFA); if (md?.[1]) { iconNames.push(md[1]); } }); }; parser(transform).processSync(rule.selector); const contents = []; rule.walkDecls('--fa', (decl) => { const content = decl.value.replace(/['"]/g, ''); // Remove quotes contents.push(content); }); const content = contents[0]; if (!content) { return; } const codePoint = Number.parseInt(content.slice(1), 16); iconNames.forEach((iconName) => { glyphMap[iconName] = codePoint; }); }); return glyphMap; }; const escapeRegExp = (str) => str.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&'); export const generateGlyphmap = (mode, fileName, selectorPrefix = '.icon-') => { if (!fileName) { throw new Error('No files provided'); } const glyphMap = mode === 'css' ? extractGlyphMapFromCss(fileName, selectorPrefix) : extractGlyphMapFromCodepoints(fileName); return JSON.stringify(glyphMap, null, ' '); };