UNPKG

fontawesome-subset

Version:

Utility to create subsets for FontAwesome and FontAwesome Pro.

128 lines (127 loc) 6.49 kB
"use strict"; /** * Author: Logan Graham <loganparkergraham@gmail.com> */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.fontawesomeSubset = void 0; const fs_1 = require("fs"); const path_1 = require("path"); const mkdirp_1 = require("mkdirp"); const subset_font_1 = __importDefault(require("subset-font")); const yaml_1 = __importDefault(require("yaml")); const utils_1 = require("./utils"); const constants_1 = require("./constants"); /** * This function will take an object of glyph names and output a subset of the standard fonts optimized in size for * use on websites / external resources. * * @param subset Array or Object containing glyph / font family names. * @param outputDir Directory output generated webfonts. * @param options Object of options / tweaks for further customization. Defaults to 'Free' package. */ function fontawesomeSubset(subset, outputDir, options = {}) { const { package: packageType = "free", targetFormats = ["woff2", "sfnt"] } = options; // Maps style to actual font name / file name. const fontTypes = Object.keys(constants_1.STYLE_FONT_MAP); let packageLocation; // Check to see if the user has either free, or pro installed. try { packageLocation = require.resolve(`@fortawesome/fontawesome-${packageType}`); } catch (e) { console.error(`Unable to resolve the module '@fortawesome/fontawesome-${packageType}'. Double-check that you have your preferred fontawesome package installed as a dependency and the package type passed into the options if using Pro features.\n\n\`fontawesomeSubset(..., ..., { package: 'pro' })\``); return Promise.resolve(false); } // Check that we have at least one target format for output if (!Array.isArray(targetFormats) || targetFormats.length === 0) { console.error("One or more target formats are required. Exiting."); return Promise.resolve(false); } const fontMeta = (0, path_1.resolve)(packageLocation, "../../metadata/icons.yml"); const fontFamilyMeta = (0, path_1.resolve)(packageLocation, "../../metadata/icon-families.yml"); const fontFiles = (0, path_1.resolve)(packageLocation, "../../webfonts"); // If 'subset' is set to array, turn into object defaulted for 'solid' use (fontawesome free) if (Array.isArray(subset)) { subset = { solid: subset }; } const iconMeta = yaml_1.default.parse((0, fs_1.readFileSync)(fontMeta, "utf8")); const iconFamilyMeta = (0, fs_1.existsSync)(fontFamilyMeta) ? yaml_1.default.parse((0, fs_1.readFileSync)(fontFamilyMeta, "utf8")) : null; const entries = Object.entries(subset); const promises = []; const iconErrors = {}; for (const [key, icons] of entries) { // Skip if current font family is not found in font_map. if (fontTypes.indexOf(key) === -1) { continue; } // Bail early if icons isn't set, isn't an array, or is empty if (!Array.isArray(icons) || icons.length === 0) { continue; } const fontFamily = key; const fontFileName = constants_1.STYLE_FONT_MAP[fontFamily]; const fontFilePath = (0, path_1.resolve)(fontFiles, `./${fontFileName}.ttf`); if (!(0, fs_1.existsSync)((0, path_1.resolve)(fontFilePath))) { console.warn(`Unable to find font file for requested font style '${fontFamily}'. Skipping.`); (0, utils_1.addIconError)(iconErrors, fontFamily, icons); continue; } // Pull unicode characters from fontawesome yml, aggregating into array const unicodeCharacters = []; for (const icon of icons) { let foundIcon; if (iconFamilyMeta) { foundIcon = (0, utils_1.findIconByName)(iconFamilyMeta, icon); // Skip if the icon isn't found in our icon yaml if (!foundIcon || !(0, utils_1.iconHasStyle)(foundIcon, fontFamily, packageType)) { (0, utils_1.addIconError)(iconErrors, fontFamily, icon); continue; } } else { foundIcon = (0, utils_1.findIconByName)(iconMeta, icon); // Skip if the icon isn't found in our icon yaml if (!foundIcon || !foundIcon.styles.includes(fontFamily)) { (0, utils_1.addIconError)(iconErrors, fontFamily, icon); continue; } } const charCode = foundIcon.unicode; unicodeCharacters.push(String.fromCodePoint(parseInt(charCode, 16))); // Duotone secondary char codes are prefixed with a `10` for the secondary color if (fontFamily === "duotone") { unicodeCharacters.push(String.fromCodePoint(parseInt(`10${charCode}`, 16))); } } mkdirp_1.mkdirp.sync((0, path_1.resolve)(outputDir)); const fontData = (0, fs_1.readFileSync)(fontFilePath); const outputFile = (0, path_1.resolve)(outputDir, fontFileName); // Loop over our requested output formats, and generate our subsets for (const targetFormat of targetFormats) { promises.push((0, subset_font_1.default)(fontData, unicodeCharacters.join(" "), { targetFormat: targetFormat, }).then((data) => { (0, fs_1.writeFileSync)(`${outputFile}.${constants_1.OUTPUT_FORMAT_MAP[targetFormat]}`, data); })); } } return Promise.all(promises).then(() => { const iconErrorArray = Object.entries(iconErrors).map(([style, missing_icons]) => ({ style, missing_icons, })); if (iconErrorArray.length > 0) { console.warn(`\nOne or more icons were not found in the icon metadata. Check that the icon is available in your version, tier, and that you are requesting the correct style.`); console.table(iconErrorArray); console.warn("See https://fontawesome.com/icons/ for icons, styles, and version availability."); return false; } return true; }); } exports.fontawesomeSubset = fontawesomeSubset;