webfont-generator 0.11.0

Generate webfonts (SVG, TTF, EOT, WOFF, WOFF2) from SVG icons
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
#[cfg(feature = "fs")]
use std::collections::HashMap;

#[cfg(feature = "fs")]
use serde_json::{Map, Value};

pub(crate) mod color;
pub use color::ColorGlyphSelection;

/// What happened to a file, for [`crate::GenerateWebfontsResult::regenerate`]. `name` is the
/// caller-resolved glyph name (the `rename` callback, if any, is applied by the caller).
#[cfg(feature = "fs")]
pub enum GlyphChange {
    /// A new file. `name` overrides the file-stem glyph name when `Some`.
    Added { name: Option<String> },
    /// An existing file's contents changed. `name` overrides the glyph name when `Some`.
    Changed { name: Option<String> },
    /// The file was deleted.
    Removed,
}

/// One entry in the `changes` array passed to the Node binding's `regenerate`. The complete
/// ordered file list passed alongside it controls final glyph order; this only describes which
/// files need re-reading, renaming, or removal.
#[cfg(feature = "fs")]
pub struct GlyphChangeEntry {
    /// Path of the changed file.
    pub path: String,
    /// What happened to the file.
    pub change_type: String,
    /// Resolved glyph name (with the caller's `rename` already applied). Optional for `'added'`
    /// and `'changed'` (defaults to the file stem/current name); ignored for `'removed'`.
    pub name: Option<String>,
}

/// Complete ordered input membership for a regeneration operation. The case must match the
/// result's generation mode. Synchronous methods borrow this value; async methods consume it.
#[cfg(feature = "fs")]
pub enum RegenerationFiles {
    /// Single-design font inputs, in the order a fresh generation would use.
    Single(Vec<String>),
    /// Complete file sets for every configured variant, each named exactly once. The order of
    /// these entries does not change configured design order. Paths can be shared between
    /// designs; each design's file list independently determines its membership and order.
    Variants(Vec<VariantFileSet>),
}

/// Complete file set for one configured variant during regeneration.
#[cfg(feature = "fs")]
pub struct VariantFileSet {
    /// Existing variant name. Full re-diff requires every configured variant exactly once.
    pub variant: String,
    /// Complete ordered file set for this variant.
    pub files: Vec<String>,
}

/// Font output format. Used in the `types` and `order` options to control which
/// formats are generated and the order they appear in the CSS `@font-face`
/// `src:` descriptor.
#[cfg_attr(feature = "cli", derive(clap::ValueEnum))]
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(
    any(feature = "cli", feature = "in_memory"),
    derive(serde::Deserialize),
    serde(rename_all = "lowercase")
)]
pub enum FontType {
    /// SVG font (`.svg`). Legacy format; intermediate representation that all
    /// other formats are derived from.
    Svg,
    /// TrueType font (`.ttf`).
    Ttf,
    /// Embedded OpenType (`.eot`). Legacy format for older Internet Explorer.
    Eot,
    /// Web Open Font Format 1.0 (`.woff`).
    Woff,
    /// Web Open Font Format 2.0 (`.woff2`). Best compression; preferred for
    /// modern browsers.
    Woff2,
}

/// One named SVG design in a multi-variant icon family.
#[derive(Clone)]
#[cfg_attr(
    feature = "cli",
    derive(serde::Deserialize),
    serde(rename_all = "camelCase", deny_unknown_fields)
)]
#[cfg(feature = "fs")]
pub struct FontVariant {
    /// User-facing variant name, used to derive CSS modifier classes.
    pub name: String,
    /// SVG files that belong to this variant.
    pub files: Vec<String>,
    /// Optional explicit CSS weight coordinate in the range 1 through 1000. Automatic weights
    /// resolve outward from the default in steps of 100, or evenly when an interval is crowded.
    pub weight: Option<u16>,
    /// Whether this is the family's default variant. Exactly one variant must set this to `true`.
    pub default: Option<bool>,
}

/// Family-wide behavior when a logical glyph is absent from a variant.
#[derive(Clone, Copy, PartialEq, Eq)]
#[cfg_attr(
    any(feature = "cli", feature = "in_memory"),
    derive(serde::Deserialize),
    serde(rename_all = "lowercase")
)]
pub enum MissingGlyphBehavior {
    /// Use an empty outline while retaining the logical glyph's advance.
    Blank,
    /// Reject generation and report every missing variant/glyph pair.
    Error,
    /// Reuse the outline from the named fallback variant, which must contain every logical glyph.
    Fallback,
}

