UNPKG

svgtofont

Version:

Converts SVG to TTF/EOT/WOFF/WOFF2/SVG format fonts.

216 lines 10.1 kB
/// <reference types="../src/types" /> import path from 'path'; import { fileURLToPath } from 'url'; import fs from 'fs-extra'; import image2uri from 'image2uri'; import color from 'colors-cli'; import { autoConf, merge } from 'auto-config-loader'; import { log } from './log.js'; import { generateIconsSource, generateReactIcons, generateReactNativeIcons } from './generate.js'; import { createSVG, createTTF, createEOT, createWOFF, createWOFF2, createSvgSymbol, copyTemplate, createHTML, createTypescript } from './utils.js'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); export default async (options = {}) => { const defaultOptions = merge({ dist: path.resolve(process.cwd(), 'fonts'), src: path.resolve(process.cwd(), 'svg'), startUnicode: 0xea01, svg2ttf: {}, svgicons2svgfont: { fontName: 'iconfont', }, fontName: 'iconfont', symbolNameDelimiter: '-', }, options); const data = autoConf('svgtofont', { mustExist: true, default: defaultOptions, ...options.config, }); options = merge(defaultOptions, data); const pkgPath = path.join(process.cwd(), 'package.json'); if (fs.pathExistsSync(pkgPath)) { const pkg = fs.readJSONSync(pkgPath); if (pkg.svgtofont) { const cssOptions = options.css; options = merge(options, pkg.svgtofont); if (pkg.svgtofont.css && cssOptions && typeof cssOptions === 'object') { options.css = merge(cssOptions, pkg.svgtofont.css); } } if (options.website && pkg.version) { options.website.version = pkg.version; } } if (options.log === undefined) options.log = true; log.disabled = !options.log; if (options.logger && typeof options.logger === 'function') log.logger = options.logger; options.svgicons2svgfont.fontName = options.fontName; options.classNamePrefix = options.classNamePrefix || options.fontName; const fontSizeOpt = typeof options.css !== 'boolean' && options.css.fontSize; const fontSize = typeof fontSizeOpt === 'boolean' ? (fontSizeOpt === true ? 'font-size: 16px;' : '') : `font-size: ${fontSizeOpt};`; // If you generate a font you need to generate a style. if (options.website && !options.css) options.css = true; const infoDataPath = path.resolve(options.dist, 'info.json'); try { if (options.emptyDist) { await fs.emptyDir(options.dist); } // Ensures that the directory exists. await fs.ensureDir(options.dist); const unicodeObject = await createSVG(options); let cssToVars = []; let cssString = []; let cssRootVars = []; let cssIconHtml = []; let unicodeHtml = []; let symbolHtml = []; const prefix = options.classNamePrefix || options.fontName; const infoData = {}; Object.keys(unicodeObject).forEach((name, index, self) => { if (!infoData[name]) infoData[name] = {}; const _code = unicodeObject[name]; let symbolName = options.classNamePrefix + options.symbolNameDelimiter + name; let iconPart = symbolName + '">'; let encodedCodes = _code.charCodeAt(0); if (options.useNameAsUnicode) { symbolName = name; iconPart = prefix + '">' + name; encodedCodes = _code.split('').map(x => x.charCodeAt(0)).join(';&amp;#'); } else { cssToVars.push(`$${symbolName}: "\\${encodedCodes.toString(16)}";\n`); if (options.useCSSVars) { if (index === 0) cssRootVars.push(`:root {\n`); cssRootVars.push(`--${symbolName}: "\\${encodedCodes.toString(16)}";\n`); cssString.push(`.${symbolName}:before { content: var(--${symbolName}); }\n`); if (index === self.length - 1) cssRootVars.push(`}\n`); } else { cssString.push(`.${symbolName}:before { content: "\\${encodedCodes.toString(16)}"; }\n`); } } infoData[name].encodedCode = `\\${encodedCodes.toString(16)}`; infoData[name].prefix = prefix; infoData[name].className = symbolName; infoData[name].unicode = `&#${encodedCodes};`; cssIconHtml.push(`<li class="class-icon"><i class="${iconPart}</i><p class="name">${name}</p></li>`); unicodeHtml.push(`<li class="unicode-icon"><span class="iconfont">${_code}</span><h4>${name}</h4><span class="unicode">&amp;#${encodedCodes};</span></li>`); symbolHtml.push(` <li class="symbol"> <svg class="icon" aria-hidden="true"> <use xlink:href="${options.fontName}.symbol.svg#${symbolName}"></use> </svg> <h4>${symbolName}</h4> </li> `); }); if (options.useCSSVars) { cssString = [...cssRootVars, ...cssString]; } if (options.generateInfoData) { await fs.writeJSON(infoDataPath, infoData, { spaces: 2 }); log.log(`${color.green('SUCCESS')} Created ${infoDataPath} `); } const ttf = await createTTF(options); await createEOT(options, ttf); await createWOFF(options, ttf); await createWOFF2(options, ttf); await createSvgSymbol(options); if (options.css) { const styleTemplatePath = options.styleTemplates || (!options.useNameAsUnicode ? path.resolve(__dirname, 'styles') : path.resolve(__dirname, 'ligature-styles')); await copyTemplate(styleTemplatePath, options.dist, { fontname: options.fontName, cssString: cssString.join(''), cssToVars: cssToVars.join(''), fontSize: fontSize, timestamp: new Date().getTime(), prefix, _opts: typeof options.css === 'boolean' ? {} : { ...options.css } }); } if (options.typescript) { await createTypescript({ ...options, typescript: options.typescript }); } if (options.website) { const pageName = ['font-class', 'unicode', 'symbol']; let fontClassPath = path.join(options.dist, 'index.html'); let unicodePath = path.join(options.dist, 'unicode.html'); let symbolPath = path.join(options.dist, 'symbol.html'); // setting default home page. const indexName = pageName.includes(options.website.index) ? pageName.indexOf(options.website.index) : 0; pageName.forEach((name, index) => { const _path = path.join(options.dist, indexName === index ? 'index.html' : `${name}.html`); if (name === 'font-class') fontClassPath = _path; if (name === 'unicode') unicodePath = _path; if (name === 'symbol') symbolPath = _path; }); // default template options.website.template = options.website.template || path.join(__dirname, 'website', 'index.ejs'); // template data const tempData = { meta: null, links: null, corners: null, description: null, footerInfo: null, ...options.website, fontname: options.fontName, classNamePrefix: options.classNamePrefix, _type: 'font-class', _link: `${(options.css && typeof options.css !== 'boolean' && options.css.fileName) || options.fontName}.css`, _IconHtml: cssIconHtml.join(''), _title: options.website.title || options.fontName }; // website logo if (options.website.logo && fs.pathExistsSync(options.website.logo) && path.extname(options.website.logo) === '.svg') { tempData.logo = fs.readFileSync(options.website.logo).toString(); } // website favicon if (options.website.favicon && fs.pathExistsSync(options.website.favicon)) { tempData.favicon = await image2uri(options.website.favicon); } else { tempData.favicon = ''; } const classHtmlStr = await createHTML(options.website.template, tempData); fs.outputFileSync(fontClassPath, classHtmlStr); log.log(`${color.green('SUCCESS')} Created ${fontClassPath} `); tempData._IconHtml = unicodeHtml.join(''); tempData._type = 'unicode'; const unicodeHtmlStr = await createHTML(options.website.template, tempData); fs.outputFileSync(unicodePath, unicodeHtmlStr); log.log(`${color.green('SUCCESS')} Created ${unicodePath} `); tempData._IconHtml = symbolHtml.join(''); tempData._type = 'symbol'; const symbolHtmlStr = await createHTML(options.website.template, tempData); fs.outputFileSync(symbolPath, symbolHtmlStr); log.log(`${color.green('SUCCESS')} Created ${unicodePath} `); } if (options.outSVGPath) { const outPath = await generateIconsSource(options); log.log(`${color.green('SUCCESS')} Created ${outPath} `); } if (options.outSVGReact) { const outPath = await generateReactIcons(options); log.log(`${color.green('SUCCESS')} Created React Components. `); } if (options.outSVGReactNative) { generateReactNativeIcons(options, unicodeObject); log.log(`${color.green('SUCCESS')} Created React Native Components. `); } } catch (error) { log.log('SvgToFont:CLI:ERR:', error); } }; //# sourceMappingURL=index.js.map