Skip to main content

webfont_generator/
types.rs

1#[cfg(feature = "fs")]
2use std::collections::HashMap;
3
4#[cfg(feature = "fs")]
5use serde_json::{Map, Value};
6
7pub(crate) mod color;
8pub use color::ColorGlyphSelection;
9
10/// What happened to a file, for [`crate::GenerateWebfontsResult::regenerate`]. `name` is the
11/// caller-resolved glyph name (the `rename` callback, if any, is applied by the caller).
12#[cfg(feature = "fs")]
13pub enum GlyphChange {
14    /// A new file. `name` overrides the file-stem glyph name when `Some`.
15    Added { name: Option<String> },
16    /// An existing file's contents changed. `name` overrides the glyph name when `Some`.
17    Changed { name: Option<String> },
18    /// The file was deleted.
19    Removed,
20}
21
22/// One entry in the `changes` array passed to the Node binding's `regenerate`. The complete
23/// ordered file list passed alongside it controls final glyph order; this only describes which
24/// files need re-reading, renaming, or removal.
25#[cfg(feature = "fs")]
26pub struct GlyphChangeEntry {
27    /// Path of the changed file.
28    pub path: String,
29    /// What happened to the file.
30    pub change_type: String,
31    /// Resolved glyph name (with the caller's `rename` already applied). Optional for `'added'`
32    /// and `'changed'` (defaults to the file stem/current name); ignored for `'removed'`.
33    pub name: Option<String>,
34}
35
36/// Complete ordered input membership for a regeneration operation. The case must match the
37/// result's generation mode. Synchronous methods borrow this value; async methods consume it.
38#[cfg(feature = "fs")]
39pub enum RegenerationFiles {
40    /// Single-design font inputs, in the order a fresh generation would use.
41    Single(Vec<String>),
42    /// Complete file sets for every configured variant, each named exactly once. The order of
43    /// these entries does not change configured design order. Paths can be shared between
44    /// designs; each design's file list independently determines its membership and order.
45    Variants(Vec<VariantFileSet>),
46}
47
48/// Complete file set for one configured variant during regeneration.
49#[cfg(feature = "fs")]
50pub struct VariantFileSet {
51    /// Existing variant name. Full re-diff requires every configured variant exactly once.
52    pub variant: String,
53    /// Complete ordered file set for this variant.
54    pub files: Vec<String>,
55}
56
57/// Font output format. Used in the `types` and `order` options to control which
58/// formats are generated and the order they appear in the CSS `@font-face`
59/// `src:` descriptor.
60#[cfg_attr(feature = "cli", derive(clap::ValueEnum))]
61#[derive(Clone, Copy, PartialEq, Eq, Hash)]
62#[cfg_attr(
63    any(feature = "cli", feature = "in_memory"),
64    derive(serde::Deserialize),
65    serde(rename_all = "lowercase")
66)]
67pub enum FontType {
68    /// SVG font (`.svg`). Legacy format; intermediate representation that all
69    /// other formats are derived from.
70    Svg,
71    /// TrueType font (`.ttf`).
72    Ttf,
73    /// Embedded OpenType (`.eot`). Legacy format for older Internet Explorer.
74    Eot,
75    /// Web Open Font Format 1.0 (`.woff`).
76    Woff,
77    /// Web Open Font Format 2.0 (`.woff2`). Best compression; preferred for
78    /// modern browsers.
79    Woff2,
80}
81
82/// One named SVG design in a multi-variant icon family.
83#[derive(Clone)]
84#[cfg_attr(
85    feature = "cli",
86    derive(serde::Deserialize),
87    serde(rename_all = "camelCase", deny_unknown_fields)
88)]
89#[cfg(feature = "fs")]
90pub struct FontVariant {
91    /// User-facing variant name, used to derive CSS modifier classes.
92    pub name: String,
93    /// SVG files that belong to this variant.
94    pub files: Vec<String>,
95    /// Optional explicit CSS weight coordinate in the range 1 through 1000. Automatic weights
96    /// resolve outward from the default in steps of 100, or evenly when an interval is crowded.
97    pub weight: Option<u16>,
98    /// Whether this is the family's default variant. Exactly one variant must set this to `true`.
99    pub default: Option<bool>,
100}
101
102/// Family-wide behavior when a logical glyph is absent from a variant.
103#[derive(Clone, Copy, PartialEq, Eq)]
104#[cfg_attr(
105    any(feature = "cli", feature = "in_memory"),
106    derive(serde::Deserialize),
107    serde(rename_all = "lowercase")
108)]
109pub enum MissingGlyphBehavior {
110    /// Use an empty outline while retaining the logical glyph's advance.
111    Blank,
112    /// Reject generation and report every missing variant/glyph pair.
113    Error,
114    /// Reuse the outline from the named fallback variant, which must contain every logical glyph.
115    Fallback,
116}
117
118/// Family-wide missing-glyph policy for multi-variant generation.
119#[derive(Clone)]
120#[cfg_attr(
121    any(feature = "cli", feature = "in_memory"),
122    derive(serde::Deserialize),
123    serde(rename_all = "camelCase", deny_unknown_fields)
124)]
125pub struct MissingGlyphOptions {
126    /// Missing-glyph behavior. Variant mode defaults to [`MissingGlyphBehavior::Blank`] when this
127    /// object is omitted.
128    pub behavior: MissingGlyphBehavior,
129    /// Fallback variant name. Required only when `behavior` is `fallback`; the named variant must
130    /// contain every logical glyph in the family.
131    pub variant: Option<String>,
132}
133
134impl FontType {
135    /// Returns the CSS `format()` value (e.g., "truetype", "woff2").
136    #[inline]
137    pub fn css_format(self) -> &'static str {
138        match self {
139            FontType::Svg => "svg",
140            FontType::Ttf => "truetype",
141            FontType::Eot => "embedded-opentype",
142            FontType::Woff => "woff",
143            FontType::Woff2 => "woff2",
144        }
145    }
146
147    /// Returns the file extension (e.g., "svg", "ttf", "woff2").
148    #[inline]
149    pub fn as_extension(self) -> &'static str {
150        match self {
151            FontType::Svg => "svg",
152            FontType::Ttf => "ttf",
153            FontType::Eot => "eot",
154            FontType::Woff => "woff",
155            FontType::Woff2 => "woff2",
156        }
157    }
158}
159
160/// SVG-format–specific options for the intermediate SVG font and the per-glyph
161/// path processing that feeds every other format.
162#[derive(Clone, Default)]
163#[cfg_attr(
164    any(feature = "cli", feature = "in_memory"),
165    derive(serde::Deserialize),
166    serde(rename_all = "camelCase", deny_unknown_fields)
167)]
168pub struct SvgFormatOptions {
169    /// SVG-format override of the top-level `centerVertically` option. When set,
170    /// it wins over the top-level value; centers each glyph vertically inside
171    /// the em-square based on its bounding box.
172    pub center_vertically: Option<bool>,
173    /// Value of the SVG font's `id` attribute. Defaults to `fontName` when
174    /// omitted.
175    pub font_id: Option<String>,
176    /// Content embedded inside the generated SVG font's `<metadata>` element.
177    pub metadata: Option<String>,
178    /// SVG-format override of the top-level `optimizeOutput` option. When set,
179    /// it wins over the top-level value. Path optimization may reduce SVG path
180    /// data, but does not guarantee smaller binary font output; compare the
181    /// generated sizes for the input set.
182    pub optimize_output: Option<bool>,
183    /// SVG-format override of the top-level `preserveAspectRatio` option. When
184    /// set, it wins over the top-level value; preserves the source viewBox
185    /// aspect ratio when scaling glyphs into the em-square.
186    pub preserve_aspect_ratio: Option<bool>,
187}
188
189/// TTF-format–specific options. Populates fields in the generated TTF `name`
190/// and `head` tables.
191#[derive(Clone)]
192#[cfg_attr(
193    any(feature = "cli", feature = "in_memory"),
194    derive(serde::Deserialize),
195    serde(rename_all = "camelCase", deny_unknown_fields)
196)]
197pub struct TtfFormatOptions {
198    /// Copyright string written to the TTF `name` table (record id 0).
199    pub copyright: Option<String>,
200    /// Description string written to the TTF `name` table (record id 10).
201    pub description: Option<String>,
202    /// Unix timestamp in seconds used for the `created` and `modified` fields
203    /// in the TTF `head` table. Pin to a fixed value to produce byte-stable
204    /// reproducible builds.
205    pub ts: Option<i64>,
206    /// Manufacturer URL written to the TTF `name` table (record id 11).
207    pub url: Option<String>,
208    /// Version string written to the TTF `name` table (record id 5).
209    pub version: Option<String>,
210}
211
212/// WOFF-format–specific options. Affects only WOFF1 output; WOFF2 ignores these.
213#[derive(Clone)]
214#[cfg_attr(
215    any(feature = "cli", feature = "in_memory"),
216    derive(serde::Deserialize),
217    serde(rename_all = "camelCase", deny_unknown_fields)
218)]
219pub struct WoffFormatOptions {
220    /// XML string embedded in the WOFF1 metadata block.
221    pub metadata: Option<String>,
222}
223
224/// WOFF2-format–specific options. Affects only WOFF2 output.
225#[derive(Clone)]
226#[cfg_attr(
227    any(feature = "cli", feature = "in_memory"),
228    derive(serde::Deserialize),
229    serde(rename_all = "camelCase", deny_unknown_fields)
230)]
231pub struct Woff2FormatOptions {
232    /// Brotli compression quality used when encoding WOFF2, from `0` (fastest,
233    /// largest output) to `11` (slowest, smallest output). This tunes compression
234    /// effort only and never changes glyph fidelity — the decompressed font is
235    /// identical at every level. Defaults to `11` for the smallest output; lower it
236    /// (e.g. to `10`) for faster encoding at a marginal size cost. Must be between
237    /// `0` and `11`; other values are rejected.
238    pub compression_quality: Option<u8>,
239}
240
241/// Per-format configuration object. Each field carries options that only apply
242/// to the corresponding output format.
243#[derive(Clone, Default)]
244#[cfg_attr(
245    any(feature = "cli", feature = "in_memory"),
246    derive(serde::Deserialize),
247    serde(rename_all = "camelCase", deny_unknown_fields)
248)]
249pub struct FormatOptions {
250    /// SVG-format options.
251    pub svg: Option<SvgFormatOptions>,
252    /// TTF-format options.
253    pub ttf: Option<TtfFormatOptions>,
254    /// WOFF1-format options.
255    pub woff: Option<WoffFormatOptions>,
256    /// WOFF2-format options.
257    pub woff2: Option<Woff2FormatOptions>,
258}
259
260/// Resolved variant metadata supplied to CSS and HTML template callbacks.
261#[derive(Clone)]
262pub struct TemplateVariant {
263    /// User-provided variant name.
264    pub name: String,
265    /// Resolved CSS weight coordinate.
266    pub weight: u32,
267    /// Whether this is the family's default design.
268    pub default: bool,
269    /// Unescaped modifier class for use in HTML.
270    pub class_name: String,
271    /// CSS-escaped modifier class identifier, without a leading dot.
272    pub selector: String,
273}
274
275/// Fields supplied to a `cssContext` callback. Additional keys from
276/// user-supplied `templateOptions` are merged into the same object at runtime,
277/// so the JS-side type widens this with an open-ended index signature.
278#[derive(Clone)]
279#[cfg(feature = "fs")]
280pub struct CssContext {
281    /// Named palette slot indices in ASCII name order. Empty when no slots are configured.
282    pub color_slots: HashMap<String, u32>,
283    /// Name of the generated font, mirroring the `fontName` option.
284    pub font_name: String,
285    /// Pre-rendered value for the CSS `@font-face` `src:` descriptor — a
286    /// comma-separated list of `url(...) format(...)` entries derived from the
287    /// configured `types`, `order`, and `cssFontsUrl`.
288    pub src: String,
289    /// Map from glyph name to its assigned codepoint as a hex-encoded string
290    /// (e.g. `"add" -> "f101"`), suitable for use inside CSS `content`
291    /// declarations like `content: "\f101"`.
292    pub codepoints: HashMap<String, String>,
293    /// Ordered resolved variants; absent in ordinary mode unless supplied by template options.
294    /// The mode-independent Node declaration is unknown because ordinary template data is arbitrary.
295    pub variants: Option<Vec<TemplateVariant>>,
296    /// Modifier class prefix, supplied in variant mode.
297    pub variant_class_prefix: Option<String>,
298    /// Resolved default weight, supplied in variant mode.
299    pub default_weight: Option<u32>,
300    /// Resolved font style, supplied in variant mode.
301    pub font_style: Option<String>,
302}
303
304/// Fields supplied to an `htmlContext` callback. Additional keys
305/// from user-supplied `templateOptions` are merged into the same object at
306/// runtime, so the JS-side type widens this with an open-ended index signature.
307#[derive(Clone)]
308#[cfg(feature = "fs")]
309pub struct HtmlContext {
310    /// Name of the generated font, mirroring the `fontName` option.
311    pub font_name: String,
312    /// Glyph names in declaration order, after any `rename` callback has been
313    /// applied. Useful for iterating over icons in a preview template.
314    pub names: Vec<String>,
315    /// Pre-rendered CSS (the same string the engine writes to the `.css`
316    /// output) so HTML templates can embed it inline for self-contained
317    /// previews without an external stylesheet reference.
318    pub styles: String,
319    /// Map from glyph name to its assigned codepoint as a numeric value
320    /// (e.g. `"add" -> 0xF101`). Use the CSS context's hex form if you need a
321    /// string for embedding into CSS `content` declarations.
322    pub codepoints: HashMap<String, u32>,
323    /// Ordered resolved variants; absent in ordinary mode unless supplied by template options.
324    /// The mode-independent Node declaration is unknown because ordinary template data is arbitrary.
325    pub variants: Option<Vec<TemplateVariant>>,
326    /// Modifier class prefix, supplied in variant mode.
327    pub variant_class_prefix: Option<String>,
328    /// Resolved default weight, supplied in variant mode.
329    pub default_weight: Option<u32>,
330    /// Resolved font style, supplied in variant mode.
331    pub font_style: Option<String>,
332}
333
334/// Top-level options controlling webfont generation. `dest` and exactly one source, ordinary
335/// `files` or `variants`, are required. Every other field has a sensible default.
336/// With the `cli` feature, options deserialize from camelCase JSON with unknown fields rejected.
337#[derive(Clone, Default)]
338#[cfg_attr(
339    feature = "cli",
340    derive(serde::Deserialize),
341    serde(rename_all = "camelCase", deny_unknown_fields)
342)]
343#[cfg(feature = "fs")]
344pub struct GenerateWebfontsOptions {
345    /// Preserve solid SVG paint for all or named post-rename logical glyphs, in every variant.
346    /// Omission or an empty named list preserves monochrome output. Active color requires
347    /// TTF, WOFF, or WOFF2; ordinary defaults include EOT, so set `types` explicitly.
348    #[cfg_attr(
349        feature = "cli",
350        serde(default, deserialize_with = "color::deserialize_selection")
351    )]
352    pub color_glyphs: Option<ColorGlyphSelection>,
353    /// Named palette slots matched against resolved SVG RGB fills. Values must be #RRGGBB.
354    /// Slots reserve indices in ASCII name order, including unused colors. Requires active
355    /// `color_glyphs`; names and RGB values must be unique. CSS context exposes name -> index.
356    pub color_slots: Option<HashMap<String, String>>,
357    /// Directory for a persistent generation cache. When set, a run saves per-glyph work and
358    /// finished font bytes there, and later runs reuse them for unchanged icons and formats.
359    /// Output is byte-identical to an uncached run, except that when `formatOptions.ttf.ts` is
360    /// unset, each cached format keeps the TTF `head` timestamp of the run that created it.
361    /// The engine owns the files it creates in this directory; clear them with
362    /// [`clear_cache`](crate::clear_cache). Cache read or write failures never fail generation.
363    pub cache_location: Option<String>,
364    /// Font ascent in font units. Overrides the value computed from the source
365    /// glyphs.
366    pub ascent: Option<f64>,
367    /// When `true`, centers each glyph horizontally inside the em-square based
368    /// on its bounding box.
369    pub center_horizontally: Option<bool>,
370    /// When `true`, centers each glyph vertically inside the em-square based
371    /// on its bounding box. Convenience alias for
372    /// `formatOptions.svg.centerVertically`.
373    pub center_vertically: Option<bool>,
374    /// Whether to generate a CSS file. Defaults to `true`.
375    pub css: Option<bool>,
376    /// Output path for the generated CSS file. Defaults to
377    /// `path.join(dest, fontName + '.css')`.
378    pub css_dest: Option<String>,
379    /// Path to a custom Handlebars template for CSS generation. The template
380    /// receives the `cssContext` shape plus any `templateOptions` keys.
381    pub css_template: Option<String>,
382    /// Explicit Unicode codepoints for specific glyphs, keyed by glyph name.
383    /// Glyphs not listed here are auto-assigned starting at `startCodepoint`.
384    pub codepoints: Option<HashMap<String, u32>>,
385    /// URL prefix for font files in the generated CSS. Defaults to the
386    /// relative path from `cssDest` to `dest`.
387    pub css_fonts_url: Option<String>,
388    /// Font descent in font units. Overrides the value computed from the
389    /// source glyphs.
390    pub descent: Option<f64>,
391    /// Output directory for generated font files. Required.
392    pub dest: String,
393    /// Paths to the SVG files to include in an ordinary font. Must be empty when `variants` is set.
394    #[cfg_attr(feature = "cli", serde(default))]
395    pub files: Vec<String>,
396    /// When `true`, produces a monospace font sized to the widest glyph.
397    pub fixed_width: Option<bool>,
398    /// Per-format option overrides. See `FormatOptions`.
399    pub format_options: Option<FormatOptions>,
400    /// Whether to generate an HTML preview file. Defaults to `false`.
401    pub html: Option<bool>,
402    /// Collect/write a fixed TypeScript module exporting icon names and selector settings.
403    /// Defaults to false; explicit result rendering is available regardless of this flag.
404    pub ts: Option<bool>,
405    /// TypeScript source destination. Defaults to `<dest>/<font_name>.ts`.
406    pub ts_dest: Option<String>,
407    /// Output path for the generated HTML preview file. Defaults to
408    /// `path.join(dest, fontName + '.html')`.
409    pub html_dest: Option<String>,
410    /// Path to a custom Handlebars template for HTML preview generation.
411    pub html_template: Option<String>,
412    /// Retain parsed glyph data on the result so `regenerate` can rebuild after file changes
413    /// without re-parsing unchanged glyphs. Defaults to `false`; enable for watch/dev. One-shot
414    /// builds (CLI, production) should leave it off to avoid holding the parsed geometry in memory.
415    /// Multi-variant results retain per-design parse/process caches. Pass
416    /// `RegenerationFiles::Variants` to the same regeneration methods for these results.
417    pub incremental: Option<bool>,
418    /// Explicit output font height in units per em. Overrides the height
419    /// computed from the source glyphs.
420    pub font_height: Option<f64>,
421    /// Name of the generated font family; also used as the base name for
422    /// output files. Defaults to `'iconfont'`.
423    pub font_name: Option<String>,
424    /// CSS `font-style` value for the generated `@font-face` rule.
425    pub font_style: Option<String>,
426    /// CSS `font-weight` value for the generated `@font-face` rule.
427    pub font_weight: Option<String>,
428    /// Enable ligature support so each glyph can be referenced by its name as
429    /// a text ligature. Defaults to `true`.
430    pub ligature: Option<bool>,
431    /// Family-wide missing-glyph policy for multi-variant generation. Defaults to `blank` and is
432    /// invalid without `variants`.
433    pub missing_glyphs: Option<MissingGlyphOptions>,
434    /// Scale icons to the height of the tallest icon. Defaults to `true`.
435    pub normalize: Option<bool>,
436    /// Order of `@font-face` `src:` entries in the generated CSS. Every entry
437    /// must also appear in `types`. Defaults to
438    /// `['eot', 'woff2', 'woff', 'ttf', 'svg']` filtered to the requested
439    /// `types`.
440    pub order: Option<Vec<FontType>>,
441    /// Run an SVG path optimizer over each glyph. This may reduce SVG path
442    /// data, but does not guarantee smaller binary font output; compare the
443    /// generated sizes for the input set. Convenience alias for
444    /// `formatOptions.svg.optimizeOutput`.
445    pub optimize_output: Option<bool>,
446    /// Preserve the source viewBox aspect ratio when scaling glyphs into the
447    /// em-square. Convenience alias for `formatOptions.svg.preserveAspectRatio`.
448    pub preserve_aspect_ratio: Option<bool>,
449    /// SVG path coordinate rounding precision.
450    pub round: Option<f64>,
451    /// Starting codepoint for auto-assigned glyphs. Defaults to `0xF101`.
452    pub start_codepoint: Option<u32>,
453    /// Additional key-value pairs merged into the Handlebars template
454    /// context for both CSS and HTML rendering. Typical home for
455    /// `classPrefix` and `baseSelector`.
456    pub template_options: Option<Map<String, Value>>,
457    /// How many threads read SVG files and do glyph work at once, including in later `regenerate`
458    /// calls on the result. Glyph work never uses more threads than CPU cores; reads can, since they
459    /// wait on storage. Not counted: WOFF2's Brotli worker, output file writes and the Tokio
460    /// runtime's own threads. Unset reads with one task per core and runs glyph work on Rayon's
461    /// global pool (`RAYON_NUM_THREADS` applies). Output is identical for every value.
462    pub threads: Option<std::num::NonZeroUsize>,
463    /// Font formats to generate. Ordinary mode defaults to `['eot', 'woff', 'woff2']`;
464    /// variant mode defaults to `['woff', 'woff2']` and rejects SVG and EOT.
465    pub types: Option<Vec<FontType>>,
466    /// Prefix for generated variant modifier classes. Defaults to `icon--` in variant mode and is
467    /// invalid without `variants`.
468    pub variant_class_prefix: Option<String>,
469    /// Ordered named SVG designs for one logical icon family. Variant generation emits shared
470    /// variable TTF/WOFF/WOFF2 fonts. SVG and EOT output are unsupported in variant mode.
471    /// Default CSS emits exact-weight faces sharing those fonts, with modifier classes and no
472    /// synthetic weights. CSS/HTML companions are written when enabled; HTML uses one default grid.
473    /// Template contexts include ordered `variants`, `variantClassPrefix`, `defaultWeight`, and
474    /// `fontStyle`. The SCSS mixin uses each family's default weight and style.
475    pub variants: Option<Vec<FontVariant>>,
476    /// Whether to write generated files to disk. Set to `false` for
477    /// in-memory usage. Defaults to `true`.
478    pub write_files: Option<bool>,
479}