/// Family-wide missing-glyph policy for multi-variant generation.
#[derive(Clone)]
#[cfg_attr(
    any(feature = "cli", feature = "in_memory"),
    derive(serde::Deserialize),
    serde(rename_all = "camelCase", deny_unknown_fields)
)]
pub struct MissingGlyphOptions {
    /// Missing-glyph behavior. Variant mode defaults to [`MissingGlyphBehavior::Blank`] when this
    /// object is omitted.
    pub behavior: MissingGlyphBehavior,
    /// Fallback variant name. Required only when `behavior` is `fallback`; the named variant must
    /// contain every logical glyph in the family.
    pub variant: Option<String>,
}

impl FontType {
    /// Returns the CSS `format()` value (e.g., "truetype", "woff2").
    #[inline]
    pub fn css_format(self) -> &'static str {
        match self {
            FontType::Svg => "svg",
            FontType::Ttf => "truetype",
            FontType::Eot => "embedded-opentype",
            FontType::Woff => "woff",
            FontType::Woff2 => "woff2",
        }
    }

    /// Returns the file extension (e.g., "svg", "ttf", "woff2").
    #[inline]
    pub fn as_extension(self) -> &'static str {
        match self {
            FontType::Svg => "svg",
            FontType::Ttf => "ttf",
            FontType::Eot => "eot",
            FontType::Woff => "woff",
            FontType::Woff2 => "woff2",
        }
    }
}

/// SVG-format–specific options for the intermediate SVG font and the per-glyph
/// path processing that feeds every other format.
#[derive(Clone, Default)]
#[cfg_attr(
    any(feature = "cli", feature = "in_memory"),
    derive(serde::Deserialize),
    serde(rename_all = "camelCase", deny_unknown_fields)
)]
pub struct SvgFormatOptions {
    /// SVG-format override of the top-level `centerVertically` option. When set,
    /// it wins over the top-level value; centers each glyph vertically inside
    /// the em-square based on its bounding box.
    pub center_vertically: Option<bool>,
    /// Value of the SVG font's `id` attribute. Defaults to `fontName` when
    /// omitted.
    pub font_id: Option<String>,
    /// Content embedded inside the generated SVG font's `<metadata>` element.
    pub metadata: Option<String>,
    /// SVG-format override of the top-level `optimizeOutput` option. When set,
    /// it wins over the top-level value. Path optimization may reduce SVG path
    /// data, but does not guarantee smaller binary font output; compare the
    /// generated sizes for the input set.
    pub optimize_output: Option<bool>,
    /// SVG-format override of the top-level `preserveAspectRatio` option. When
    /// set, it wins over the top-level value; preserves the source viewBox
    /// aspect ratio when scaling glyphs into the em-square.
    pub preserve_aspect_ratio: Option<bool>,
}

/// TTF-format–specific options. Populates fields in the generated TTF `name`
/// and `head` tables.
#[derive(Clone)]
#[cfg_attr(
    any(feature = "cli", feature = "in_memory"),
    derive(serde::Deserialize),
    serde(rename_all = "camelCase", deny_unknown_fields)
)]
pub struct TtfFormatOptions {
    /// Copyright string written to the TTF `name` table (record id 0).
    pub copyright: Option<String>,
    /// Description string written to the TTF `name` table (record id 10).
    pub description: Option<String>,
    /// Unix timestamp in seconds used for the `created` and `modified` fields
    /// in the TTF `head` table. Pin to a fixed value to produce byte-stable
    /// reproducible builds.
    pub ts: Option<i64>,
    /// Manufacturer URL written to the TTF `name` table (record id 11).
    pub url: Option<String>,
    /// Version string written to the TTF `name` table (record id 5).
    pub version: Option<String>,
}

/// WOFF-format–specific options. Affects only WOFF1 output; WOFF2 ignores these.
#[derive(Clone)]
#[cfg_attr(
    any(feature = "cli", feature = "in_memory"),
    derive(serde::Deserialize),
    serde(rename_all = "camelCase", deny_unknown_fields)
)]
pub struct WoffFormatOptions {
    /// XML string embedded in the WOFF1 metadata block.
    pub metadata: Option<String>,
}

