",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/jaywcjlove/svgtofont.git"
+ },
+ "keywords": [
+ "webfont",
+ "icon",
+ "iconfont",
+ "font-face",
+ "compress",
+ "minify",
+ "font-cli",
+ "otf",
+ "ttf",
+ "woff",
+ "eot",
+ "svg",
+ "ttf2eot",
+ "ttf2woff",
+ "ttf2svg",
+ "svg2ttf",
+ "css",
+ "base64"
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "colors-cli": "^1.0.18",
+ "copy-template-dir": "^1.4.0",
+ "ejs": "^2.6.1",
+ "fs-extra": "^7.0.0",
+ "svg2ttf": "^4.1.0",
+ "svgicons2svgfont": "^9.0.3",
+ "ttf2eot": "^2.0.0",
+ "ttf2woff": "^2.0.1",
+ "ttf2woff2": "^2.0.3"
+ }
+}
diff --git a/src/index.js b/src/index.js
new file mode 100644
index 0000000..7996902
--- /dev/null
+++ b/src/index.js
@@ -0,0 +1,101 @@
+
+
+const fs = require("fs-extra");
+const path = require("path");
+require("colors-cli/toxic");
+const {
+ createSVG,
+ createTTF,
+ createEOT,
+ createWOFF,
+ createWOFF2,
+ createHTML,
+ copyTemplate
+} = require("./utils");
+
+module.exports = function create(options) {
+ if (!options) options = {};
+ options.dist = options.dist || "dist";
+ options.src = options.src || "svg";
+ options.unicodeStart = options.unicodeStart || 10000;
+ options.svg2ttf = options.svg2ttf || {};
+ options.svgicons2svgfont = options.svgicons2svgfont || {};
+ options.svgicons2svgfont.fontName = options.fontName || "iconfont";
+ options.clssaNamePrefix = options.clssaNamePrefix || options.svgicons2svgfont.fontName;
+ let dist = options.dist;
+
+ fs.emptyDirSync(dist);
+ let cssString = [];
+ let cssIconHtml = [];
+ let unicodeHtml = [];
+ const htmlPath = path.join(options.dist, "index.html");
+ const unicodeHtmlPath = path.join(options.dist, "unicode.html");
+
+ return createSVG(options)
+ .then(UnicodeObject => {
+ Object.keys(UnicodeObject).forEach(name => {
+ let _code = UnicodeObject[name];
+ let _num = _code.charCodeAt(0).toString(16);
+ cssIconHtml.push(`${name}
`);
+ unicodeHtml.push(`${_code}${name}
&#${_code.charCodeAt(0)};`);
+ cssString.push(`.${options.clssaNamePrefix}-${name}:before { content: "\\${_num}"; }\n`);
+ });
+ return createTTF(options);
+ })
+ .then(() => {
+ return createEOT(options);
+ })
+ .then(() => {
+ return createWOFF(options);
+ })
+ .then(() => {
+ return createWOFF2(options);
+ })
+ .then(() => {
+ // If you generate a font you need to generate a style.
+ if (options.website) options.css = true;
+ if (options.css) {
+ const font_temp = path.resolve(__dirname, "styles");
+ return copyTemplate(font_temp, options.dist, {
+ fontname: options.fontName,
+ cssString: cssString.join(""),
+ timestamp: new Date().getTime(),
+ prefix: options.clssaNamePrefix || options.fontName
+ });
+ }
+ })
+ .then(filePaths => {
+ // output log
+ filePaths && filePaths.length > 0 && filePaths.forEach(filePath =>
+ console.log(`${'SUCCESS'.green} Created ${filePath} `)
+ );
+ })
+ .then(() => {
+ if (options.website) {
+ options.website.template = options.website.template || path.join(__dirname, "website", "index.ejs");
+ this.tempData = { ...options.website, _fontname: options.fontName, _unicode: false, _logo: options.website.logo, _link: `${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") {
+ this.tempData._logo = fs.readFileSync(options.website.logo);
+ }
+ return createHTML({
+ outPath: options.website.template,
+ data: this.tempData
+ });
+ }
+ })
+ .then(str => str && fs.outputFileSync(htmlPath, str))
+ .then(str => console.log(`${'SUCCESS'.green} Created ${htmlPath} `))
+ .then(str => {
+ if (options.website) {
+ this.tempData._IconHtml = unicodeHtml.join();
+ this.tempData._unicode = true;
+ return createHTML({
+ outPath: options.website.template,
+ data: this.tempData
+ });
+ }
+ })
+ .then(str => str && fs.outputFileSync(unicodeHtmlPath, str))
+ .then(str => console.log(`${'SUCCESS'.green} Created ${unicodeHtmlPath} `));
+}
\ No newline at end of file
diff --git a/src/styles/_{{fontname}}.css b/src/styles/_{{fontname}}.css
new file mode 100644
index 0000000..c6f85da
--- /dev/null
+++ b/src/styles/_{{fontname}}.css
@@ -0,0 +1,18 @@
+@font-face {
+ font-family: "{{fontname}}";
+ src: url('{{fontname}}.eot?t={{timestamp}}'); /* IE9*/
+ src: url('{{fontname}}.eot?t={{timestamp}}#iefix') format('embedded-opentype'), /* IE6-IE8 */
+ url('{{fontname}}.ttf?t={{timestamp}}') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
+ url('{{fontname}}.svg?t={{timestamp}}#{{fontname}}') format('svg'); /* iOS 4.1- */
+}
+
+[class^="{{prefix}}-"], [class*=" {{prefix}}-"] {
+ font-family: '{{fontname}}' !important;
+ font-size:16px;
+ font-style:normal;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+
+{{cssString}}
\ No newline at end of file
diff --git a/src/styles/_{{fontname}}.less b/src/styles/_{{fontname}}.less
new file mode 100644
index 0000000..71bd198
--- /dev/null
+++ b/src/styles/_{{fontname}}.less
@@ -0,0 +1,18 @@
+@font-face {font-family: "{{fontname}}";
+ src: url('{{fontname}}.eot?t={{timestamp}}'); /* IE9*/
+ src: url('{{fontname}}.eot?t={{timestamp}}#iefix') format('embedded-opentype'), /* IE6-IE8 */
+ url('{{fontname}}.ttf?t={{timestamp}}') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
+ url('{{fontname}}.svg?t={{timestamp}}#{{fontname}}') format('svg'); /* iOS 4.1- */
+}
+
+[class^="{{prefix}}-"], [class*=" {{prefix}}-"] {
+ font-family: '{{fontname}}' !important;
+ font-size:16px;
+ font-style:normal;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+:global {
+{{cssString}}
+}
\ No newline at end of file
diff --git a/src/utils.js b/src/utils.js
new file mode 100644
index 0000000..43fc048
--- /dev/null
+++ b/src/utils.js
@@ -0,0 +1,177 @@
+const fs = require("fs");
+const path = require("path");
+const ejs = require("ejs");
+const SVGIcons2SVGFont = require("svgicons2svgfont");
+const copy = require("copy-template-dir");
+const ttf2eot = require('ttf2eot');
+const svg2ttf = require("svg2ttf");
+const ttf2woff = require("ttf2woff");
+const ttf2woff2 = require("ttf2woff2");
+require("colors-cli/toxic");
+
+let UnicodeObj = {};
+// Unicode Private Use Area start.
+// https://en.wikipedia.org/wiki/Private_Use_Areas
+let startUnicode = 0xea01;
+
+/*
+ * Get icon unicode
+ * @return {Array} unicode array
+ */
+function getIconUnicode(name) {
+ let unicode = String.fromCharCode(startUnicode++);
+ UnicodeObj[name] = unicode;
+ return [unicode];
+}
+/*
+ * Filter svg files
+ * @return {Array} svg files
+ */
+function filterSvgFiles(svgFolderPath) {
+ let files = fs.readdirSync(svgFolderPath, 'utf-8');
+ let svgArr = [];
+ if (!files) {
+ throw new Error(`Error! Svg folder is empty.${svgFolderPath}`);
+ }
+
+ for (let i in files) {
+ if (typeof files[i] !== 'string' || path.extname(files[i]) !== '.svg') continue;
+ if (!~svgArr.indexOf(files[i])) {
+ svgArr.push(path.join(svgFolderPath, files[i]));
+ }
+ }
+ return svgArr;
+}
+/**
+ * SVG to SVG font
+ */
+exports.createSVG = OPTIONS => {
+ number = OPTIONS.unicodeStart;
+ return new Promise((resolve, reject) => {
+ // init
+ const fontStream = new SVGIcons2SVGFont({
+ ...OPTIONS.svgicons2svgfont
+ });
+ function writeFontStream(svgPath) {
+ // file name
+ let _name = path.basename(svgPath, ".svg");
+ const glyph = fs.createReadStream(svgPath);
+ glyph.metadata = { unicode: getIconUnicode(_name), name: _name };
+ fontStream.write(glyph);
+ }
+
+ const DIST_PATH = path.join(OPTIONS.dist, OPTIONS.fontName + ".svg");
+ // Setting the font destination
+ fontStream.pipe(fs.createWriteStream(DIST_PATH)).on("finish", () => {
+ console.log(`${"SUCCESS".green} ${'SVG'.blue_bt} font successfully created! (${DIST_PATH})`);
+ resolve(UnicodeObj);
+ }).on("error", (err) => {
+ if (err) {
+ console.log(err);
+ reject(err);
+ }
+ });
+ filterSvgFiles(OPTIONS.src).forEach(svg => {
+ if (typeof svg !== "string") return false;
+ writeFontStream(svg);
+ });
+
+ // Do not forget to end the stream
+ fontStream.end();
+ });
+};
+
+/**
+ * SVG font to TTF
+ */
+exports.createTTF = OPTIONS => {
+ return new Promise((resolve, reject) => {
+ OPTIONS.svg2ttf = OPTIONS.svg2ttf || {};
+ const DIST_PATH = path.join(OPTIONS.dist, OPTIONS.fontName + ".ttf");
+ let ttf = svg2ttf(fs.readFileSync(path.join(OPTIONS.dist, OPTIONS.fontName + ".svg"), "utf8"), OPTIONS.svg2ttf);
+ ttf = this.ttf = new Buffer(ttf.buffer);
+ fs.writeFile(DIST_PATH, ttf, (err, data) => {
+ if (err) {
+ return reject(err);
+ }
+ console.log(`${"SUCCESS".green} ${"TTF".blue_bt} font successfully created! (${DIST_PATH})`);
+ resolve(data);
+ });
+ });
+};
+
+/**
+ * TTF font to EOT
+ */
+exports.createEOT = OPTIONS => {
+ return new Promise((resolve, reject) => {
+ const DIST_PATH = path.join(OPTIONS.dist, OPTIONS.fontName + '.eot');
+ const eot = new Buffer(ttf2eot(this.ttf).buffer);
+
+ fs.writeFile(DIST_PATH, eot, (err, data) => {
+ if (err) {
+ return reject(err);
+ }
+ console.log(`${"SUCCESS".green} ${"EOT".blue_bt} font successfully created! (${DIST_PATH})`);
+ resolve(data);
+ });
+ });
+};
+
+/**
+ * TTF font to WOFF
+ */
+exports.createWOFF = OPTIONS => {
+ return new Promise((resolve, reject) => {
+ const DIST_PATH = path.join(OPTIONS.dist, OPTIONS.fontName + ".woff");
+ const woff = new Buffer(ttf2woff(this.ttf).buffer);
+ fs.writeFile(DIST_PATH, woff, (err, data) => {
+ if (err) {
+ return reject(err);
+ }
+ console.log(`${"SUCCESS".green} ${"WOFF".blue_bt} font successfully created! (${DIST_PATH})`);
+ resolve(data);
+ });
+ });
+};
+
+/**
+ * TTF font to WOFF2
+ */
+exports.createWOFF2 = OPTIONS => {
+ return new Promise((resolve, reject) => {
+ const DIST_PATH = path.join(OPTIONS.dist, OPTIONS.fontName + ".woff2");
+ const woff2 = new Buffer(ttf2woff2(this.ttf).buffer);
+ fs.writeFile(DIST_PATH, woff2, (err, data) => {
+ if (err) {
+ return reject(err);
+ }
+ console.log(`${"SUCCESS".green} ${"WOFF2".blue_bt} font successfully created! (${DIST_PATH})`);
+ resolve(data);
+ });
+ });
+};
+
+/**
+ * Copy template files
+ */
+exports.copyTemplate = (inDir, outDir, vars) => {
+ return new Promise((resolve, reject) => {
+ copy(inDir, outDir, vars, (err, createdFiles) => {
+ if (err) reject(err);
+ resolve(createdFiles);
+ })
+ });
+};
+
+/**
+ * Create HTML
+ */
+exports.createHTML = ({ outPath, data = {}, options = {} }) => {
+ return new Promise((resolve, reject) => {
+ ejs.renderFile(outPath, data, options, (err, str) => {
+ if (err) reject(err);
+ resolve(str);
+ });
+ });
+};
diff --git a/src/website/index.ejs b/src/website/index.ejs
new file mode 100644
index 0000000..ae9f8bb
--- /dev/null
+++ b/src/website/index.ejs
@@ -0,0 +1,124 @@
+
+
+
+
+ <%=_title%>
+
+ <%if (meta && Object.keys(meta).length > 0) { Object.keys(meta).forEach((metaName) => { %>
+
+ <%})}%>
+ <%if(!_unicode && _link) {%>
+
+ <%}%>
+
+
+
+
+
+
+
+ <%if(links && links.length > 0) { links.forEach((linkItem, index) => {%>
+ <%-linkItem.title%><%if(links.length-1 !== index){%> · <%}%>
+ <%})}%>
+
+
+
+
+
\ No newline at end of file
diff --git a/test/index.js b/test/index.js
new file mode 100644
index 0000000..059625b
--- /dev/null
+++ b/test/index.js
@@ -0,0 +1,50 @@
+const svgtofont = require("../src");
+const path = require("path");
+const pkg = require('../package.json')
+
+const rootPath = path.resolve(process.cwd(), "test");
+
+svgtofont({
+ src: path.resolve(rootPath, "svg"), // svg path
+ dist: path.resolve(rootPath, "dist"), // output path
+ fontName: "svgtofont", // font name
+ css: true, // Create CSS files.
+ startNumber: 20000, // unicode start number
+ nodemo: true, // no demo html files
+ svgicons2svgfont: {
+ fontHeight: 1000,
+ normalize: true
+ },
+ website: {
+ title: "svgtofont",
+ // Must be a .svg format image.
+ logo: path.resolve(rootPath, "svg", "git.svg"),
+ version: pkg.version,
+ meta: {
+ description: "Converts SVG fonts to TTF/EOT/WOFF/WOFF2/SVG format.",
+ keywords: "svgtofont,TTF,EOT,WOFF,WOFF2,SVG"
+ },
+ description: ``,
+ links: [
+ {
+ title: "GitHub",
+ url: "https://github.com/jaywcjlove/svgtofont"
+ },
+ {
+ title: "Feedback",
+ url: "https://github.com/jaywcjlove/svgtofont/issues"
+ },
+ {
+ title: "Font Class",
+ url: "index.html"
+ },
+ {
+ title: "Unicode",
+ url: "unicode.html"
+ }
+ ],
+ footerInfo: `Licensed under MIT. (Yes it's free and open-sourced)`
+ }
+}).then(() => {
+ console.log("done!!!!");
+});
diff --git a/test/svg/git.svg b/test/svg/git.svg
new file mode 100644
index 0000000..27da680
--- /dev/null
+++ b/test/svg/git.svg
@@ -0,0 +1,3 @@
+