├── 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 |
70 |
--------------------------------------------------------------------------------
/tests/src/close.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
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 |
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 |
--------------------------------------------------------------------------------