Skip to main content

webfont_generator/
types.rs

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