@docfonts/fallbacks 0.1.0 → 0.2.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/README.md CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  Document font substitution, measured.
4
4
 
5
- Measured open-font fallbacks for proprietary document fonts (Office / Word / DOCX), as a tiny runtime data package. It carries the structured substitution evidence plus one asset-aware lookup, so a renderer can map a requested proprietary font to an open one without hand-copying tables, and without routing to a font it does not bundle.
5
+ Measured open-font fallbacks for proprietary document fonts. Use it to decide whether a requested document font can render with an open family you actually ship.
6
6
 
7
- It ships no fonts and no proprietary binaries: only the measured evidence (which open family stands in, the verdict, the advance delta, the license id, and a stable evidence id).
7
+ It ships no fonts and no proprietary binaries. It ships decisions: the recommended open family when one exists, the fidelity verdict, and the honest cases where no open family should be used.
8
8
 
9
9
  ## Install
10
10
 
@@ -12,46 +12,85 @@ It ships no fonts and no proprietary binaries: only the measured evidence (which
12
12
  npm install @docfonts/fallbacks
13
13
  ```
14
14
 
15
- ## Usage
15
+ ESM-only. Use `import`, or let your bundler handle it. CommonJS `require()` is not supported.
16
16
 
17
- `getFallback` answers "what does docfonts recommend for this family?". Pass `hasFamily` to keep it to fonts you actually bundle:
17
+ ## Render A Font
18
+
19
+ Use `getRenderableFallback` when you need one font family to render now. Pass `canRenderFamily` so docfonts only returns families your app can load.
18
20
 
19
21
  ```ts
20
- import { getFallback } from "@docfonts/fallbacks";
22
+ import { getRenderableFallback } from "@docfonts/fallbacks";
23
+
24
+ const fallback = getRenderableFallback("Helvetica", {
25
+ canRenderFamily: (family) => bundledFamilies.has(family),
26
+ });
21
27
 
22
- getFallback("Helvetica", { hasFamily: (f) => bundled.has(f) });
23
- // { family: "Liberation Sans", action: "substitute", verdict: "metric_safe", faithful: true, evidenceId: "helvetica" }
28
+ // { substituteFamily: "Liberation Sans", policyAction: "substitute", verdict: "metric_safe", lineBreakSafe: true, evidenceId: "helvetica" }
24
29
  ```
25
30
 
26
- `deriveFallbackMap` builds the substitute map you wire into a resolver. `hasFamily` is required here: a render map never includes a substitute whose font you cannot load.
31
+ The result is `null` when there is nothing renderable from your available assets. Use `getFallbackDecision` when you need to know why.
32
+
33
+ ## Explain A Decision
34
+
35
+ Use `getFallbackDecision` for UI, diagnostics, and reporting. It distinguishes known fonts with no recommended fallback from fonts docfonts has never seen.
27
36
 
28
37
  ```ts
29
- import { deriveFallbackMap } from "@docfonts/fallbacks";
38
+ import { getFallbackDecision } from "@docfonts/fallbacks";
39
+
40
+ getFallbackDecision("Aptos");
41
+ // { kind: "customer_supplied", evidenceId: "aptos" }
30
42
 
31
- const map = deriveFallbackMap({ hasFamily: (f) => bundled.has(f) });
32
- // { helvetica: { family: "Liberation Sans", ... }, calibri: { ... }, ... }
33
- // Rows whose family you do not bundle are left out, not routed to a missing asset.
43
+ getFallbackDecision("Tahoma");
44
+ // { kind: "no_recommended_fallback", evidenceId: "tahoma" }
45
+
46
+ getFallbackDecision("Made Up Font");
47
+ // { kind: "unknown" }
48
+
49
+ getFallbackDecision("Georgia", {
50
+ canRenderFamily: (family) => bundledFamilies.has(family),
51
+ });
52
+ // { kind: "asset_missing", substituteFamily: "Gelasio", verdict: "near_metric", evidenceId: "georgia" }
34
53
  ```
35
54
 
36
- Both resolve to `null` (or omit the row) when docfonts has no row, the recommendation is "no open font stands in", or you do not ship the physical family.
55
+ Decision kinds:
56
+
57
+ - `fallback` - render the returned `substituteFamily`.
58
+ - `asset_missing` - docfonts has a fallback, but your app does not load that family.
59
+ - `no_recommended_fallback` - docfonts knows the font but recommends no renderable open family.
60
+ - `customer_supplied` - the real font should come from the customer or environment.
61
+ - `preserve_only` - keep the original family name. Do not substitute.
62
+ - `unknown` - docfonts has no evidence for this family.
63
+
64
+ ## Create A Resolver Map
65
+
66
+ Use `createFallbackMap` when wiring a resolver. `canRenderFamily` is required because a resolver map must never point at fonts you cannot load.
67
+
68
+ ```ts
69
+ import { createFallbackMap, normalizeFamilyName } from "@docfonts/fallbacks";
70
+
71
+ const map = createFallbackMap({
72
+ canRenderFamily: (family) => bundledFamilies.has(family),
73
+ });
74
+
75
+ map[normalizeFamilyName("Times New Roman")]; // { substituteFamily: "Liberation Serif", ... }
76
+ ```
77
+
78
+ Keys are normalized. Use `normalizeFamilyName` for lookups. Rows whose substitute family is not available are omitted.
37
79
 
38
80
  ## What the fields mean
39
81
 
40
- - `family` - the open family to render in place of the requested one.
41
- - `action` - `substitute` (a measured metric match) or `category_fallback` (right letterforms, lower fidelity).
42
- - `verdict` - the measured fidelity, from a fixed taxonomy (`metric_safe`, `near_metric`, `cell_width_only`, `visual_only`, ...). The headline rolls up to the worst face.
43
- - `faithful` - a coarse "good enough for line-break fidelity" flag (`metric_safe` or `near_metric`). Not a claim of an exact clone; read `verdict` for the tier.
44
- - `evidenceId` - the stable id for the reviewed evidence row.
82
+ - `substituteFamily` - the open family to render in place of the requested one.
83
+ - `policyAction` - what a renderer should do, not a quality claim. Use `verdict` for fidelity.
84
+ - `verdict` - the measured fidelity. Examples: `metric_safe`, `near_metric`, `cell_width_only`, `visual_only`.
85
+ - `lineBreakSafe` - true when advances preserve line breaks: `metric_safe`, `near_metric`, or monospace `cell_width_only`.
86
+ - `evidenceId` - the stable id for the reviewed evidence row; look the full row up in `SUBSTITUTION_EVIDENCE`.
87
+
88
+ `cell_width_only` keeps monospace advances stable, but glyph shapes can still differ. A `substitute` can still have a lower-fidelity `verdict` when one face or glyph is qualified. The verdict is the fidelity signal.
45
89
 
46
- The full structured rows are exported as `SUBSTITUTION_EVIDENCE` (faces, per-face verdicts, glyph exceptions) for richer reporting. Face-level routing stays yours: `getFallback` answers "which family", not "which face".
90
+ The full structured rows are exported as `SUBSTITUTION_EVIDENCE` for richer reporting, including faces, per-face verdicts, and glyph exceptions. Face-level routing stays yours: these helpers answer "which family", not "which face".
47
91
 
48
92
  ## Provenance
49
93
 
50
- The data comes from reviewed docfonts evidence. Measurements are produced against licensed originals,
51
- but this package distributes no proprietary binaries or raw proprietary metrics.
94
+ The data comes from reviewed docfonts evidence. Measurements are produced against licensed originals, but this package distributes no proprietary binaries or raw proprietary metrics.
52
95
 
53
96
  Built by the team behind SuperDoc. Standalone and neutral.
54
-
55
- ## License
56
-
57
- MIT
package/dist/data.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import type { SubstitutionEvidence } from "./types";
1
+ import type { SubstitutionEvidence } from "./types.js";
2
2
  export declare const SUBSTITUTION_EVIDENCE: readonly SubstitutionEvidence[];
@@ -1,27 +1,31 @@
1
- import type { FontFallback } from "./types";
1
+ import type { FallbackDecision, FontFallback } from "./types.js";
2
2
  /** Reports whether the consumer can actually render (i.e. bundles the asset for) a physical family. */
3
- export type HasFamily = (family: string) => boolean;
4
- /** Options for {@link getFallback}. `hasFamily` is OPTIONAL here - omit it to get the raw recommendation. */
5
- export interface FallbackOptions {
6
- /**
7
- * When given, a row whose `physicalFamily` is not available resolves to null - the row stays inert
8
- * until the consumer bundles it. When omitted, every row with a physical family is considered present.
9
- */
10
- hasFamily?: HasFamily;
3
+ export type CanRenderFamily = (family: string) => boolean;
4
+ /** Options for {@link getRenderableFallback} and {@link createFallbackMap}: a render map must be asset-safe. */
5
+ export interface RenderableFallbackOptions {
6
+ canRenderFamily: CanRenderFamily;
11
7
  }
12
- /** Options for {@link deriveFallbackMap}. `hasFamily` is REQUIRED - a render map must be asset-safe. */
13
- export interface FallbackMapOptions {
14
- hasFamily: HasFamily;
8
+ /** Options for {@link getFallbackDecision}. `canRenderFamily` is optional - omit it for the raw decision. */
9
+ export interface FallbackDecisionOptions {
10
+ canRenderFamily?: CanRenderFamily;
15
11
  }
12
+ /** Normalize a family name to a lookup key: trim, strip surrounding quotes, lowercase (CSS-name safe). */
13
+ export declare function normalizeFamilyName(name: string): string;
16
14
  /**
17
- * The open fallback for a requested font family, or null when docfonts has no row, the row recommends
18
- * no substitute, or the consumer does not ship the physical family. Case- and quote-insensitive.
15
+ * The full, honest outcome for a requested family: a discriminated union (see {@link FallbackDecision}).
16
+ * Distinguishes an unknown font from a measured "no open substitute", a substitute you do not bundle,
17
+ * and the deliberate non-substitution policies. Case- and quote-insensitive.
19
18
  */
20
- export declare function getFallback(logicalFamily: string, options?: FallbackOptions): FontFallback | null;
19
+ export declare function getFallbackDecision(family: string, options?: FallbackDecisionOptions): FallbackDecision;
20
+ /**
21
+ * The open family to render for a requested font, or null when there is nothing the consumer can render
22
+ * (no row, no open substitute, a deliberate non-substitution policy, or a substitute it does not
23
+ * bundle). For the reasons behind a null - to report them in a UI - use {@link getFallbackDecision}.
24
+ */
25
+ export declare function getRenderableFallback(family: string, options: RenderableFallbackOptions): FontFallback | null;
21
26
  /**
22
27
  * The renderer's substitute map: every fallback the consumer can actually render, keyed by the
23
- * normalized (lowercased) logical family. `hasFamily` is REQUIRED - rows whose physical family the
24
- * consumer does not bundle are excluded, so the map is safe to wire straight into a resolver. The keys
25
- * are exactly the families it should remap. For the un-gated single recommendation, use {@link getFallback}.
28
+ * normalized (lowercased) logical family - normalize lookups with {@link normalizeFamilyName}. Only
29
+ * `kind: "fallback"` rows are included, so the map is safe to wire straight into a resolver.
26
30
  */
27
- export declare function deriveFallbackMap(options: FallbackMapOptions): Record<string, FontFallback>;
31
+ export declare function createFallbackMap(options: RenderableFallbackOptions): Record<string, FontFallback>;
package/dist/fallbacks.js CHANGED
@@ -1,21 +1,23 @@
1
1
  /**
2
- * Asset-aware fallback helpers. `getFallback` can inspect the raw recommendation; `deriveFallbackMap`
3
- * requires `hasFamily` because a renderer map must not include fonts the consumer cannot load. Face
4
- * routing stays consumer-owned; this package answers which family, not which face.
2
+ * Fallback lookups over the reviewed evidence. Three intents:
3
+ * - getRenderableFallback - "I need a family to render now" (asset-gated, returns a family or null).
4
+ * - getFallbackDecision - "I need diagnostics / UI / reporting" (the full honest outcome).
5
+ * - createFallbackMap - "I need a resolver map" (asset-gated, render-only rows).
6
+ * Face routing stays consumer-owned: these answer which family, not which face.
5
7
  */
6
- import { SUBSTITUTION_EVIDENCE } from "./data";
7
- /** The two metric-grade bands. A substitution in either is line-break faithful; everything else is not. */
8
- const FAITHFUL_VERDICTS = new Set([
8
+ import { SUBSTITUTION_EVIDENCE } from "./data.js";
9
+ /**
10
+ * Verdicts whose advances preserve line breaks: the proportional metric-grade bands, plus
11
+ * cell_width_only (a monospace whose cell width - and therefore every advance - matches). Glyph shapes
12
+ * may still differ (read `verdict`); line breaks do not move.
13
+ */
14
+ const LINE_BREAK_SAFE_VERDICTS = new Set([
9
15
  "metric_safe",
10
16
  "near_metric",
11
- ]);
12
- /** Actions that mean "render this physical family". */
13
- const RENDERABLE_ACTIONS = new Set([
14
- "substitute",
15
- "category_fallback",
17
+ "cell_width_only",
16
18
  ]);
17
19
  /** Normalize a family name to a lookup key: trim, strip surrounding quotes, lowercase (CSS-name safe). */
18
- function normalizeFamily(name) {
20
+ export function normalizeFamilyName(name) {
19
21
  return name
20
22
  .trim()
21
23
  .replace(/^['"]+|['"]+$/g, "")
@@ -23,43 +25,71 @@ function normalizeFamily(name) {
23
25
  .toLowerCase();
24
26
  }
25
27
  /** Evidence rows indexed by normalized logical family, built once. */
26
- const BY_LOGICAL = new Map(SUBSTITUTION_EVIDENCE.map((row) => [normalizeFamily(row.logicalFamily), row]));
27
- /** Project a row to a FontFallback, or null when it offers nothing the consumer can render. */
28
- function toFallback(row, hasFamily) {
29
- if (row.physicalFamily === null)
30
- return null;
31
- if (!RENDERABLE_ACTIONS.has(row.policyAction))
32
- return null;
33
- if (hasFamily && !hasFamily(row.physicalFamily))
34
- return null;
28
+ const BY_LOGICAL = new Map(SUBSTITUTION_EVIDENCE.map((row) => [
29
+ normalizeFamilyName(row.logicalFamily),
30
+ row,
31
+ ]));
32
+ /** Build the FontFallback for a row known to carry a renderable physical family. */
33
+ function buildFallback(row, physicalFamily) {
35
34
  return {
36
- family: row.physicalFamily,
37
- action: row.policyAction,
35
+ substituteFamily: physicalFamily,
36
+ policyAction: row.policyAction,
38
37
  verdict: row.verdict,
39
- faithful: FAITHFUL_VERDICTS.has(row.verdict),
38
+ lineBreakSafe: LINE_BREAK_SAFE_VERDICTS.has(row.verdict),
40
39
  evidenceId: row.evidenceId,
41
40
  };
42
41
  }
42
+ /** Decide a single row against the consumer's asset availability. Pure. */
43
+ function decideRow(row, canRenderFamily) {
44
+ const { policyAction, physicalFamily, verdict, evidenceId } = row;
45
+ // Deliberate non-substitution policies first: nothing renders in the original's place.
46
+ if (policyAction === "preserve_only")
47
+ return { kind: "preserve_only", evidenceId };
48
+ if (policyAction === "customer_supplied")
49
+ return { kind: "customer_supplied", evidenceId };
50
+ // substitute / category_fallback with no named open family: docfonts knows the font but recommends
51
+ // no renderable family - distinct from the `no_substitute` verdict (read the row for that nuance).
52
+ if (physicalFamily === null)
53
+ return { kind: "no_recommended_fallback", evidenceId };
54
+ // Named substitute the consumer does not bundle: surfaced so a UI can say which font to add.
55
+ if (canRenderFamily && !canRenderFamily(physicalFamily))
56
+ return {
57
+ kind: "asset_missing",
58
+ substituteFamily: physicalFamily,
59
+ verdict,
60
+ evidenceId,
61
+ };
62
+ return { kind: "fallback", fallback: buildFallback(row, physicalFamily) };
63
+ }
64
+ /**
65
+ * The full, honest outcome for a requested family: a discriminated union (see {@link FallbackDecision}).
66
+ * Distinguishes an unknown font from a measured "no open substitute", a substitute you do not bundle,
67
+ * and the deliberate non-substitution policies. Case- and quote-insensitive.
68
+ */
69
+ export function getFallbackDecision(family, options = {}) {
70
+ const row = BY_LOGICAL.get(normalizeFamilyName(family));
71
+ return row ? decideRow(row, options.canRenderFamily) : { kind: "unknown" };
72
+ }
43
73
  /**
44
- * The open fallback for a requested font family, or null when docfonts has no row, the row recommends
45
- * no substitute, or the consumer does not ship the physical family. Case- and quote-insensitive.
74
+ * The open family to render for a requested font, or null when there is nothing the consumer can render
75
+ * (no row, no open substitute, a deliberate non-substitution policy, or a substitute it does not
76
+ * bundle). For the reasons behind a null - to report them in a UI - use {@link getFallbackDecision}.
46
77
  */
47
- export function getFallback(logicalFamily, options = {}) {
48
- const row = BY_LOGICAL.get(normalizeFamily(logicalFamily));
49
- return row ? toFallback(row, options.hasFamily) : null;
78
+ export function getRenderableFallback(family, options) {
79
+ const decision = getFallbackDecision(family, options);
80
+ return decision.kind === "fallback" ? decision.fallback : null;
50
81
  }
51
82
  /**
52
83
  * The renderer's substitute map: every fallback the consumer can actually render, keyed by the
53
- * normalized (lowercased) logical family. `hasFamily` is REQUIRED - rows whose physical family the
54
- * consumer does not bundle are excluded, so the map is safe to wire straight into a resolver. The keys
55
- * are exactly the families it should remap. For the un-gated single recommendation, use {@link getFallback}.
84
+ * normalized (lowercased) logical family - normalize lookups with {@link normalizeFamilyName}. Only
85
+ * `kind: "fallback"` rows are included, so the map is safe to wire straight into a resolver.
56
86
  */
57
- export function deriveFallbackMap(options) {
87
+ export function createFallbackMap(options) {
58
88
  const out = {};
59
89
  for (const [key, row] of BY_LOGICAL) {
60
- const fallback = toFallback(row, options.hasFamily);
61
- if (fallback)
62
- out[key] = fallback;
90
+ const decision = decideRow(row, options.canRenderFamily);
91
+ if (decision.kind === "fallback")
92
+ out[key] = decision.fallback;
63
93
  }
64
94
  return out;
65
95
  }
package/dist/index.d.ts CHANGED
@@ -2,6 +2,6 @@
2
2
  * Runtime fallback evidence and asset-aware lookup helpers. No font parser, research data, or runtime
3
3
  * dependency.
4
4
  */
5
- export { SUBSTITUTION_EVIDENCE } from "./data";
6
- export { deriveFallbackMap, type FallbackMapOptions, type FallbackOptions, getFallback, type HasFamily, } from "./fallbacks";
7
- export type { AdvanceDelta, FaceCoverage, FaceSlot, FontFallback, GlyphException, PolicyAction, SubstituteGates, SubstitutionEvidence, Verdict, } from "./types";
5
+ export { SUBSTITUTION_EVIDENCE } from "./data.js";
6
+ export { type CanRenderFamily, createFallbackMap, type FallbackDecisionOptions, getFallbackDecision, getRenderableFallback, normalizeFamilyName, type RenderableFallbackOptions, } from "./fallbacks.js";
7
+ export type { AdvanceDelta, FaceCoverage, FaceSlot, FallbackDecision, FontFallback, GlyphException, PolicyAction, SubstituteGates, SubstitutionEvidence, Verdict, } from "./types.js";
package/dist/index.js CHANGED
@@ -2,5 +2,5 @@
2
2
  * Runtime fallback evidence and asset-aware lookup helpers. No font parser, research data, or runtime
3
3
  * dependency.
4
4
  */
5
- export { SUBSTITUTION_EVIDENCE } from "./data";
6
- export { deriveFallbackMap, getFallback, } from "./fallbacks";
5
+ export { SUBSTITUTION_EVIDENCE } from "./data.js";
6
+ export { createFallbackMap, getFallbackDecision, getRenderableFallback, normalizeFamilyName, } from "./fallbacks.js";
package/dist/types.d.ts CHANGED
@@ -38,7 +38,8 @@ export interface GlyphException {
38
38
  note: string;
39
39
  }
40
40
  /**
41
- * One logical font's structured fallback evidence.
41
+ * One logical font's structured fallback evidence. The raw rows are exported as
42
+ * {@link SUBSTITUTION_EVIDENCE} for reporting; the helpers project the renderer-relevant fields.
42
43
  */
43
44
  export interface SubstitutionEvidence {
44
45
  /** docfonts evidence id, e.g. "cambria". */
@@ -65,24 +66,56 @@ export interface SubstitutionEvidence {
65
66
  exportRule: "preserve_original_name";
66
67
  }
67
68
  /**
68
- * The ergonomic result of {@link getFallback}: the single decision a renderer needs to act on - which
69
- * physical family to render, how it was chosen, and whether it is metric-faithful. The full structured
70
- * row stays available via {@link SUBSTITUTION_EVIDENCE} for richer reporting.
69
+ * A resolved fallback: which open family to render, how it was chosen, and whether advances preserve
70
+ * line breaks. The full structured row stays available via {@link SUBSTITUTION_EVIDENCE} for reporting.
71
71
  */
72
72
  export interface FontFallback {
73
- /** the physical family to render in place of the requested font. */
74
- family: string;
75
- /** how it was chosen: a metric substitute vs a same-category visual fallback. */
76
- action: PolicyAction;
73
+ /** the open family to render in place of the requested font. */
74
+ substituteFamily: string;
75
+ /**
76
+ * What a renderer should DO, independent of fidelity: `substitute` = render the named open family;
77
+ * `category_fallback` = render a lower-fidelity same-category family. NOT a quality claim - a
78
+ * `substitute` can still be top-level `visual_only` (e.g. Cambria). Read `verdict` for fidelity.
79
+ */
80
+ policyAction: PolicyAction;
77
81
  /** the worst-face fidelity verdict behind the choice. */
78
82
  verdict: Verdict;
79
83
  /**
80
- * Coarse "good enough for line-break fidelity" flag: true for the metric-grade bands (verdict
81
- * metric_safe or near_metric), false otherwise. NOT a claim of a perfect/exact clone - near_metric
82
- * drifts a few glyphs, and a row can roll up to a worse top-level verdict because of one face (see
83
- * Cambria). Read `verdict` (and the row's `faceVerdicts`) for the precise tier.
84
+ * Coarse "advances preserve line breaks" flag: true for metric_safe, near_metric, or monospace
85
+ * cell_width_only (cell width, and so every advance, matches). NOT a claim of a perfect/exact clone -
86
+ * near_metric drifts a few glyphs, cell_width_only keeps the advances but not the glyph shapes, and a
87
+ * row can roll up to a worse top-level verdict because of one face (see Cambria). Read `verdict` (and
88
+ * the row's `faceVerdicts`) for the precise tier.
84
89
  */
85
- faithful: boolean;
86
- /** stable reviewed-evidence id. */
90
+ lineBreakSafe: boolean;
91
+ /** stable reviewed-evidence id; look the full row up in {@link SUBSTITUTION_EVIDENCE}. */
87
92
  evidenceId: string;
88
93
  }
94
+ /**
95
+ * The full, honest outcome of a fallback lookup. A discriminated union so a consumer can tell apart
96
+ * cases that a bare `FontFallback | null` collapses: docfonts has never heard of the font (`unknown`)
97
+ * vs knows it but recommends no renderable family (`no_recommended_fallback`), the substitute exists
98
+ * but the consumer does not bundle it (`asset_missing`), and the deliberate non-substitution policies
99
+ * (`preserve_only`, `customer_supplied`). `evidenceId` on the terminal kinds points back into
100
+ * {@link SUBSTITUTION_EVIDENCE} for the full row (verdict, faces, ...).
101
+ */
102
+ export type FallbackDecision = {
103
+ kind: "fallback";
104
+ fallback: FontFallback;
105
+ } | {
106
+ kind: "asset_missing";
107
+ substituteFamily: string;
108
+ verdict: Verdict;
109
+ evidenceId: string;
110
+ } | {
111
+ kind: "no_recommended_fallback";
112
+ evidenceId: string;
113
+ } | {
114
+ kind: "customer_supplied";
115
+ evidenceId: string;
116
+ } | {
117
+ kind: "preserve_only";
118
+ evidenceId: string;
119
+ } | {
120
+ kind: "unknown";
121
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@docfonts/fallbacks",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Measured open-font fallbacks for proprietary document fonts.",
5
5
  "license": "MIT",
6
6
  "type": "module",