UNPKG

@sctg/fontminify

Version:

Minify font seamlessly, font subsetter, webfont (eot, woff, svg) converter.

171 lines (170 loc) 4.74 kB
/** * @file css * @author junmer eltorio */ /* eslint-env node */ import _ from "lodash"; import * as fs from "fs"; import * as path from "path"; import isTtf from "is-ttf"; import through from "through2"; import replaceExt from "replace-ext"; import { b2a } from "b3b"; import { fileURLToPath } from 'url'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); /** * listUnicode * * @param {Array} unicode unicode * @return {string} unicode string */ function listUnicode(unicode) { return unicode .map(u => { return "\\" + u.toString(16); }) .join(","); } /** * get glyf list from ttf obj * * @param {ttfObject} ttf ttfObject * @return {Object} icon obj */ function getGlyfList(ttf) { const glyfList = []; // exclude empty glyf const filtered = ttf.glyf.filter(g => { return (g.name !== ".notdef" && g.name !== ".null" && g.name !== "nonmarkingreturn" && g.unicode && g.unicode.length); }); // format glyf info filtered.forEach(g => { glyfList.push({ code: "&#x" + g.unicode[0].toString(16) + ";", codeName: listUnicode(g.unicode), name: g.name || "uni" + g.unicode[0].toString(16), }); }); return { glyfList: glyfList, }; } /** * get font family name * * @param {Object} fontInfo font info object * @param {ttfObject} ttf ttfObject * @param {Object} opts opts * @return {string} font family name */ function getFontFamily(fontInfo, ttf, opts) { let fontFamily = opts.fontFamily; // Call transform function if (typeof fontFamily === "function") { fontFamily = fontFamily(_.cloneDeep(fontInfo), ttf); } return fontFamily || ttf.name.fontFamily || fontInfo.fontFile; } /** * Transform font family name * @callback FontFamilyTransform * @param {Object} font info object * @param {ttfObject} ttf ttfObject * @return {string} font family name */ // function(fontInfo, ttfObject) { return "Font Name"; } /** * css fontmin plugin * * @param {(string|FontFamilyTransform)=} opts.fontFamily fontFamily * @return {Object} stream.Transform instance * @api public */ export default (_opts) => { const opts = _opts || {}; return through.ctor({ objectMode: true, }, function (file, enc, cb) { // check null if (file.isNull()) { cb(null, file); return; } // check stream if (file.isStream()) { cb(new Error("Streaming is not supported")); return; } // check ttf if (!isTtf(file.contents)) { cb(null, file); return; } // clone this.push(file.clone(false)); file.path = replaceExt(file.path, ".css"); const fontFile = opts.filename || path.basename(file.path, ".css"); // font data const fontInfo = { fontFile: fontFile, fontPath: "", base64: false, glyph: false, iconPrefix: "icon", local: false, }; // opts _.extend(fontInfo, opts); // ttf obj const ttfObject = file.ttfObject || { name: {}, }; // glyph if (opts.glyph && ttfObject.glyf) { _.extend(fontInfo, getGlyfList(ttfObject)); } // font family fontInfo.fontFamily = getFontFamily(fontInfo, ttfObject, opts); // rewrite font family as filename if (opts.asFileName) { fontInfo.fontFamily = fontFile; } // base64 if (opts.base64) { fontInfo.base64 = "" + "data:application/x-font-ttf;charset=utf-8;base64," + b2a(file.contents); } // local // if (fontInfo.local === true) { // fontInfo.local = fontInfo.fontFamily as string; // } // render const output = _.attempt(data => { let tpl = ""; if (opts.tpl && opts.tpl.length && fs.existsSync(opts.tpl)) { tpl = fs.readFileSync(opts.tpl).toString("utf-8"); } else { tpl = fs .readFileSync(path.resolve(__dirname, "../lib/font-face.tpl")) .toString("utf-8"); } const renderCss = _.template(tpl); return Buffer.from(renderCss(data)); }, fontInfo); if (_.isError(output)) { cb(output, file); } else { file.contents = output; cb(null, file); } }); };