├── tests ├── customTemplate.hbs ├── scss │ ├── singleFont.scss │ └── multipleFonts.scss ├── .jshintrc ├── manual.js ├── src │ ├── triangleDown.svg │ ├── close.svg │ └── back.svg └── test.js ├── .travis.yml ├── .gitignore ├── .jshintrc ├── templates ├── css.hbs ├── scss.hbs └── html.hbs ├── src ├── renderHtml.js ├── renderCss.js ├── generateFonts.js └── index.js ├── CHANGELOG.md ├── package.json ├── LICENSE └── README.md /tests/customTemplate.hbs: -------------------------------------------------------------------------------- 1 | custom template {{option}} 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | dist: trusty 3 | language: node_js 4 | node_js: 5 | - "4" 6 | - "5" 7 | - "6" 8 | -------------------------------------------------------------------------------- /tests/scss/singleFont.scss: -------------------------------------------------------------------------------- 1 | @import '../dest/fontName'; 2 | 3 | .back { 4 | @include webfont-icon('back') 5 | } 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | lib-cov 2 | coverage 3 | node_modules 4 | temp 5 | 6 | [._]*.s[a-w][a-z] 7 | [._]s[a-w][a-z] 8 | *.un~ 9 | Session.vim 10 | .netrwhist 11 | *~ 12 | -------------------------------------------------------------------------------- /tests/scss/multipleFonts.scss: -------------------------------------------------------------------------------- 1 | @import '../dest/fontName'; 2 | @import '../dest/fontName2'; 3 | 4 | .back { 5 | @include webfont-icon('back') 6 | } 7 | 8 | .close { 9 | @include webfont-icon('close') 10 | } 11 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "indent": 2, 3 | "asi": true, 4 | "quotmark": "single", 5 | "camelcase": true, 6 | "noarg": true, 7 | "undef": true, 8 | "unused": true, 9 | "maxlen": 100, 10 | "node": true, 11 | "shadow": true 12 | } 13 | -------------------------------------------------------------------------------- /tests/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "indent": 2, 3 | "asi": true, 4 | "quotmark": "single", 5 | "camelcase": true, 6 | "noarg": true, 7 | "undef": true, 8 | "unused": true, 9 | "maxlen": 100, 10 | "node": true, 11 | "shadow": true, 12 | "predef": [ 13 | "describe", 14 | "xdescribe", 15 | "it", 16 | "xit", 17 | "beforeEach", 18 | "afterEach" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /templates/css.hbs: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: "{{fontName}}"; 3 | src: {{{src}}}; 4 | } 5 | 6 | {{baseSelector}} { 7 | line-height: 1; 8 | } 9 | 10 | {{baseSelector}}:before { 11 | font-family: {{fontName}} !important; 12 | font-style: normal; 13 | font-weight: normal !important; 14 | vertical-align: top; 15 | } 16 | 17 | {{#each codepoints}} 18 | .{{../classPrefix}}{{@key}}:before { 19 | content: "\\{{this}}"; 20 | } 21 | {{/each}} 22 | -------------------------------------------------------------------------------- /tests/manual.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs') 2 | var path = require('path') 3 | var _ = require('underscore') 4 | 5 | var webfontsGenerator = require('../src/index') 6 | 7 | var SRC = path.join(__dirname, 'src') 8 | var FILES = _.map(fs.readdirSync(SRC), function(file) { 9 | return path.join(SRC, file) 10 | }) 11 | var OPTIONS = { 12 | dest: path.join(__dirname, '..', 'temp'), 13 | files: FILES, 14 | fontName: 'fontName', 15 | types: ['svg', 'ttf', 'woff', 'woff2', 'eot'], 16 | html: true 17 | } 18 | 19 | webfontsGenerator(OPTIONS, function(error) { 20 | if (error) console.log('Fail!', error) 21 | else console.log('Done!') 22 | }) 23 | -------------------------------------------------------------------------------- /templates/scss.hbs: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: "{{fontName}}"; 3 | src: {{{src}}}; 4 | } 5 | 6 | @if not variable-exists('webfont-icons') { 7 | $webfont-icons: () !global; 8 | } 9 | 10 | $webfont-icons: map-merge($webfont-icons, ( 11 | {{#each codepoints}} 12 | '{{@key}}': ('{{../fontName}}' '{{this}}'), 13 | {{/each}} 14 | )); 15 | 16 | @mixin webfont-icon($name) { 17 | line-height: 1; 18 | 19 | $icon: map-get($webfont-icons, $name); 20 | &:before { 21 | font-family: nth($icon, 1) !important; 22 | font-style: normal; 23 | font-weight: normal !important; 24 | vertical-align: top; 25 | content: str-slice('\x', 1, 1) + nth($icon, 2); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /templates/html.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{fontName}} 6 | 30 | 31 | 32 |

{{fontName}}

33 | {{#each names}} 34 |
35 | 36 | 37 | 38 | {{this}} 39 |
40 | {{/each}} 41 | 42 | 43 | -------------------------------------------------------------------------------- /src/renderHtml.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs') 2 | var path = require('path') 3 | var _ = require('underscore') 4 | var handlebars = require('handlebars') 5 | 6 | var renderCss = require('./renderCss') 7 | 8 | handlebars.registerHelper('removePeriods', function (selector) { 9 | return selector.replace(/\./, ''); 10 | }); 11 | 12 | var renderHtml = function(options) { 13 | var source = fs.readFileSync(options.htmlTemplate, 'utf8') 14 | var template = handlebars.compile(source) 15 | 16 | var htmlFontsPath = path.relative(options.htmlDest, options.dest) 17 | // Styles embedded in the html file should use default CSS template and 18 | // have path to fonts that is relative to html file location. 19 | var styles = renderCss(_.extend({}, options, { 20 | cssFontPath: htmlFontsPath 21 | })) 22 | 23 | var ctx = _.extend({ 24 | names: options.names, 25 | fontName: options.fontName, 26 | styles: styles 27 | }, options.templateOptions) 28 | return template(ctx) 29 | } 30 | 31 | module.exports = renderHtml 32 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 0.4.0 2 | 3 | * Add woff2 support. 4 | * Update dependencies. 5 | * Deprecate baseClass in favor of a more powerful baseSelector. 6 | 7 | 0.3.4 8 | 9 | * Fix support for URLs to fonts in style files (#10). 10 | Option 'cssFontsPath' is deprecated. New option is 'cssFontsUrl'. 11 | 12 | 0.3.3 13 | 14 | * Update deps 15 | 16 | 0.3.2 17 | 18 | * Add options 'formatOptions'. 19 | 20 | 0.3.0 21 | 22 | * Add option 'writeFiles'. 23 | 24 | 0.2.4 25 | 26 | * Add hashes to font urls. 27 | * Fix backslashes in urls on Windows. 28 | 29 | 0.2.0 30 | 31 | * Option `cssTemplatePath` replaced with object `webfontsGenerator.templates` 32 | * Option `templateOptions` now extends defaults, not replaces. 33 | 34 | 0.1.2 – Added generating SCSS mixins: 35 | 36 | * Added options `cssTemplatePath` 37 | * Added SCSS template 38 | 39 | 0.1.1 – Fix bug with options.codepoints and multiple calls 40 | 41 | 0.1.0 – Added generating HTML previews: 42 | 43 | * Renamed option `cssTemplateData` to `templateOptions`. 44 | * Renamed option `destCss` to `cssDest`. 45 | * Added options `css`, `html`, `htmlTemplate`, `htmlDest`. 46 | 47 | 0.0.0 – Initial release. 48 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webfonts-generator", 3 | "version": "0.4.0", 4 | "description": "Generator of webfonts from svg icons", 5 | "main": "src/index.js", 6 | "directories": { 7 | "test": "tests" 8 | }, 9 | "scripts": { 10 | "test": "mocha tests" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/sunflowerdeath/webfonts-generator.git" 15 | }, 16 | "keywords": [ 17 | "font", 18 | "webfont", 19 | "svg", 20 | "ttf", 21 | "woff", 22 | "woff2" 23 | ], 24 | "author": "sunflowerdeath", 25 | "license": "Unlicense", 26 | "bugs": { 27 | "url": "https://github.com/sunflowerdeath/webfonts-generator/issues" 28 | }, 29 | "dependencies": { 30 | "handlebars": "^4.0.5", 31 | "mkdirp": "^0.5.0", 32 | "q": "^1.1.2", 33 | "svg2ttf": "^4.0.0", 34 | "svgicons2svgfont": "^5.0.0", 35 | "ttf2eot": "^2.0.0", 36 | "ttf2woff": "^2.0.1", 37 | "ttf2woff2": "^2.0.3", 38 | "underscore": "^1.7.0", 39 | "url-join": "^1.1.0" 40 | }, 41 | "devDependencies": { 42 | "file-type": "^3.9.0", 43 | "mocha": "^3.1.2", 44 | "node-sass": "^3.4.2", 45 | "read-chunk": "^2.0.0" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /tests/src/triangleDown.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 20 | 38 | 45 | 46 | 48 | 49 | 51 | image/svg+xml 52 | 54 | 55 | 56 | 57 | 58 | 63 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /tests/src/close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 20 | 39 | 46 | 47 | 49 | 50 | 52 | image/svg+xml 53 | 55 | 56 | 57 | 58 | 59 | 64 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /src/renderCss.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs') 2 | var path = require('path') 3 | var crypto = require('crypto') 4 | var _ = require('underscore') 5 | var handlebars = require('handlebars') 6 | var urlJoin = require('url-join') 7 | 8 | /** Caclulates hash based on options and source SVG files */ 9 | var calcHash = function(options) { 10 | var hash = crypto.createHash('md5') 11 | options.files.forEach(function(file) { 12 | hash.update(fs.readFileSync(file, 'utf8')) 13 | }) 14 | hash.update(JSON.stringify(options)) 15 | return hash.digest('hex') 16 | } 17 | 18 | var makeUrls = function(options) { 19 | var hash = calcHash(options) 20 | var baseUrl = options.cssFontsUrl && options.cssFontsUrl.replace(/\\/g, '/') 21 | var urls = _.map(options.types, function(type) { 22 | var fontName = options.fontName + '.' + type + '?' + hash 23 | return baseUrl ? urlJoin(baseUrl, fontName) : fontName 24 | }) 25 | return _.object(options.types, urls) 26 | } 27 | 28 | 29 | var makeSrc = function(options, urls) { 30 | var templates = { 31 | eot: _.template('url("<%= url %>?#iefix") format("embedded-opentype")'), 32 | woff2: _.template('url("<%= url %>") format("woff2")'), 33 | woff: _.template('url("<%= url %>") format("woff")'), 34 | ttf: _.template('url("<%= url %>") format("truetype")'), 35 | svg: _.template('url("<%= url %>#<%= fontName %>") format("svg")') 36 | } 37 | 38 | // Order used types according to 'options.order'. 39 | var orderedTypes = _.filter(options.order, function(type) { 40 | return options.types.indexOf(type) !== -1 41 | }) 42 | 43 | var src = _.map(orderedTypes, function(type) { 44 | return templates[type]({ 45 | url: urls[type], 46 | fontName: options.fontName 47 | }) 48 | }).join(',\n') 49 | 50 | return src 51 | } 52 | 53 | var makeCtx = function(options, urls) { 54 | // Transform codepoints to hex strings 55 | var codepoints = _.object(_.map(options.codepoints, function(codepoint, name) { 56 | return [name, codepoint.toString(16)] 57 | })) 58 | 59 | return _.extend({ 60 | fontName: options.fontName, 61 | src: makeSrc(options, urls), 62 | codepoints: codepoints 63 | }, options.templateOptions) 64 | } 65 | 66 | var renderCss = function(options, urls) { 67 | if (typeof urls === 'undefined') urls = makeUrls(options) 68 | var ctx = makeCtx(options, urls) 69 | var source = fs.readFileSync(options.cssTemplate, 'utf8') 70 | var template = handlebars.compile(source) 71 | return template(ctx) 72 | } 73 | 74 | module.exports = renderCss 75 | -------------------------------------------------------------------------------- /tests/src/back.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 21 | 23 | 41 | 48 | 49 | 51 | 52 | 54 | image/svg+xml 55 | 57 | 58 | 59 | 60 | 61 | 66 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /src/generateFonts.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs') 2 | var _ = require('underscore') 3 | var Q = require('q') 4 | 5 | var svgicons2svgfont = require('svgicons2svgfont') 6 | var svg2ttf = require('svg2ttf') 7 | var ttf2woff = require('ttf2woff') 8 | var ttf2woff2 = require('ttf2woff2') 9 | var ttf2eot = require('ttf2eot') 10 | 11 | /** 12 | * Generators for files of different font types. 13 | * 14 | * Generators have following properties: 15 | * [deps] {array.} Names of font types that will be generated before current 16 | * and passed to generator function. 17 | * fn {function(options, ...depsFonts, done)} Generator function with following arguments: 18 | * options {object} Options passed to 'generateFonts' function. 19 | * ...depsFonts Fonts listed in deps. 20 | * done {function(err, font)} Callback that takes error or null and generated font. 21 | */ 22 | var generators = { 23 | svg: { 24 | fn: function(options, done) { 25 | var font = new Buffer(0) 26 | var svgOptions = _.pick(options, 27 | 'fontName', 'fontHeight', 'descent', 'normalize', 'round' 28 | ) 29 | 30 | if (options.formatOptions['svg']) { 31 | svgOptions = _.extend(svgOptions, options.formatOptions['svg']) 32 | } 33 | 34 | svgOptions.log = function(){} 35 | 36 | var fontStream = svgicons2svgfont(svgOptions) 37 | .on('data', function(data) { 38 | font = Buffer.concat([font, data]) 39 | }) 40 | .on('end', function() { 41 | done(null, font.toString()) 42 | }) 43 | 44 | _.each(options.files, function(file, idx) { 45 | var glyph = fs.createReadStream(file) 46 | var name = options.names[idx] 47 | var unicode = String.fromCharCode(options.codepoints[name]) 48 | var ligature = '' 49 | for(var i=0;i` 59 | 60 | List of SVG files. 61 | 62 | ### dest 63 | 64 | *required* 65 | 66 | Type: `string` 67 | 68 | Directory for generated font files. 69 | 70 | ### fontName 71 | 72 | Type: `string` 73 |
74 | Default: `'iconfont'` 75 | 76 | Name of font and base name of font files. 77 | 78 | ### css 79 | 80 | Type: `boolean` 81 |
82 | Default: `true` 83 | 84 | Whether to generate CSS file. 85 | 86 | ### cssDest 87 | 88 | Type: `string` 89 |
90 | Default: `path.join(options.dest, options.fontName + '.css')` 91 | 92 | Path for generated CSS file. 93 | 94 | ### cssTemplate 95 | 96 | Type: `string` 97 |
98 | Default: path of default CSS template 99 | 100 | Path of custom CSS template. 101 | Generator uses handlebars templates. 102 | 103 | Template receives options from `options.templateOptions` along with the following options: 104 | 105 | * fontName 106 | * src `string` – Value of the `src` property for `@font-face`. 107 | * codepoints `object` – Codepoints of icons in hex format. 108 | 109 | Paths of default templates are stored in the `webfontsGenerator.templates` object. 110 | 111 | * `webfontsGenerator.templates.css` – Default CSS template path. 112 |
113 | It generates classes with names based on values from `options.templateOptions`. 114 | 115 | * `webfontsGenerator.templates.scss` – Default SCSS template path. 116 |
117 | It generates mixin `webfont-icon` to add icon styles. 118 |
119 | It is safe to use multiple generated files with mixins together. 120 |
121 | Example of use: 122 | 123 | ``` 124 | @import 'iconfont'; 125 | .icon { @include webfont-icon('icon'); } 126 | ``` 127 | 128 | ### cssFontsPath 129 | 130 | Type: `string` 131 |
132 | Default: `options.destCss` 133 | 134 | Fonts path used in CSS file. 135 | 136 | ### html 137 | 138 | Type: `boolean` 139 |
140 | Default: `false` 141 | 142 | Whether to generate HTML preview. 143 | 144 | ### htmlDest 145 | 146 | Type: `string` 147 |
148 | Default: `path.join(options.dest, options.fontName + '.html')` 149 | 150 | Path for generated HTML file. 151 | 152 | ### htmlTemplate 153 | 154 | Type: `string` 155 |
156 | Default: `templates/html.hbs` 157 | 158 | HTML template path. 159 | Generator uses handlebars templates. 160 | 161 | Template receives options from `options.templateOptions` along with the following options: 162 | 163 | * fontName 164 | * styles `string` – Styles generated with default CSS template. 165 | (`cssFontsPath` is chaged to relative path from `htmlDest` to `dest`) 166 | * names `array.` – Names of icons. 167 | 168 | ### templateOptions 169 | 170 | Type: `object` 171 | 172 | Additional options for CSS & HTML templates, that extends default options. 173 | 174 | Default options are: 175 | ```js 176 | { 177 | classPrefix: 'icon-', 178 | baseSelector: '.icon' 179 | } 180 | ``` 181 | 182 | ### types 183 | 184 | Type: `array` 185 |
186 | Default: `['woff2', 'woff', 'eot']` 187 | 188 | Font file types to generate. 189 | Possible values: `svg, ttf, woff, woff2, eot`. 190 | 191 | ### order 192 | 193 | Type: `array` 194 |
195 | Default: `['eot', 'woff2', 'woff', 'ttf', 'svg']` 196 | 197 | Order of `src` values in `font-face` in CSS file. 198 | 199 | ### rename 200 | 201 | Type: `function(string) -> string` 202 |
203 | Default: basename of file 204 | 205 | Function that takes path of file and return name of icon. 206 | 207 | ### startCodepoint 208 | 209 | Type: `number` 210 |
211 | Default: `0xF101` 212 | 213 | Starting codepoint. Defaults to beginning of unicode private area. 214 | 215 | ### codepoints 216 | 217 | Type: `object` 218 | 219 | Specific codepoints for certain icons. 220 | Icons without codepoints will have codepoints incremented from `startCodepoint` skipping duplicates. 221 | 222 | ### fontName, normalize, fontHeight, round, descent 223 | 224 | Options that are passed directly to 225 | [svgicons2svgfont](https://github.com/nfroidure/svgicons2svgfont). 226 | 227 | ### formatOptions 228 | 229 | Type: `object` 230 | 231 | Specific per format arbitrary options to pass to the generator 232 | 233 | format and matching generator: 234 | - `svg` - [svgicons2svgfont](https://github.com/nfroidure/svgicons2svgfont). 235 | - `ttf` - [svg2ttf](https://github.com/fontello/svg2ttf). 236 | - `woff2` - [ttf2woff2](https://github.com/nfroidure/ttf2woff2). 237 | - `woff` - [ttf2woff](https://github.com/fontello/ttf2woff). 238 | - `eot` - [ttf2eot](https://github.com/fontello/ttf2eot). 239 | 240 | ```js 241 | webfontsGenerator({ 242 | // options 243 | formatOptions: { 244 | // options to pass specifically to the ttf generator 245 | ttf: { 246 | ts: 1451512800000 247 | } 248 | } 249 | }, function(error, result) {}) 250 | ``` 251 | 252 | ### writeFiles 253 | 254 | Type: `boolean` 255 |
256 | Default: `true` 257 | 258 | It is possible to not create files and get generated fonts in object 259 | to write them to files later. 260 |
261 | Also results object will have function `generateCss([urls])` 262 | where `urls` is an object with future fonts urls. 263 | 264 | ```js 265 | webfontsGenerator({ 266 | // options 267 | writeFiles: false 268 | }, function(error, result) { 269 | // result.eot, result.ttf, etc - generated fonts 270 | // result.generateCss(urls) - function to generate css 271 | }) 272 | ``` 273 | 274 | ## License 275 | 276 | Public domain, see the `LICENCE` file. 277 | -------------------------------------------------------------------------------- /tests/test.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs') 2 | var path = require('path') 3 | var _ = require('underscore') 4 | var assert = require('assert') 5 | 6 | var sass = require('node-sass') 7 | var Q = require('q') 8 | var readChunk = require('read-chunk') 9 | var getFileType = require('file-type') 10 | 11 | var webfontsGenerator = require('../src/index') 12 | 13 | describe('webfont', function() { 14 | var SRC = path.join(__dirname, 'src') 15 | var DEST = path.join(__dirname, 'dest') 16 | 17 | var FILES = _.map(fs.readdirSync(SRC), function(file) { 18 | return path.join(SRC, file) 19 | }) 20 | 21 | var TYPES = ['ttf', 'woff', 'woff2', 'eot', 'svg'] 22 | var FONT_NAME = 'fontName' 23 | 24 | var OPTIONS = { 25 | dest: DEST, 26 | files: FILES, 27 | fontName: FONT_NAME, 28 | types: TYPES 29 | } 30 | 31 | afterEach(function() { 32 | var files = _.map(fs.readdirSync(DEST), function(file) { 33 | return path.join(DEST, file) 34 | }) 35 | for (var i in files) fs.unlinkSync(files[i]) 36 | }) 37 | 38 | it('generates all fonts and css files', function(done) { 39 | webfontsGenerator(OPTIONS, function(err) { 40 | if (err) return done(err) 41 | 42 | var destFiles = fs.readdirSync(DEST) 43 | for (var i in TYPES) { 44 | var type = TYPES[i] 45 | var filename = FONT_NAME + '.' + type 46 | var filepath = path.join(DEST, filename) 47 | assert(destFiles.indexOf(filename) !== -1, type + ' file exists') 48 | assert(fs.statSync(filepath).size > 0, type + ' file is not empty') 49 | 50 | var DETECTABLE = ['ttf', 'woff', 'woff2', 'eot'] 51 | if (_.contains(DETECTABLE, type)) { 52 | var chunk = readChunk.sync(filepath, 0, 262) 53 | var filetype = getFileType(chunk) 54 | assert.equal(type, filetype && filetype.ext, 'ttf filetype is correct') 55 | } 56 | } 57 | 58 | var cssFile = path.join(DEST, FONT_NAME + '.css') 59 | assert(fs.existsSync(cssFile), 'CSS file exists') 60 | assert(fs.statSync(cssFile).size > 0, 'CSS file is not empty') 61 | 62 | var htmlFile = path.join(DEST, FONT_NAME + '.html') 63 | assert(!fs.existsSync(htmlFile), 'HTML file does not exists by default') 64 | 65 | done(null) 66 | }) 67 | }) 68 | 69 | it('returns object with fonts and function generateCss()', function() { 70 | webfontsGenerator(OPTIONS, function(err, result) { 71 | assert(result.svg) 72 | assert(result.ttf) 73 | 74 | assert.equal(typeof result.generateCss, 'function') 75 | var css = result.generateCss() 76 | assert.equal(typeof css, 'string') 77 | }) 78 | }) 79 | 80 | it('function generateCss can change urls', function() { 81 | webfontsGenerator(OPTIONS, function(err, result) { 82 | var urls = {svg: 'AAA', ttf: 'BBB', woff: 'CCC', eot: 'DDD'} 83 | var css = result.generateCss(urls) 84 | assert(css.indexOf('AAA') !== -1) 85 | }) 86 | }) 87 | 88 | it('gives error when "dest" is undefined', function(done) { 89 | var options = _.extend({}, OPTIONS, {dest: undefined}) 90 | webfontsGenerator(options, function(err) { 91 | assert(err !== undefined) 92 | done() 93 | }) 94 | }) 95 | 96 | it('gives error when "files" is undefined', function(done) { 97 | var options = _.extend({}, OPTIONS, {files: undefined}) 98 | webfontsGenerator(options, function(err) { 99 | assert(err !== undefined) 100 | done() 101 | }) 102 | }) 103 | 104 | it('uses codepoints and startCodepoint', function(done) { 105 | var START_CODEPOINT = 0x40 106 | var CODEPOINTS = { 107 | close: 0xFF 108 | } 109 | var options = _.extend({}, OPTIONS, { 110 | codepoints: CODEPOINTS, 111 | startCodepoint: START_CODEPOINT 112 | }) 113 | webfontsGenerator(options, function(err) { 114 | if (err) return done(err) 115 | 116 | var svg = fs.readFileSync(path.join(DEST, FONT_NAME + '.svg'), 'utf8') 117 | 118 | function codepointInSvg(cp) { 119 | return svg.indexOf(cp.toString(16).toUpperCase()) !== -1 120 | } 121 | 122 | assert(codepointInSvg(START_CODEPOINT), 'startCodepoint used') 123 | assert(codepointInSvg(START_CODEPOINT+1), 'startCodepoint incremented') 124 | assert(codepointInSvg(CODEPOINTS.close), 'codepoints used') 125 | 126 | done() 127 | }) 128 | }) 129 | 130 | it('generates html file when options.html is true', function(done) { 131 | var options = _.extend({}, OPTIONS, {html: true}) 132 | webfontsGenerator(options, function(err) { 133 | if (err) return done(err) 134 | 135 | var htmlFile = path.join(DEST, FONT_NAME + '.html') 136 | assert(fs.existsSync(htmlFile), 'HTML file exists') 137 | assert(fs.statSync(htmlFile).size > 0, 'HTML file is not empty') 138 | 139 | done(null) 140 | }) 141 | }) 142 | 143 | describe('custom templates', function() { 144 | var TEMPLATE = path.join(__dirname, 'customTemplate.hbs') 145 | var TEMPLATE_OPTIONS = { 146 | option: 'TEST' 147 | } 148 | var RENDERED_TEMPLATE = 'custom template ' + TEMPLATE_OPTIONS.option + '\n' 149 | 150 | it('uses custom css template', function(done) { 151 | var options = _.extend({}, OPTIONS, { 152 | cssTemplate: TEMPLATE, 153 | templateOptions: TEMPLATE_OPTIONS 154 | }) 155 | webfontsGenerator(options, function(err) { 156 | if (err) return done(err) 157 | var cssFile = fs.readFileSync(path.join(DEST, FONT_NAME + '.css'), 'utf8') 158 | assert.equal(cssFile, RENDERED_TEMPLATE) 159 | done(null) 160 | }) 161 | }) 162 | 163 | it('uses custom html template', function(done) { 164 | var options = _.extend({}, OPTIONS, { 165 | html: true, 166 | htmlTemplate: TEMPLATE, 167 | templateOptions: TEMPLATE_OPTIONS 168 | }) 169 | webfontsGenerator(options, function(err) { 170 | if (err) return done(err) 171 | var htmlFile = fs.readFileSync(path.join(DEST, FONT_NAME + '.html'), 'utf8') 172 | assert.equal(htmlFile, RENDERED_TEMPLATE) 173 | done(null) 174 | }) 175 | }) 176 | }) 177 | 178 | describe('scss template', function() { 179 | var TEST_SCSS_SINGLE = path.join(__dirname, 'scss', 'singleFont.scss') 180 | var TEST_SCSS_MULTIPLE = path.join(__dirname, 'scss', 'multipleFonts.scss') 181 | 182 | it('creates mixins that can be used to create icons styles', function(done) { 183 | var DEST_CSS = path.join(DEST, FONT_NAME + '.scss') 184 | var options = _.extend({}, OPTIONS, { 185 | cssTemplate: webfontsGenerator.templates.scss, 186 | cssDest: DEST_CSS 187 | }) 188 | webfontsGenerator(options, function(err) { 189 | if (err) return done(new Error(err)) 190 | var rendered = sass.renderSync({ 191 | file: TEST_SCSS_SINGLE 192 | }) 193 | var css = rendered.css.toString() 194 | assert(css.indexOf(FONT_NAME) !== -1) 195 | done(null) 196 | }) 197 | }) 198 | 199 | it('multiple scss mixins can be used together', function() { 200 | var FONT_NAME_2 = FONT_NAME + '2' 201 | var DEST_CSS = path.join(DEST, FONT_NAME + '.scss') 202 | var DEST_CSS_2 = path.join(DEST, FONT_NAME_2 + '.scss') 203 | 204 | var options1 = _.extend({}, OPTIONS, { 205 | cssTemplate: webfontsGenerator.templates.scss, 206 | cssDest: DEST_CSS, 207 | files: [path.join(SRC, 'close.svg')] 208 | }) 209 | var options2 = _.extend({}, OPTIONS, { 210 | fontName: FONT_NAME_2, 211 | cssTemplate: webfontsGenerator.templates.scss, 212 | cssDest: DEST_CSS_2, 213 | files: [path.join(SRC, 'back.svg')] 214 | }) 215 | 216 | var generate1 = Q.nfcall(webfontsGenerator, options1) 217 | var generate2 = Q.nfcall(webfontsGenerator, options2) 218 | 219 | return Q.all([generate1, generate2]).then(function() { 220 | var rendered = sass.renderSync({ 221 | file: TEST_SCSS_MULTIPLE 222 | }) 223 | var css = rendered.css.toString() 224 | assert(css.indexOf(FONT_NAME) !== -1) 225 | assert(css.indexOf(FONT_NAME_2) !== -1) 226 | }) 227 | }) 228 | }) 229 | }) 230 | --------------------------------------------------------------------------------