/// WOFF2-format–specific options. Affects only WOFF2 output.
#[derive(Clone)]
#[cfg_attr(
    any(feature = "cli", feature = "in_memory"),
    derive(serde::Deserialize),
    serde(rename_all = "camelCase", deny_unknown_fields)
)]
pub struct Woff2FormatOptions {
    /// Brotli compression quality used when encoding WOFF2, from `0` (fastest,
    /// largest output) to `11` (slowest, smallest output). This tunes compression
    /// effort only and never changes glyph fidelity — the decompressed font is
    /// identical at every level. Defaults to `11` for the smallest output; lower it
    /// (e.g. to `10`) for faster encoding at a marginal size cost. Must be between
    /// `0` and `11`; other values are rejected.
    pub compression_quality: Option<u8>,
}

/// Per-format configuration object. Each field carries options that only apply
/// to the corresponding output format.
#[derive(Clone, Default)]
#[cfg_attr(
    any(feature = "cli", feature = "in_memory"),
    derive(serde::Deserialize),
    serde(rename_all = "camelCase", deny_unknown_fields)
)]
pub struct FormatOptions {
    /// SVG-format options.
    pub svg: Option<SvgFormatOptions>,
    /// TTF-format options.
    pub ttf: Option<TtfFormatOptions>,
    /// WOFF1-format options.
    pub woff: Option<WoffFormatOptions>,
    /// WOFF2-format options.
    pub woff2: Option<Woff2FormatOptions>,
}

/// Resolved variant metadata supplied to CSS and HTML template callbacks.
#[derive(Clone)]
pub struct TemplateVariant {
    /// User-provided variant name.
    pub name: String,
    /// Resolved CSS weight coordinate.
    pub weight: u32,
    /// Whether this is the family's default design.
    pub default: bool,
    /// Unescaped modifier class for use in HTML.
    pub class_name: String,
    /// CSS-escaped modifier class identifier, without a leading dot.
    pub selector: String,
}

/// Fields supplied to a `cssContext` callback. Additional keys from
/// user-supplied `templateOptions` are merged into the same object at runtime,
/// so the JS-side type widens this with an open-ended index signature.
#[derive(Clone)]
#[cfg(feature = "fs")]
pub struct CssContext {
    /// Named palette slot indices in ASCII name order. Empty when no slots are configured.
    pub color_slots: HashMap<String, u32>,
    /// Name of the generated font, mirroring the `fontName` option.
    pub font_name: String,
    /// Pre-rendered value for the CSS `@font-face` `src:` descriptor — a
    /// comma-separated list of `url(...) format(...)` entries derived from the
    /// configured `types`, `order`, and `cssFontsUrl`.
    pub src: String,
    /// Map from glyph name to its assigned codepoint as a hex-encoded string
    /// (e.g. `"add" -> "f101"`), suitable for use inside CSS `content`
    /// declarations like `content: "\f101"`.
    pub codepoints: HashMap<String, String>,
    /// Ordered resolved variants; absent in ordinary mode unless supplied by template options.
    /// The mode-independent Node declaration is unknown because ordinary template data is arbitrary.
    pub variants: Option<Vec<TemplateVariant>>,
    /// Modifier class prefix, supplied in variant mode.
    pub variant_class_prefix: Option<String>,
    /// Resolved default weight, supplied in variant mode.
    pub default_weight: Option<u32>,
    /// Resolved font style, supplied in variant mode.
    pub font_style: Option<String>,
}

/// Fields supplied to an `htmlContext` callback. Additional keys
/// from user-supplied `templateOptions` are merged into the same object at
/// runtime, so the JS-side type widens this with an open-ended index signature.
#[derive(Clone)]
#[cfg(feature = "fs")]
pub struct HtmlContext {
    /// Name of the generated font, mirroring the `fontName` option.
    pub font_name: String,
    /// Glyph names in declaration order, after any `rename` callback has been
    /// applied. Useful for iterating over icons in a preview template.
    pub names: Vec<String>,
    /// Pre-rendered CSS (the same string the engine writes to the `.css`
    /// output) so HTML templates can embed it inline for self-contained
    /// previews without an external stylesheet reference.
    pub styles: String,
    /// Map from glyph name to its assigned codepoint as a numeric value
    /// (e.g. `"add" -> 0xF101`). Use the CSS context's hex form if you need a
    /// string for embedding into CSS `content` declarations.
    pub codepoints: HashMap<String, u32>,
    /// Ordered resolved variants; absent in ordinary mode unless supplied by template options.
    /// The mode-independent Node declaration is unknown because ordinary template data is arbitrary.
    pub variants: Option<Vec<TemplateVariant>>,
    /// Modifier class prefix, supplied in variant mode.
    pub variant_class_prefix: Option<String>,
    /// Resolved default weight, supplied in variant mode.
    pub default_weight: Option<u32>,
    /// Resolved font style, supplied in variant mode.
    pub font_style: Option<String>,
}

