@hibi_10000/grunt-webfont 2.0.1 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Gruntfile.ts +370 -0
- package/{License.md → LICENSE.md} +1 -0
- package/bin/fontforge/generate.py +1 -1
- package/dist/engines/fontforge.js +10 -5
- package/dist/engines/fontforge.js.map +1 -1
- package/dist/engines/node.js +16 -13
- package/dist/engines/node.js.map +1 -1
- package/dist/package.js +3 -102
- package/dist/package.js.map +1 -1
- package/dist/types.d.ts +13 -13
- package/dist/util/util.js +15 -4
- package/dist/util/util.js.map +1 -1
- package/dist/webfont.d.ts +5 -5
- package/dist/webfont.js +76 -60
- package/dist/webfont.js.map +1 -1
- package/package.json +34 -22
- package/pnpm-workspace.yaml +4 -0
- package/tasks/engines/fontforge.ts +5 -5
- package/tasks/engines/node.ts +3 -4
- package/tasks/types.ts +14 -12
- package/tasks/util/util.ts +18 -12
- package/tasks/webfont.ts +63 -47
- package/templates/demo.html +1 -1
- package/tsconfig.json +3 -10
package/Gruntfile.ts
ADDED
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
//@ts-expect-error
|
|
3
|
+
import clean from 'grunt-contrib-clean';
|
|
4
|
+
import webfont from './tasks/webfont.ts';
|
|
5
|
+
|
|
6
|
+
import type { Configs } from './tasks/types.ts';
|
|
7
|
+
|
|
8
|
+
const config = (grunt: IGrunt) => {
|
|
9
|
+
clean(grunt);
|
|
10
|
+
|
|
11
|
+
webfont(grunt);
|
|
12
|
+
|
|
13
|
+
grunt.initConfig({
|
|
14
|
+
webfont: {
|
|
15
|
+
test1: {
|
|
16
|
+
src: 'test/src/*.svg',
|
|
17
|
+
dest: 'test/tmp/test1',
|
|
18
|
+
options: {
|
|
19
|
+
hashes: false
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
test2: {
|
|
23
|
+
src: 'test/src/*.svg',
|
|
24
|
+
dest: 'test/tmp/test2/fonts',
|
|
25
|
+
destCss: 'test/tmp/test2',
|
|
26
|
+
options: {
|
|
27
|
+
font: 'myfont',
|
|
28
|
+
types: 'woff,svg',
|
|
29
|
+
syntax: 'bootstrap'
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
embed: {
|
|
33
|
+
src: 'test/src/*.svg',
|
|
34
|
+
dest: 'test/tmp/embed',
|
|
35
|
+
options: {
|
|
36
|
+
hashes: false,
|
|
37
|
+
embed: true
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
embed_woff: {
|
|
41
|
+
src: 'test/src/*.svg',
|
|
42
|
+
dest: 'test/tmp/embed_woff',
|
|
43
|
+
options: {
|
|
44
|
+
types: 'woff',
|
|
45
|
+
hashes: false,
|
|
46
|
+
embed: true
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
embed_ttf: {
|
|
50
|
+
src: 'test/src/*.svg',
|
|
51
|
+
dest: 'test/tmp/embed_ttf',
|
|
52
|
+
options: {
|
|
53
|
+
types: 'ttf',
|
|
54
|
+
hashes: false,
|
|
55
|
+
embed: 'ttf'
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
embed_ttf_woff: {
|
|
59
|
+
src: 'test/src/*.svg',
|
|
60
|
+
dest: 'test/tmp/embed_ttf_woff',
|
|
61
|
+
options: {
|
|
62
|
+
types: 'ttf,woff',
|
|
63
|
+
hashes: false,
|
|
64
|
+
embed: 'ttf,woff'
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
one: {
|
|
68
|
+
src: 'test/src_one/*.svg',
|
|
69
|
+
dest: 'test/tmp/one',
|
|
70
|
+
options: {
|
|
71
|
+
hashes: false
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
template: {
|
|
75
|
+
src: 'test/src/*.svg',
|
|
76
|
+
dest: 'test/tmp/template',
|
|
77
|
+
options: {
|
|
78
|
+
template: 'test/templates/template.css'
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
template_scss: {
|
|
82
|
+
src: 'test/src/*.svg',
|
|
83
|
+
dest: 'test/tmp/template_scss',
|
|
84
|
+
options: {
|
|
85
|
+
stylesheet: 'scss',
|
|
86
|
+
template: 'test/templates/template.scss'
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
template_sass: {
|
|
90
|
+
src: 'test/src/*.svg',
|
|
91
|
+
dest: 'test/tmp/template_sass',
|
|
92
|
+
options: {
|
|
93
|
+
template: 'test/templates/template.sass'
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
html_template: {
|
|
97
|
+
src: 'test/src/*.svg',
|
|
98
|
+
dest: 'test/tmp/html_template',
|
|
99
|
+
options: {
|
|
100
|
+
htmlDemoTemplate: 'test/templates/template.html'
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
html_filename: {
|
|
104
|
+
src: 'test/src/*.svg',
|
|
105
|
+
dest: 'test/tmp/html_filename',
|
|
106
|
+
options: {
|
|
107
|
+
htmlDemoFilename: 'index'
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
relative_path: {
|
|
111
|
+
src: 'test/src/*.svg',
|
|
112
|
+
dest: 'test/tmp/relative_path',
|
|
113
|
+
options: {
|
|
114
|
+
relativeFontPath: '../iamrelative',
|
|
115
|
+
hashes: false
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
sass: {
|
|
119
|
+
src: 'test/src/*.svg',
|
|
120
|
+
dest: 'test/tmp/sass',
|
|
121
|
+
options: {
|
|
122
|
+
stylesheet: 'sass'
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
less: {
|
|
126
|
+
src: 'test/src/*.svg',
|
|
127
|
+
dest: 'test/tmp/less',
|
|
128
|
+
options: {
|
|
129
|
+
stylesheet: 'less'
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
css_plus_scss: {
|
|
133
|
+
src: 'test/src/*.svg',
|
|
134
|
+
dest: 'test/tmp/sass',
|
|
135
|
+
destCss: 'test/tmp/css',
|
|
136
|
+
destScss: 'test/tmp/scss',
|
|
137
|
+
options: {
|
|
138
|
+
stylesheets: ['css', 'scss']
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
stylus_bem: {
|
|
142
|
+
src: 'test/src/*.svg',
|
|
143
|
+
dest: 'test/tmp/stylus_bem',
|
|
144
|
+
options: {
|
|
145
|
+
stylesheet: 'styl'
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
stylus_bootstrap: {
|
|
149
|
+
src: 'test/src/*.svg',
|
|
150
|
+
dest: 'test/tmp/stylus_bootstrap',
|
|
151
|
+
options: {
|
|
152
|
+
stylesheet: 'styl',
|
|
153
|
+
syntax: 'bootstrap'
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
spaces: {
|
|
157
|
+
src: 'test/src_space/*.svg',
|
|
158
|
+
dest: 'test/tmp/spaces'
|
|
159
|
+
},
|
|
160
|
+
disable_demo: {
|
|
161
|
+
src: 'test/src_one/*.svg',
|
|
162
|
+
dest: 'test/tmp/disable_demo',
|
|
163
|
+
options: {
|
|
164
|
+
htmlDemo: false
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
non_css_demo: {
|
|
168
|
+
src: 'test/src/*.svg',
|
|
169
|
+
dest: 'test/tmp/non_css_demo',
|
|
170
|
+
options: {
|
|
171
|
+
stylesheet: 'less',
|
|
172
|
+
relativeFontPath: '../iamrelative',
|
|
173
|
+
htmlDemo: true
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
parent_source: {
|
|
177
|
+
src: '../grunt-webfont/test/src/*.svg',
|
|
178
|
+
dest: 'test/tmp/parent_source',
|
|
179
|
+
options: {
|
|
180
|
+
hashes: false
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
// #167: Ligatures with hyphen don’t work
|
|
184
|
+
ligatures: {
|
|
185
|
+
src: 'test/src_ligatures/*.svg',
|
|
186
|
+
dest: 'test/tmp/ligatures',
|
|
187
|
+
options: {
|
|
188
|
+
hashes: false,
|
|
189
|
+
ligatures: true
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
duplicate_names: {
|
|
193
|
+
src: '../grunt-webfont/test/src_duplicate_names/**/*.svg',
|
|
194
|
+
dest: 'test/tmp/duplicate_names',
|
|
195
|
+
options: {
|
|
196
|
+
hashes: false,
|
|
197
|
+
rename: (name) => {
|
|
198
|
+
return [path.basename(path.dirname(name)), path.basename(name)].join('-');
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
},
|
|
202
|
+
order: {
|
|
203
|
+
src: 'test/src/*.svg',
|
|
204
|
+
dest: 'test/tmp/order',
|
|
205
|
+
options: {
|
|
206
|
+
types: 'woff,svg',
|
|
207
|
+
order: 'svg,woff',
|
|
208
|
+
hashes: false
|
|
209
|
+
}
|
|
210
|
+
},
|
|
211
|
+
template_options: {
|
|
212
|
+
src: 'test/src/*.svg',
|
|
213
|
+
dest: 'test/tmp/template_options',
|
|
214
|
+
options: {
|
|
215
|
+
hashes: false,
|
|
216
|
+
syntax: 'bem',
|
|
217
|
+
stylesheet: 'less',
|
|
218
|
+
templateOptions: {
|
|
219
|
+
baseClass: 'glyph-icon',
|
|
220
|
+
classPrefix: 'glyph_'
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
},
|
|
224
|
+
node: {
|
|
225
|
+
src: 'test/src/*.svg',
|
|
226
|
+
dest: 'test/tmp/node',
|
|
227
|
+
options: {
|
|
228
|
+
hashes: false,
|
|
229
|
+
engine: 'node'
|
|
230
|
+
}
|
|
231
|
+
},
|
|
232
|
+
ie7: {
|
|
233
|
+
src: 'test/src/*.svg',
|
|
234
|
+
dest: 'test/tmp/ie7',
|
|
235
|
+
options: {
|
|
236
|
+
hashes: false,
|
|
237
|
+
ie7: true,
|
|
238
|
+
syntax: 'bem'
|
|
239
|
+
}
|
|
240
|
+
},
|
|
241
|
+
ie7_bootstrap: {
|
|
242
|
+
src: 'test/src/*.svg',
|
|
243
|
+
dest: 'test/tmp/ie7_bootstrap',
|
|
244
|
+
options: {
|
|
245
|
+
hashes: false,
|
|
246
|
+
ie7: true,
|
|
247
|
+
syntax: 'bootstrap'
|
|
248
|
+
}
|
|
249
|
+
},
|
|
250
|
+
optimize_enabled: {
|
|
251
|
+
src: 'test/src/*.svg',
|
|
252
|
+
dest: 'test/tmp/optimize_enabled',
|
|
253
|
+
options: {
|
|
254
|
+
engine: 'node',
|
|
255
|
+
types: 'svg',
|
|
256
|
+
autoHint: false,
|
|
257
|
+
optimize: true
|
|
258
|
+
}
|
|
259
|
+
},
|
|
260
|
+
optimize_disabled: {
|
|
261
|
+
src: 'test/src/*.svg',
|
|
262
|
+
dest: 'test/tmp/optimize_disabled',
|
|
263
|
+
options: {
|
|
264
|
+
engine: 'node',
|
|
265
|
+
types: 'svg',
|
|
266
|
+
autoHint: false,
|
|
267
|
+
optimize: false
|
|
268
|
+
}
|
|
269
|
+
},
|
|
270
|
+
codepoints: {
|
|
271
|
+
src: 'test/src/*.svg',
|
|
272
|
+
dest: 'test/tmp/codepoints',
|
|
273
|
+
options: {
|
|
274
|
+
types: 'svg',
|
|
275
|
+
hashes: false,
|
|
276
|
+
startCodepoint: 0x41,
|
|
277
|
+
codepoints: {
|
|
278
|
+
single: 0x43
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
},
|
|
282
|
+
camel: {
|
|
283
|
+
src: 'test/camel/*.svg',
|
|
284
|
+
dest: 'test/tmp/camel',
|
|
285
|
+
options: {
|
|
286
|
+
hashes: false
|
|
287
|
+
}
|
|
288
|
+
},
|
|
289
|
+
folders: {
|
|
290
|
+
src: 'test/src_folders/**/*.svg',
|
|
291
|
+
dest: 'test/tmp/folders',
|
|
292
|
+
options: {
|
|
293
|
+
hashes: false
|
|
294
|
+
}
|
|
295
|
+
},
|
|
296
|
+
woff2: {
|
|
297
|
+
src: 'test/src/*.svg',
|
|
298
|
+
dest: 'test/tmp/woff2',
|
|
299
|
+
options: {
|
|
300
|
+
types: 'woff2,woff'
|
|
301
|
+
}
|
|
302
|
+
},
|
|
303
|
+
woff2_node: {
|
|
304
|
+
src: 'test/src/*.svg',
|
|
305
|
+
dest: 'test/tmp/woff2_node',
|
|
306
|
+
options: {
|
|
307
|
+
types: 'woff2,woff',
|
|
308
|
+
engine: 'node'
|
|
309
|
+
}
|
|
310
|
+
},
|
|
311
|
+
target_overrides: {
|
|
312
|
+
src: 'test/src/*.svg',
|
|
313
|
+
options: {
|
|
314
|
+
dest: 'test/tmp/target_overrides_icons',
|
|
315
|
+
destCss: 'test/tmp/target_overrides_css',
|
|
316
|
+
}
|
|
317
|
+
},
|
|
318
|
+
font_family_name: {
|
|
319
|
+
src: 'test/src/*.svg',
|
|
320
|
+
dest: 'test/tmp/font_family_name',
|
|
321
|
+
options: {
|
|
322
|
+
fontFamilyName: 'customName',
|
|
323
|
+
types: 'ttf',
|
|
324
|
+
}
|
|
325
|
+
},
|
|
326
|
+
custom_output: {
|
|
327
|
+
src: 'test/src/*.svg',
|
|
328
|
+
options: {
|
|
329
|
+
dest: 'test/tmp/custom_output_icons',
|
|
330
|
+
destCss: 'test/tmp/custom_output_css',
|
|
331
|
+
customOutputs: [{
|
|
332
|
+
template: 'test/templates/custom.js',
|
|
333
|
+
dest: 'test/tmp/custom_output/test-icon-config.js'
|
|
334
|
+
}, {
|
|
335
|
+
template: 'test/templates/custom.json',
|
|
336
|
+
dest: 'test/tmp/custom_output'
|
|
337
|
+
}, {
|
|
338
|
+
template: 'test/templates/context-test.html',
|
|
339
|
+
dest: 'test/tmp/custom_output',
|
|
340
|
+
context: {
|
|
341
|
+
testHeading: 'Hello, world!'
|
|
342
|
+
}
|
|
343
|
+
}]
|
|
344
|
+
}
|
|
345
|
+
},
|
|
346
|
+
enabled_template_variables: {
|
|
347
|
+
src: 'test/src/*.svg',
|
|
348
|
+
dest: 'test/tmp/enabled_template_variables',
|
|
349
|
+
options: {
|
|
350
|
+
relativeFontPath: '../iamrelative',
|
|
351
|
+
fontPathVariables: true,
|
|
352
|
+
stylesheets: ['css', 'scss', 'less']
|
|
353
|
+
}
|
|
354
|
+
},
|
|
355
|
+
filename_length: {
|
|
356
|
+
src: 'test/src_filename_length/*.svg',
|
|
357
|
+
dest: 'test/tmp/filename_length',
|
|
358
|
+
options: {
|
|
359
|
+
autoHint: false,
|
|
360
|
+
engine: 'node',
|
|
361
|
+
hashes: false,
|
|
362
|
+
types: 'woff'
|
|
363
|
+
}
|
|
364
|
+
},
|
|
365
|
+
} satisfies Configs,
|
|
366
|
+
clean: ['test/tmp']
|
|
367
|
+
});
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
export { config as "module.exports" }
|
|
@@ -81,7 +81,7 @@ for dirname, dirnames, filenames in os.walk(args['inputDir']):
|
|
|
81
81
|
if args['round']:
|
|
82
82
|
glyph.round(int(args['round']))
|
|
83
83
|
|
|
84
|
-
fontfile = args['dest'] +
|
|
84
|
+
fontfile = args['dest'] + '/' + args['fontFilename']
|
|
85
85
|
|
|
86
86
|
f.fontname = args['fontFilename']
|
|
87
87
|
f.familyname = args['fontFamilyName']
|
|
@@ -5,8 +5,13 @@ import chalk from "chalk";
|
|
|
5
5
|
import util from "node:util";
|
|
6
6
|
import { exec } from "node:child_process";
|
|
7
7
|
import temp from "temp";
|
|
8
|
-
|
|
9
8
|
//#region tasks/engines/fontforge.ts
|
|
9
|
+
/**
|
|
10
|
+
* grunt-webfont: fontforge engine
|
|
11
|
+
*
|
|
12
|
+
* @requires fontforge, ttfautohint 1.00+ (optional), eotlitetool.py
|
|
13
|
+
* @author Artem Sapegin (http://sapegin.me), Hibi_10000
|
|
14
|
+
*/
|
|
10
15
|
var fontforge_default = async (o) => {
|
|
11
16
|
const logger = o.logger || consolaLogger;
|
|
12
17
|
temp.track();
|
|
@@ -30,7 +35,7 @@ var fontforge_default = async (o) => {
|
|
|
30
35
|
});
|
|
31
36
|
proc.on("exit", (code, signal) => {
|
|
32
37
|
if (code !== 0) logger.log.info(`fontforge process has unexpectedly closed.
|
|
33
|
-
1. Try to run grunt in verbose mode to see fontforge output: ${chalk.bold("grunt --verbose webfont")}.\n2. If stderr maxBuffer exceeded try to increase ${chalk.bold("execMaxBuffer")}, see ${chalk.underline("https://github.com/
|
|
38
|
+
1. Try to run grunt in verbose mode to see fontforge output: ${chalk.bold("grunt --verbose webfont")}.\n2. If stderr maxBuffer exceeded try to increase ${chalk.bold("execMaxBuffer")}, see ${chalk.underline("https://github.com/Hibi-10000/grunt-webfont#execMaxBuffer")}. `);
|
|
34
39
|
});
|
|
35
40
|
const params = Object.assign(o, { inputDir: tempDir });
|
|
36
41
|
proc.stdin.write(JSON.stringify(params));
|
|
@@ -40,7 +45,7 @@ var fontforge_default = async (o) => {
|
|
|
40
45
|
out = (await promise).stdout;
|
|
41
46
|
} catch (err) {
|
|
42
47
|
if (err instanceof Error && err.code === 127) {
|
|
43
|
-
logger.log.error(`fontforge not found. Please install fontforge and all other requirements: ${chalk.underline("https://github.com/
|
|
48
|
+
logger.log.error(`fontforge not found. Please install fontforge and all other requirements: ${chalk.underline("https://github.com/Hibi-10000/grunt-webfont#installation")}`);
|
|
44
49
|
return false;
|
|
45
50
|
}
|
|
46
51
|
if (err instanceof Error) {
|
|
@@ -71,14 +76,14 @@ var fontforge_default = async (o) => {
|
|
|
71
76
|
logger.log.verbose(`Webfont did not receive a proper JSON result from Python script: ${e}`);
|
|
72
77
|
logger.log.error(`Something went wrong when running fontforge. Probably fontforge wasn’t installed correctly or one of your SVGs is too complicated for fontforge.
|
|
73
78
|
|
|
74
|
-
1. Try to run Grunt in verbose mode: ${chalk.bold("grunt --verbose webfont")} and see what fontforge says. Then search GitHub issues for the solution: ${chalk.underline("https://github.com/
|
|
79
|
+
1. Try to run Grunt in verbose mode: ${chalk.bold("grunt --verbose webfont")} and see what fontforge says. Then search GitHub issues for the solution: ${chalk.underline("https://github.com/Hibi-10000/grunt-webfont/issues")}.\n\n2. Try to use “node” engine instead of “fontforge”: ${chalk.underline("https://github.com/Hibi-10000/grunt-webfont#engine")}\n\n3. To find “bad” icon try to remove SVGs one by one until error disappears. Then try to simplify this SVG in Sketch, Illustrator, etc.
|
|
75
80
|
|
|
76
81
|
`);
|
|
77
82
|
return false;
|
|
78
83
|
}
|
|
79
84
|
return { fontName: path.basename(result.file) };
|
|
80
85
|
};
|
|
81
|
-
|
|
82
86
|
//#endregion
|
|
83
87
|
export { fontforge_default as default };
|
|
88
|
+
|
|
84
89
|
//# sourceMappingURL=fontforge.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fontforge.js","names":["wf.consolaLogger","
|
|
1
|
+
{"version":3,"file":"fontforge.js","names":["wf.consolaLogger","wf.generatedFontFiles"],"sources":["../../tasks/engines/fontforge.ts"],"sourcesContent":["/**\n * grunt-webfont: fontforge engine\n *\n * @requires fontforge, ttfautohint 1.00+ (optional), eotlitetool.py\n * @author Artem Sapegin (http://sapegin.me), Hibi_10000\n */\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport util from 'node:util';\nimport { exec, type ExecException } from 'node:child_process';\nimport temp from 'temp';\nimport chalk from 'chalk';\n\nimport * as wf from '../util/util.ts';\nimport type { OptionsInternal } from '../types.ts';\n\nexport default async (o: OptionsInternal): Promise<false | { fontName: string }> => {\n\tconst logger = o.logger || wf.consolaLogger;\n\n\t// Copy source files to temporary directory\n\ttemp.track();\n\tconst tempDir = temp.mkdirSync();\n\to.files.forEach((file) => {\n\t\tfs.writeFileSync(path.join(tempDir, o.rename(file)), fs.readFileSync(file));\n\t});\n\n\t// Run Fontforge\n\tconst args = [\n\t\t'fontforge',\n\t\t'-script',\n\t\t`\"${path.join(import.meta.dirname, '../../bin/fontforge/generate.py')}\"`,\n\t].join(' ');\n\n\tconst execPromise = util.promisify(exec);\n\tconst promise = execPromise(args, { maxBuffer: o.execMaxBuffer });\n\tconst proc = promise.child;\n\n\t// Send JSON with params\n\tif (!proc) throw new TypeError('process is null');\n\n\tproc.stderr.on('data', (data) => {\n\t\tlogger.log.verbose(data);\n\t});\n\tproc.stdout.on('data', (data) => {\n\t\tlogger.log.verbose(data);\n\t});\n\tproc.on('exit', (code, signal) => {\n\t\tif (code !== 0) {\n\t\t\tlogger.log.info( // cannot use error() because it will stop execution of callback of exec (which shows error message)\n\t\t\t\t\"fontforge process has unexpectedly closed.\\n\" +\n\t\t\t\t`1. Try to run grunt in verbose mode to see fontforge output: ${chalk.bold('grunt --verbose webfont')}.\\n` +\n\t\t\t\t`2. If stderr maxBuffer exceeded try to increase ${chalk.bold('execMaxBuffer')}, ` +\n\t\t\t\t`see ${chalk.underline('https://github.com/Hibi-10000/grunt-webfont#execMaxBuffer')}. `\n\t\t\t);\n\t\t}\n\t});\n\n\tconst params = Object.assign(o, {\n\t\tinputDir: tempDir,\n\t});\n\tproc.stdin.write(JSON.stringify(params));\n\tproc.stdin.end();\n\n\tlet out: string;\n\ttry {\n\t\tout = (await promise).stdout;\n\t} catch (err: unknown) {\n\t\tif (err instanceof Error && (err as ExecException).code === 127) {\n\t\t\tlogger.log.error(`fontforge not found. Please install fontforge and all other requirements: ${chalk.underline('https://github.com/Hibi-10000/grunt-webfont#installation')}`);\n\t\t\treturn false;\n\t\t}\n\t\tif (err instanceof Error) {\n\t\t\tlogger.log.error(err.message);\n\t\t\treturn false;\n\t\t}\n\t\tlogger.log.error(`probably an impossible error`);\n\n\t\t// Skip some fontforge output such as copyrights. Show warnings only when no font files was created\n\t\t// or in verbose mode.\n\t\tconst success = !!wf.generatedFontFiles(o);\n\t\tconst notError = /(Copyright|License |with many parts BSD |Executable based on sources from|Library based on sources from|Based on source from git)/;\n\t\t//const version = /(Executable based on sources from|Library based on sources from)/;\n\t\tconst lines = (err as string).split('\\n');\n\n\t\tconst warn: string[] = [];\n\t\tlines.forEach((line) => {\n\t\t\tif (!line.match(notError) && !success) {\n\t\t\t\twarn.push(line);\n\t\t\t} else {\n\t\t\t\tlogger.log.verbose(chalk.grey('fontforge: ') + line);\n\t\t\t}\n\t\t});\n\n\t\tif (warn.length) {\n\t\t\tlogger.log.error(warn.join('\\n'));\n\t\t\treturn false;\n\t\t}\n\t\tlogger.log.error(`impossible error: ${err}`);\n\t\treturn false;\n\t}\n\n\t// Trim fontforge result\n\tconst json = out.replace(/^[^{]+/, '').replace(/[^}]+$/, '');\n\n\t// Parse json\n\tlet result: { file: string };\n\ttry {\n\t\tresult = JSON.parse(json);\n\t} catch (e) {\n\t\tlogger.log.verbose(`Webfont did not receive a proper JSON result from Python script: ${e}`);\n\t\tlogger.log.error(\n\t\t\t'Something went wrong when running fontforge. Probably fontforge wasn’t installed correctly or one of your SVGs is too complicated for fontforge.\\n\\n' +\n\t\t\t`1. Try to run Grunt in verbose mode: ${chalk.bold('grunt --verbose webfont')} and see what fontforge says. Then search GitHub issues for the solution: ${chalk.underline('https://github.com/Hibi-10000/grunt-webfont/issues')}.\\n\\n` +\n\t\t\t`2. Try to use “node” engine instead of “fontforge”: ${chalk.underline('https://github.com/Hibi-10000/grunt-webfont#engine')}\\n\\n` +\n\t\t\t'3. To find “bad” icon try to remove SVGs one by one until error disappears. Then try to simplify this SVG in Sketch, Illustrator, etc.\\n\\n'\n\t\t);\n\t\treturn false;\n\t}\n\n\treturn {\n\t\tfontName: path.basename(result.file)\n\t};\n};\n"],"mappings":";;;;;;;;;;;;;;AAiBA,IAAA,oBAAe,OAAO,MAA8D;CACnF,MAAM,SAAS,EAAE,UAAUA;CAG3B,KAAK,MAAM;CACX,MAAM,UAAU,KAAK,UAAU;CAC/B,EAAE,MAAM,SAAS,SAAS;EACzB,GAAG,cAAc,KAAK,KAAK,SAAS,EAAE,OAAO,IAAI,CAAC,GAAG,GAAG,aAAa,IAAI,CAAC;CAC3E,CAAC;CAGD,MAAM,OAAO;EACZ;EACA;EACA,IAAI,KAAK,KAAK,YAAY,SAAS,iCAAiC,EAAE;CACvE,CAAC,CAAC,KAAK,GAAG;CAGV,MAAM,UADc,KAAK,UAAU,IACT,CAAC,CAAC,MAAM,EAAE,WAAW,EAAE,cAAc,CAAC;CAChE,MAAM,OAAO,QAAQ;CAGrB,IAAI,CAAC,MAAM,MAAM,IAAI,UAAU,iBAAiB;CAEhD,KAAK,OAAO,GAAG,SAAS,SAAS;EAChC,OAAO,IAAI,QAAQ,IAAI;CACxB,CAAC;CACD,KAAK,OAAO,GAAG,SAAS,SAAS;EAChC,OAAO,IAAI,QAAQ,IAAI;CACxB,CAAC;CACD,KAAK,GAAG,SAAS,MAAM,WAAW;EACjC,IAAI,SAAS,GACZ,OAAO,IAAI,KACV;+DACgE,MAAM,KAAK,yBAAyB,EAAE,qDACnD,MAAM,KAAK,eAAe,EAAE,QACxE,MAAM,UAAU,2DAA2D,EAAE,GACrF;CAEF,CAAC;CAED,MAAM,SAAS,OAAO,OAAO,GAAG,EAC/B,UAAU,QACX,CAAC;CACD,KAAK,MAAM,MAAM,KAAK,UAAU,MAAM,CAAC;CACvC,KAAK,MAAM,IAAI;CAEf,IAAI;CACJ,IAAI;EACH,OAAO,MAAM,QAAA,CAAS;CACvB,SAAS,KAAc;EACtB,IAAI,eAAe,SAAU,IAAsB,SAAS,KAAK;GAChE,OAAO,IAAI,MAAM,6EAA6E,MAAM,UAAU,0DAA0D,GAAG;GAC3K,OAAO;EACR;EACA,IAAI,eAAe,OAAO;GACzB,OAAO,IAAI,MAAM,IAAI,OAAO;GAC5B,OAAO;EACR;EACA,OAAO,IAAI,MAAM,8BAA8B;EAI/C,MAAM,UAAU,CAAC,CAACC,mBAAsB,CAAC;EACzC,MAAM,WAAW;EAEjB,MAAM,QAAS,IAAe,MAAM,IAAI;EAExC,MAAM,OAAiB,CAAC;EACxB,MAAM,SAAS,SAAS;GACvB,IAAI,CAAC,KAAK,MAAM,QAAQ,KAAK,CAAC,SAC7B,KAAK,KAAK,IAAI;QAEd,OAAO,IAAI,QAAQ,MAAM,KAAK,aAAa,IAAI,IAAI;EAErD,CAAC;EAED,IAAI,KAAK,QAAQ;GAChB,OAAO,IAAI,MAAM,KAAK,KAAK,IAAI,CAAC;GAChC,OAAO;EACR;EACA,OAAO,IAAI,MAAM,qBAAqB,KAAK;EAC3C,OAAO;CACR;CAGA,MAAM,OAAO,IAAI,QAAQ,UAAU,EAAE,CAAC,CAAC,QAAQ,UAAU,EAAE;CAG3D,IAAI;CACJ,IAAI;EACH,SAAS,KAAK,MAAM,IAAI;CACzB,SAAS,GAAG;EACX,OAAO,IAAI,QAAQ,oEAAoE,GAAG;EAC1F,OAAO,IAAI,MACV;;uCACwC,MAAM,KAAK,yBAAyB,EAAE,4EAA4E,MAAM,UAAU,oDAAoD,EAAE,2DACzK,MAAM,UAAU,oDAAoD,EAAE;;CAE9H;EACA,OAAO;CACR;CAEA,OAAO,EACN,UAAU,KAAK,SAAS,OAAO,IAAI,EACpC;AACD"}
|
package/dist/engines/node.js
CHANGED
|
@@ -12,8 +12,13 @@ import ttf2woff from "ttf2woff";
|
|
|
12
12
|
import ttf2eot from "ttf2eot";
|
|
13
13
|
import * as svgo from "svgo";
|
|
14
14
|
import which from "which";
|
|
15
|
-
|
|
16
15
|
//#region tasks/engines/node.ts
|
|
16
|
+
/**
|
|
17
|
+
* grunt-webfont: Node.js engine
|
|
18
|
+
*
|
|
19
|
+
* @requires ttfautohint 1.00+ (optional)
|
|
20
|
+
* @author Artem Sapegin (http://sapegin.me), Hibi_10000
|
|
21
|
+
*/
|
|
17
22
|
var node_default = async (o) => {
|
|
18
23
|
const logger = o.logger || consolaLogger;
|
|
19
24
|
const fonts = {};
|
|
@@ -92,23 +97,21 @@ var node_default = async (o) => {
|
|
|
92
97
|
function svgFilesToStreams(files) {
|
|
93
98
|
try {
|
|
94
99
|
return files.map((file) => {
|
|
95
|
-
function fileStreamed(name
|
|
100
|
+
function fileStreamed(name, stream) {
|
|
96
101
|
return {
|
|
97
|
-
codepoint: o.codepoints[name
|
|
98
|
-
name
|
|
99
|
-
stream
|
|
102
|
+
codepoint: o.codepoints[name],
|
|
103
|
+
name,
|
|
104
|
+
stream
|
|
100
105
|
};
|
|
101
106
|
}
|
|
102
|
-
function streamSVG(name
|
|
103
|
-
|
|
104
|
-
return fileStreamed(name$1, stream$1);
|
|
107
|
+
function streamSVG(name, file) {
|
|
108
|
+
return fileStreamed(name, fs.createReadStream(file));
|
|
105
109
|
}
|
|
106
|
-
function streamSVGO(name
|
|
107
|
-
const svg = fs.readFileSync(file
|
|
110
|
+
function streamSVGO(name, file) {
|
|
111
|
+
const svg = fs.readFileSync(file, "utf8");
|
|
108
112
|
try {
|
|
109
113
|
const optimized = svgo.optimize(svg).data;
|
|
110
|
-
|
|
111
|
-
return fileStreamed(name$1, strStream);
|
|
114
|
+
return fileStreamed(name, stream.Readable.from(optimized));
|
|
112
115
|
} catch (err) {
|
|
113
116
|
logger.log.error("Can’t simplify SVG file with SVGO.\n\n" + err);
|
|
114
117
|
throw err;
|
|
@@ -158,7 +161,7 @@ var node_default = async (o) => {
|
|
|
158
161
|
return fs.readFileSync(hintedFilepath);
|
|
159
162
|
}
|
|
160
163
|
};
|
|
161
|
-
|
|
162
164
|
//#endregion
|
|
163
165
|
export { node_default as default };
|
|
166
|
+
|
|
164
167
|
//# sourceMappingURL=node.js.map
|
package/dist/engines/node.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node.js","names":["wf.consolaLogger","
|
|
1
|
+
{"version":3,"file":"node.js","names":["wf.consolaLogger","wf.getFontPath"],"sources":["../../tasks/engines/node.ts"],"sourcesContent":["/**\n * grunt-webfont: Node.js engine\n *\n * @requires ttfautohint 1.00+ (optional)\n * @author Artem Sapegin (http://sapegin.me), Hibi_10000\n */\n\nimport fs from 'node:fs';\nimport stream from 'node:stream';\nimport path from 'node:path';\nimport util from 'node:util';\nimport { exec, type ExecException } from 'node:child_process';\nimport { StringDecoder } from 'node:string_decoder';\nimport temp from 'temp';\nimport { SVGIcons2SVGFontStream } from 'svgicons2svgfont';\nimport svg2ttf from 'svg2ttf';\nimport ttf2woff from 'ttf2woff';\nimport ttf2eot from 'ttf2eot';\nimport * as svgo from 'svgo';\nimport which from 'which';\n\nimport * as wf from '../util/util.ts';\nimport type { OptionsInternal, ReadableStreamWithMetadata } from '../types.ts';\n\nexport default async (o: OptionsInternal): Promise<false> => {\n\tconst logger = o.logger || wf.consolaLogger;\n\n\t// @todo Ligatures\n\n\tconst fonts: { svg?: string, ttf?: Uint8Array, woff?: Uint8Array, eot?: Uint8Array } = {};\n\n\tconst generators = {\n\t\tsvg: async () => {\n\t\t\tlet font = '';\n\t\t\tconst decoder = new StringDecoder('utf8');\n\t\t\tconst streams = svgFilesToStreams(o.files);\n\t\t\tconst fontStream = new SVGIcons2SVGFontStream({\n\t\t\t\tfontName: o.fontFamilyName,\n\t\t\t\tfontHeight: o.fontHeight,\n\t\t\t\tdescent: o.descent,\n\t\t\t\tnormalize: o.normalize,\n\t\t\t\tround: o.round,\n\t\t\t});\n\t\t\tfontStream.on('data', (chunk) => {\n\t\t\t\tfont += decoder.write(chunk);\n\t\t\t});\n\t\t\tawait new Promise<void>((resolve) => {\n\t\t\t\tfontStream.on('end', () => {\n\t\t\t\t\tfonts.svg = font;\n\t\t\t\t\tresolve();\n\t\t\t\t});\n\t\t\t\tfor (const s of streams) {\n\t\t\t\t\tconst svgStream = s.stream as ReadableStreamWithMetadata;\n\t\t\t\t\tsvgStream.metadata = {\n\t\t\t\t\t\tunicode: [String.fromCodePoint(s.codepoint)],\n\t\t\t\t\t\tname: s.name,\n\t\t\t\t\t}\n\t\t\t\t\tfontStream.write(svgStream);\n\t\t\t\t}\n\t\t\t\tfontStream.end();\n\t\t\t});\n\t\t\treturn font;\n\t\t},\n\n\t\tttf: async () => {\n\t\t\tconst svgFont = await getFont('svg')\n\t\t\tlet font = svg2ttf(svgFont, {}).buffer;\n\t\t\tconst hintedFont = await autohintTtfFont(font)\n\t\t\t// ttfautohint is optional\n\t\t\tif (hintedFont) {\n\t\t\t\tfont = hintedFont;\n\t\t\t}\n\t\t\tfonts.ttf = font;\n\t\t\treturn font;\n\t\t},\n\n\t\twoff: async () => {\n\t\t\tconst ttfFont = await getFont('ttf')\n\t\t\tconst font = ttf2woff(ttfFont, {});\n\t\t\tfonts.woff = font;\n\t\t\treturn font;\n\t\t},\n\n\t\twoff2: async () => {\n\t\t\t// Will be converted from TTF later\n\t\t},\n\n\t\teot: async () => {\n\t\t\tconst ttfFont = await getFont('ttf')\n\t\t\tconst font = ttf2eot(ttfFont);\n\t\t\tfonts.eot = font;\n\t\t\treturn font;\n\t\t}\n\t};\n\n\t// Font types\n\tconst typesToGenerate = o.types.slice();\n\tif ((o.types.indexOf('woff2') !== -1) && (o.types.indexOf('ttf') === -1)) typesToGenerate.push('ttf');\n\ttry {\n\t\tfor (const type of typesToGenerate) {\n\t\t\tif (type === 'woff2') continue;\n\t\t\tawait createFontWriter(type);\n\t\t}\n\t} catch (e) {\n\t\treturn false;\n\t}\n\n\tasync function getFont(type: 'svg'): Promise<string>;\n\tasync function getFont(type: 'eot' | 'woff' | 'ttf'): Promise<Uint8Array>;\n\tasync function getFont(type: 'eot' | 'woff' | 'ttf' | 'svg'): Promise<string | Uint8Array>;\n\tasync function getFont(type: 'eot' | 'woff' | 'ttf' | 'svg') {\n\t\tif (fonts[type]) {\n\t\t\treturn fonts[type];\n\t\t} else {\n\t\t\treturn await generators[type]();\n\t\t}\n\t}\n\n\tasync function createFontWriter(type: 'eot' | 'woff' | 'ttf' | 'svg') {\n\t\tconst font = await getFont(type)\n\t\tfs.writeFileSync(wf.getFontPath(o, type), font);\n\t}\n\n\ttype Stream = { codepoint: number, name?: string, stream: NodeJS.ReadableStream };\n\tfunction svgFilesToStreams(files: string[]) {\n\t\ttry {\n\t\t\treturn files.map((file) => {\n\n\t\t\t\tfunction fileStreamed(name: string, stream: NodeJS.ReadableStream): Stream {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcodepoint: o.codepoints[name],\n\t\t\t\t\t\tname: name,\n\t\t\t\t\t\tstream: stream,\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tfunction streamSVG(name: string, file: string) {\n\t\t\t\t\tconst stream = fs.createReadStream(file);\n\t\t\t\t\treturn fileStreamed(name, stream);\n\t\t\t\t}\n\n\t\t\t\tfunction streamSVGO(name: string, file: string) {\n\t\t\t\t\tconst svg = fs.readFileSync(file, 'utf8');\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst optimized = svgo.optimize(svg).data;\n\t\t\t\t\t\tconst strStream = stream.Readable.from(optimized);\n\t\t\t\t\t\treturn fileStreamed(name, strStream);\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tlogger.log.error('Can’t simplify SVG file with SVGO.\\n\\n' + err);\n\t\t\t\t\t\tthrow err;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst idx = files.indexOf(file);\n\t\t\t\tconst name = o.glyphs[idx];\n\n\t\t\t\tif (o.optimize === true) {\n\t\t\t\t\treturn streamSVGO(name, file)\n\t\t\t\t} else {\n\t\t\t\t\treturn streamSVG(name, file);\n\t\t\t\t}\n\t\t\t});\n\t\t} catch (err) {\n\t\t\tlogger.log.error('Can’t stream SVG file.\\n\\n' + err);\n\t\t\tthrow err;\n\t\t}\n\t}\n\n\tasync function autohintTtfFont(font: Uint8Array) {\n\t\tif (!which.sync('ttfautohint', { nothrow: true })) {\n\t\t\tlogger.log.verbose('Hinting skipped, ttfautohint not found.');\n\t\t\treturn false;\n\t\t}\n\n\t\ttemp.track();\n\t\tconst tempDir = temp.mkdirSync();\n\t\tconst originalFilepath = path.join(tempDir, 'font.ttf');\n\t\tconst hintedFilepath = path.join(tempDir, 'hinted.ttf');\n\n\t\tif (!o.autoHint){\n\t\t\treturn false;\n\t\t}\n\t\t// Save original font to temporary directory\n\t\tfs.writeFileSync(originalFilepath, font);\n\n\t\t// Run ttfautohint\n\t\tconst args = [\n\t\t\t'ttfautohint',\n\t\t\t'--symbol',\n\t\t\t'--fallback-script=latn',\n\t\t\t'--windows-compatibility',\n\t\t\t'--no-info',\n\t\t\toriginalFilepath,\n\t\t\thintedFilepath\n\t\t].join(' ');\n\n\t\tconst execPromise = util.promisify(exec);\n\t\ttry {\n\t\t\tawait execPromise(args, { maxBuffer: o.execMaxBuffer });\n\t\t} catch (err) {\n\t\t\tif ((err as ExecException).code === 127) {\n\t\t\t\tlogger.log.verbose('Hinting skipped, ttfautohint not found.');\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tlogger.log.error('Can’t run ttfautohint.\\n\\n' + (err as Error).message);\n\t\t\treturn false;\n\t\t}\n\t\tconst hintedFont = fs.readFileSync(hintedFilepath);\n\t\treturn hintedFont;\n\t}\n\n};\n"],"mappings":"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"}
|