@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/tasks/webfont.ts
CHANGED
|
@@ -10,42 +10,32 @@ import path from 'node:path';
|
|
|
10
10
|
import crypto from 'node:crypto';
|
|
11
11
|
import { globSync } from 'glob';
|
|
12
12
|
import chalk from 'chalk';
|
|
13
|
-
import
|
|
13
|
+
import { Eta } from 'eta';
|
|
14
14
|
import ttf2woff2 from 'ttf2woff2';
|
|
15
15
|
|
|
16
16
|
import fontforge from './engines/fontforge.ts';
|
|
17
17
|
import node from './engines/node.ts';
|
|
18
18
|
import * as wf from './util/util.ts';
|
|
19
|
-
import type { Logger, CustomOutput, TemplateOptions, Config, Options, OptionsInternal, Context } from './types.ts';
|
|
19
|
+
import type { Logger, FontFormat, CustomOutput, TemplateOptions, Config, Options, OptionsInternal, Context } from './types.ts';
|
|
20
20
|
|
|
21
21
|
import packageJson from '../package.json' with { type: "json" };
|
|
22
22
|
|
|
23
|
-
export
|
|
23
|
+
export const webfontGrunt = (grunt: IGrunt): void => {
|
|
24
24
|
grunt.registerMultiTask('webfont', 'Compile separate SVG files to webfont', function() {
|
|
25
25
|
/**
|
|
26
26
|
* Consola to Grunt logger adapter.
|
|
27
27
|
*/
|
|
28
28
|
const logger: Logger = {
|
|
29
29
|
log: {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
grunt.warn.apply(null, args);
|
|
35
|
-
},
|
|
36
|
-
info: (...args) => {
|
|
37
|
-
grunt.log.writeln.apply(null, args);
|
|
38
|
-
},
|
|
39
|
-
verbose: (...args) => {
|
|
40
|
-
grunt.log.verbose.writeln.apply(null, args);
|
|
41
|
-
},
|
|
30
|
+
error: grunt.warn,
|
|
31
|
+
warn: grunt.log.warn,
|
|
32
|
+
info: grunt.log.writeln,
|
|
33
|
+
verbose: grunt.log.verbose.writeln,
|
|
42
34
|
},
|
|
43
35
|
fail: {
|
|
44
|
-
fatal:
|
|
45
|
-
grunt.fail.fatal.apply(null, args);
|
|
46
|
-
},
|
|
36
|
+
fatal: grunt.fail.fatal,
|
|
47
37
|
},
|
|
48
|
-
};
|
|
38
|
+
} as const;
|
|
49
39
|
|
|
50
40
|
const allDone = this.async();
|
|
51
41
|
const params = this.data;
|
|
@@ -56,12 +46,31 @@ export default (grunt: IGrunt): void => {
|
|
|
56
46
|
*/
|
|
57
47
|
this.requiresConfig([this.name, this.target, 'src'].join('.'));
|
|
58
48
|
|
|
59
|
-
|
|
49
|
+
webfontMain(this.name, this.target, this.filesSrc, params, options, logger).finally(allDone);
|
|
60
50
|
});
|
|
61
51
|
};
|
|
62
52
|
|
|
63
|
-
export const webfont = async (
|
|
64
|
-
|
|
53
|
+
export const webfont = async (targetName: string, config: Config): Promise<void> => {
|
|
54
|
+
const filesSrc = globSync(config.src, { posix: true });
|
|
55
|
+
await webfontMain("webfont", targetName, filesSrc, config);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const webfontGruntCjs = (grunt: IGrunt): void => webfontGrunt(grunt);
|
|
59
|
+
Object.assign(webfontGruntCjs, {
|
|
60
|
+
default: webfontGrunt,
|
|
61
|
+
webfont: webfont,
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
export { webfontGrunt as default, webfontGruntCjs as "module.exports" };
|
|
65
|
+
|
|
66
|
+
const webfontMain = async (
|
|
67
|
+
name: string,
|
|
68
|
+
target: string,
|
|
69
|
+
filesSrc: string[],
|
|
70
|
+
params: Config,
|
|
71
|
+
options: Options = params.options ?? {},
|
|
72
|
+
logger: Logger = wf.consolaLogger,
|
|
73
|
+
): Promise<void> => {
|
|
65
74
|
const md5 = crypto.createHash('md5');
|
|
66
75
|
|
|
67
76
|
/*
|
|
@@ -110,10 +119,10 @@ export const webfont = async (name: string, target: string, filesSrc: string[],
|
|
|
110
119
|
htmlDemo: options.htmlDemo !== false,
|
|
111
120
|
htmlDemoTemplate: options.htmlDemoTemplate,
|
|
112
121
|
htmlDemoFilename: options.htmlDemoFilename,
|
|
113
|
-
styles: optionToArray(options.styles, 'font,icon'),
|
|
114
|
-
types: optionToArray(options.types, 'eot,woff,ttf'),
|
|
115
|
-
order: optionToArray(options.order, wf.fontFormats),
|
|
116
|
-
embed: options.embed === true ? ['woff'] : optionToArray(options.embed, false),
|
|
122
|
+
styles: optionToArray(options.styles, ['font', 'icon']),
|
|
123
|
+
types: optionToArray<FontFormat>(options.types, ['eot', 'woff', 'ttf']),
|
|
124
|
+
order: optionToArray<FontFormat>(options.order, wf.fontFormats),
|
|
125
|
+
embed: options.embed === true ? ['woff'] : optionToArray<FontFormat>(options.embed, false),
|
|
117
126
|
rename: options.rename || path.basename,
|
|
118
127
|
engine: options.engine || 'fontforge',
|
|
119
128
|
autoHint: options.autoHint !== false,
|
|
@@ -174,7 +183,7 @@ export const webfont = async (name: string, target: string, filesSrc: string[],
|
|
|
174
183
|
|
|
175
184
|
// Check if we need to generate font
|
|
176
185
|
const previousHash = readHash(name, target);
|
|
177
|
-
logger.log.verbose(
|
|
186
|
+
logger.log.verbose(`New hash: ${o.hash} - previous hash: ${previousHash}`);
|
|
178
187
|
if (o.hash === previousHash) {
|
|
179
188
|
logger.log.verbose('Config and source files weren’t changed since last run, checking resulting files...');
|
|
180
189
|
let regenerationNeeded = false;
|
|
@@ -191,7 +200,7 @@ export const webfont = async (name: string, target: string, filesSrc: string[],
|
|
|
191
200
|
regenerationNeeded = generatedFiles.some((filename) => {
|
|
192
201
|
if (!filename) return false;
|
|
193
202
|
if (!fs.existsSync(filename)) {
|
|
194
|
-
logger.log.verbose(
|
|
203
|
+
logger.log.verbose(`File ${filename} is missed.`);
|
|
195
204
|
return true;
|
|
196
205
|
}
|
|
197
206
|
return false;
|
|
@@ -347,8 +356,8 @@ export const webfont = async (name: string, target: string, filesSrc: string[],
|
|
|
347
356
|
o.relativeFontPath = normalizePath(o.relativeFontPath);
|
|
348
357
|
|
|
349
358
|
// Generate font URLs to use in @font-face
|
|
350
|
-
const fontSrcs: { 0: string[], 1: string[] } = { 0: [], 1: [] };
|
|
351
|
-
o.order.forEach((type
|
|
359
|
+
const fontSrcs: { readonly 0: string[], readonly 1: string[] } = { 0: [], 1: [] };
|
|
360
|
+
o.order.forEach((type) => {
|
|
352
361
|
if (!has(o.types, type)) return;
|
|
353
362
|
const fontSrc1 = wf.fontsSrcsMap[type][0];
|
|
354
363
|
if (fontSrc1) fontSrcs[0].push(generateFontSrc(type, fontSrc1, stylesheet));
|
|
@@ -411,7 +420,7 @@ export const webfont = async (name: string, target: string, filesSrc: string[],
|
|
|
411
420
|
fs.writeFileSync(o.codepointsFile, codepointsToString);
|
|
412
421
|
logger.log.verbose(`Codepoints saved to file "${o.codepointsFile}".`);
|
|
413
422
|
} catch (err) {
|
|
414
|
-
logger.log.error(err.message);
|
|
423
|
+
logger.log.error((err as Error).message);
|
|
415
424
|
}
|
|
416
425
|
}
|
|
417
426
|
|
|
@@ -431,10 +440,10 @@ export const webfont = async (name: string, target: string, filesSrc: string[],
|
|
|
431
440
|
|
|
432
441
|
let context = prepareBaseTemplateContext();
|
|
433
442
|
|
|
434
|
-
let htmlStyles;
|
|
443
|
+
let htmlStyles: string;
|
|
435
444
|
|
|
436
445
|
// Prepare relative font paths for injection into @font-face refs in HTML
|
|
437
|
-
const relativeRe = new RegExp(
|
|
446
|
+
const relativeRe = new RegExp(o.relativeFontPath.replace(/[\\^$.*+?()[\]{}|]/g, '\\$&').replace(/[=!:\/]/g, '\\$&'), 'g');
|
|
438
447
|
const htmlRelativeFontPath = normalizePath(path.relative(o.destHtml, o.dest));
|
|
439
448
|
const _fontSrc1 = o.fontSrc1.replace(relativeRe, htmlRelativeFontPath);
|
|
440
449
|
const _fontSrc2 = o.fontSrc2.replace(relativeRe, htmlRelativeFontPath);
|
|
@@ -483,9 +492,9 @@ export const webfont = async (name: string, target: string, filesSrc: string[],
|
|
|
483
492
|
// Prepares config attributes related to destination filepath
|
|
484
493
|
const dest = outputConfig.dest || o.dest;
|
|
485
494
|
|
|
486
|
-
let filepath;
|
|
487
|
-
let destParent;
|
|
488
|
-
let destName;
|
|
495
|
+
let filepath: string;
|
|
496
|
+
let destParent: string;
|
|
497
|
+
let destName: string;
|
|
489
498
|
|
|
490
499
|
if (path.extname(dest) === '') {
|
|
491
500
|
// If user specifies a directory, filename should be same as template
|
|
@@ -533,7 +542,7 @@ export const webfont = async (name: string, target: string, filesSrc: string[],
|
|
|
533
542
|
await fs.promises.mkdir(getDemoPath(), { recursive: true });
|
|
534
543
|
} catch (err) {
|
|
535
544
|
if (err) {
|
|
536
|
-
logger.log.info(err);
|
|
545
|
+
logger.log.info(err as string);
|
|
537
546
|
return;
|
|
538
547
|
}
|
|
539
548
|
}
|
|
@@ -560,9 +569,9 @@ export const webfont = async (name: string, target: string, filesSrc: string[],
|
|
|
560
569
|
* @param val Input string
|
|
561
570
|
* @param defVal Default value
|
|
562
571
|
*/
|
|
563
|
-
function optionToArray(val: string | false, defVal:
|
|
572
|
+
function optionToArray<T extends string>(val: string | false, defVal: T[] | false): T[] {
|
|
564
573
|
if (val === undefined) {
|
|
565
|
-
|
|
574
|
+
return defVal || [];
|
|
566
575
|
}
|
|
567
576
|
if (!val) {
|
|
568
577
|
return [];
|
|
@@ -570,7 +579,7 @@ export const webfont = async (name: string, target: string, filesSrc: string[],
|
|
|
570
579
|
if (typeof val !== 'string') {
|
|
571
580
|
return val;
|
|
572
581
|
}
|
|
573
|
-
return val.split(',').map((value) => value.trim());
|
|
582
|
+
return val.split(',').map((value) => value.trim() as T);
|
|
574
583
|
}
|
|
575
584
|
|
|
576
585
|
/**
|
|
@@ -580,7 +589,7 @@ export const webfont = async (name: string, target: string, filesSrc: string[],
|
|
|
580
589
|
* @param needle Value to find
|
|
581
590
|
* @return Needle was found
|
|
582
591
|
*/
|
|
583
|
-
function has(haystack: string[] | string, needle: string): boolean {
|
|
592
|
+
function has(haystack: readonly string[] | string, needle: string): boolean {
|
|
584
593
|
return haystack.indexOf(needle) !== -1;
|
|
585
594
|
}
|
|
586
595
|
|
|
@@ -590,7 +599,7 @@ export const webfont = async (name: string, target: string, filesSrc: string[],
|
|
|
590
599
|
* @param map Options object
|
|
591
600
|
* @param key Option to find in the object
|
|
592
601
|
*/
|
|
593
|
-
function option(map: { _default?: string, [key: string]: string }, key: string): string {
|
|
602
|
+
function option(map: { readonly _default?: string, readonly [key: string]: string }, key: string): string {
|
|
594
603
|
if (key in map) {
|
|
595
604
|
return map[key];
|
|
596
605
|
} else {
|
|
@@ -661,11 +670,11 @@ export const webfont = async (name: string, target: string, filesSrc: string[],
|
|
|
661
670
|
* @param font URL or Base64 string
|
|
662
671
|
* @param stylesheet type: css, scss, ...
|
|
663
672
|
*/
|
|
664
|
-
function generateFontSrc(type:
|
|
673
|
+
function generateFontSrc(type: FontFormat, font: { readonly ext: string, readonly format?: string, readonly embeddable?: boolean }, stylesheet: string): string {
|
|
665
674
|
const filename = template(`${o.fontFilename}${font.ext}`, o);
|
|
666
675
|
let fontPathVariableName = `${o.fontFamilyName}-font-path`;
|
|
667
676
|
|
|
668
|
-
let url;
|
|
677
|
+
let url: string;
|
|
669
678
|
if (font.embeddable && has(o.embed, type)) {
|
|
670
679
|
url = embedFont(path.join(o.dest, filename));
|
|
671
680
|
} else {
|
|
@@ -739,10 +748,17 @@ export const webfont = async (name: string, target: string, filesSrc: string[],
|
|
|
739
748
|
*/
|
|
740
749
|
function renderTemplate(template: { filename: string, template: string }, context: Context): string {
|
|
741
750
|
try {
|
|
742
|
-
|
|
743
|
-
|
|
751
|
+
return new Eta({
|
|
752
|
+
autoTrim: ["nl", false],
|
|
753
|
+
parse: {
|
|
754
|
+
exec: "",
|
|
755
|
+
interpolate: "~",
|
|
756
|
+
raw: "=",
|
|
757
|
+
},
|
|
758
|
+
useWith: true,
|
|
759
|
+
}).renderString(template.template, context);
|
|
744
760
|
} catch (e) {
|
|
745
|
-
logger.fail.fatal(`Error while rendering template ${template.filename}: ${e.message}`);
|
|
761
|
+
logger.fail.fatal(`Error while rendering template ${template.filename}: ${(e as Error).message}`);
|
|
746
762
|
}
|
|
747
763
|
}
|
|
748
764
|
|
package/templates/demo.html
CHANGED
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
<pre><code><i class="ligature-icons"><span id="name2">name</span></i></code></pre>
|
|
82
82
|
<% } %>
|
|
83
83
|
|
|
84
|
-
<footer>Generated by <a href="https://github.com/
|
|
84
|
+
<footer>Generated by <a href="https://github.com/Hibi-10000/grunt-webfont">grunt-webfont</a>.</footer>
|
|
85
85
|
|
|
86
86
|
<script>
|
|
87
87
|
(function() {
|
package/tsconfig.json
CHANGED
|
@@ -1,19 +1,13 @@
|
|
|
1
1
|
{
|
|
2
|
-
"typeAcquisition": {
|
|
3
|
-
"enable": true,
|
|
4
|
-
},
|
|
5
2
|
"compilerOptions": {
|
|
6
3
|
"module": "ESNext",
|
|
7
4
|
"moduleResolution": "bundler",
|
|
8
|
-
"target": "
|
|
9
|
-
"lib": ["
|
|
5
|
+
"target": "ES2023",
|
|
6
|
+
"lib": ["ES2023"],
|
|
7
|
+
"types": ["grunt"],
|
|
10
8
|
"noEmit": true,
|
|
11
|
-
"allowJs": true,
|
|
12
|
-
"checkJs": true,
|
|
13
9
|
"strict": true,
|
|
14
10
|
"strictNullChecks": false,
|
|
15
|
-
"strictFunctionTypes": false,
|
|
16
|
-
"useUnknownInCatchVariables": false,
|
|
17
11
|
"resolveJsonModule": true,
|
|
18
12
|
"esModuleInterop": true,
|
|
19
13
|
"allowImportingTsExtensions": true,
|
|
@@ -26,6 +20,5 @@
|
|
|
26
20
|
},
|
|
27
21
|
"exclude": [
|
|
28
22
|
"dist",
|
|
29
|
-
"node_modules",
|
|
30
23
|
],
|
|
31
24
|
}
|