/// Top-level options controlling webfont generation. `dest` and exactly one source, ordinary
/// `files` or `variants`, are required. Every other field has a sensible default.
/// With the `cli` feature, options deserialize from camelCase JSON with unknown fields rejected.
#[derive(Clone, Default)]
#[cfg_attr(
    feature = "cli",
    derive(serde::Deserialize),
    serde(rename_all = "camelCase", deny_unknown_fields)
)]
#[cfg(feature = "fs")]
pub struct GenerateWebfontsOptions {
    /// Preserve solid SVG paint for all or named post-rename logical glyphs, in every variant.
    /// Omission or an empty named list preserves monochrome output. Active color requires
    /// TTF, WOFF, or WOFF2; ordinary defaults include EOT, so set `types` explicitly.
    #[cfg_attr(
        feature = "cli",
        serde(default, deserialize_with = "color::deserialize_selection")
    )]
    pub color_glyphs: Option<ColorGlyphSelection>,
    /// Named palette slots matched against resolved SVG RGB fills. Values must be #RRGGBB.
    /// Slots reserve indices in ASCII name order, including unused colors. Requires active
    /// `color_glyphs`; names and RGB values must be unique. CSS context exposes name -> index.
    pub color_slots: Option<HashMap<String, String>>,
    /// Directory for a persistent generation cache. When set, a run saves per-glyph work and
    /// finished font bytes there, and later runs reuse them for unchanged icons and formats.
    /// Output is byte-identical to an uncached run, except that when `formatOptions.ttf.ts` is
    /// unset, each cached format keeps the TTF `head` timestamp of the run that created it.
    /// The engine owns the files it creates in this directory; clear them with
    /// [`clear_cache`](crate::clear_cache). Cache read or write failures never fail generation.
    pub cache_location: Option<String>,
    /// Font ascent in font units. Overrides the value computed from the source
    /// glyphs.
    pub ascent: Option<f64>,
    /// When `true`, centers each glyph horizontally inside the em-square based
    /// on its bounding box.
    pub center_horizontally: Option<bool>,
    /// When `true`, centers each glyph vertically inside the em-square based
    /// on its bounding box. Convenience alias for
    /// `formatOptions.svg.centerVertically`.
    pub center_vertically: Option<bool>,
    /// Whether to generate a CSS file. Defaults to `true`.
    pub css: Option<bool>,
    /// Output path for the generated CSS file. Defaults to
    /// `path.join(dest, fontName + '.css')`.
    pub css_dest: Option<String>,
    /// Path to a custom Handlebars template for CSS generation. The template
    /// receives the `cssContext` shape plus any `templateOptions` keys.
    pub css_template: Option<String>,
    /// Explicit Unicode codepoints for specific glyphs, keyed by glyph name.
    /// Glyphs not listed here are auto-assigned starting at `startCodepoint`.
    pub codepoints: Option<HashMap<String, u32>>,
    /// URL prefix for font files in the generated CSS. Defaults to the
    /// relative path from `cssDest` to `dest`.
    pub css_fonts_url: Option<String>,
    /// Font descent in font units. Overrides the value computed from the
    /// source glyphs.
    pub descent: Option<f64>,
    /// Output directory for generated font files. Required.
    pub dest: String,
    /// Paths to the SVG files to include in an ordinary font. Must be empty when `variants` is set.
    #[cfg_attr(feature = "cli", serde(default))]
    pub files: Vec<String>,
    /// When `true`, produces a monospace font sized to the widest glyph.
    pub fixed_width: Option<bool>,
    /// Per-format option overrides. See `FormatOptions`.
    pub format_options: Option<FormatOptions>,
    /// Whether to generate an HTML preview file. Defaults to `false`.
    pub html: Option<bool>,
    /// Collect/write a fixed TypeScript module exporting icon names and selector settings.
    /// Defaults to false; explicit result rendering is available regardless of this flag.
    pub ts: Option<bool>,
    /// TypeScript source destination. Defaults to `<dest>/<font_name>.ts`.
    pub ts_dest: Option<String>,
    /// Output path for the generated HTML preview file. Defaults to
    /// `path.join(dest, fontName + '.html')`.
    pub html_dest: Option<String>,
    /// Path to a custom Handlebars template for HTML preview generation.
    pub html_template: Option<String>,
    /// Retain parsed glyph data on the result so `regenerate` can rebuild after file changes
    /// without re-parsing unchanged glyphs. Defaults to `false`; enable for watch/dev. One-shot
    /// builds (CLI, production) should leave it off to avoid holding the parsed geometry in memory.
    /// Multi-variant results retain per-design parse/process caches. Pass
    /// `RegenerationFiles::Variants` to the same regeneration methods for these results.
    pub incremental: Option<bool>,
    /// Explicit output font height in units per em. Overrides the height
    /// computed from the source glyphs.
    pub font_height: Option<f64>,
    /// Name of the generated font family; also used as the base name for
    /// output files. Defaults to `'iconfont'`.
    pub font_name: Option<String>,
    /// CSS `font-style` value for the generated `@font-face` rule.
    pub font_style: Option<String>,
    /// CSS `font-weight` value for the generated `@font-face` rule.
    pub font_weight: Option<String>,
    /// Enable ligature support so each glyph can be referenced by its name as
    /// a text ligature. Defaults to `true`.
    pub ligature: Option<bool>,
    /// Family-wide missing-glyph policy for multi-variant generation. Defaults to `blank` and is
    /// invalid without `variants`.
    pub missing_glyphs: Option<MissingGlyphOptions>,
    /// Scale icons to the height of the tallest icon. Defaults to `true`.
    pub normalize: Option<bool>,
    /// Order of `@font-face` `src:` entries in the generated CSS. Every entry
    /// must also appear in `types`. Defaults to
    /// `['eot', 'woff2', 'woff', 'ttf', 'svg']` filtered to the requested
    /// `types`.
    pub order: Option<Vec<FontType>>,
    /// Run an SVG path optimizer over each glyph. This may reduce SVG path
    /// data, but does not guarantee smaller binary font output; compare the
    /// generated sizes for the input set. Convenience alias for
    /// `formatOptions.svg.optimizeOutput`.
    pub optimize_output: Option<bool>,
    /// Preserve the source viewBox aspect ratio when scaling glyphs into the
    /// em-square. Convenience alias for `formatOptions.svg.preserveAspectRatio`.
    pub preserve_aspect_ratio: Option<bool>,
    /// SVG path coordinate rounding precision.
    pub round: Option<f64>,
    /// Starting codepoint for auto-assigned glyphs. Defaults to `0xF101`.
    pub start_codepoint: Option<u32>,
    /// Additional key-value pairs merged into the Handlebars template
    /// context for both CSS and HTML rendering. Typical home for
    /// `classPrefix` and `baseSelector`.
    pub template_options: Option<Map<String, Value>>,
    /// How many threads read SVG files and do glyph work at once, including in later `regenerate`
    /// calls on the result. Glyph work never uses more threads than CPU cores; reads can, since they
    /// wait on storage. Not counted: WOFF2's Brotli worker, output file writes and the Tokio
    /// runtime's own threads. Unset reads with one task per core and runs glyph work on Rayon's
    /// global pool (`RAYON_NUM_THREADS` applies). Output is identical for every value.
    pub threads: Option<std::num::NonZeroUsize>,
    /// Font formats to generate. Ordinary mode defaults to `['eot', 'woff', 'woff2']`;
    /// variant mode defaults to `['woff', 'woff2']` and rejects SVG and EOT.
    pub types: Option<Vec<FontType>>,
    /// Prefix for generated variant modifier classes. Defaults to `icon--` in variant mode and is
    /// invalid without `variants`.
    pub variant_class_prefix: Option<String>,
    /// Ordered named SVG designs for one logical icon family. Variant generation emits shared
    /// variable TTF/WOFF/WOFF2 fonts. SVG and EOT output are unsupported in variant mode.
    /// Default CSS emits exact-weight faces sharing those fonts, with modifier classes and no
    /// synthetic weights. CSS/HTML companions are written when enabled; HTML uses one default grid.
    /// Template contexts include ordered `variants`, `variantClassPrefix`, `defaultWeight`, and
    /// `fontStyle`. The SCSS mixin uses each family's default weight and style.
    pub variants: Option<Vec<FontVariant>>,
    /// Whether to write generated files to disk. Set to `false` for
    /// in-memory usage. Defaults to `true`.
    pub write_files: Option<bool>,
}