Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 68 additions & 18 deletions packages/fallbacks/fallbacks.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,32 +184,32 @@ describe("face-aware lookups (Regular-only safety)", () => {
});
});

test("a Regular-only substitute is returned for Regular and NULL for bold/italic", () => {
// Baskerville -> Bacasime is Regular-only. The face-safe lookup must not route bold to it.
test("a Regular-only substitute can expose reviewed synthetic faces", () => {
expect(
getRenderableFallbackForFace("Baskerville Old Face", "regular", renderAll)
?.substituteFamily,
).toBe("Bacasime Antique");
expect(
getRenderableFallbackForFace("Baskerville Old Face", "bold", renderAll),
).toBeNull();
expect(
getRenderableFallbackForFace("Baskerville Old Face", "italic", renderAll),
).toBeNull();
for (const face of ["bold", "italic", "boldItalic"] as const) {
expect(
getRenderableFallbackForFace("Baskerville Old Face", face, renderAll),
`Baskerville ${face}`,
).toMatchObject({
substituteFamily: "Bacasime Antique",
verdict: "visual_only",
lineBreakSafe: false,
faceSource: { kind: "synthetic", from: "regular" },
});
}
});

test("an uncovered face is `face_missing`, not `unknown` or null collapse", () => {
expect(
getFallbackDecisionForFace(
"Baskerville Old Face",
"boldItalic",
renderAll,
),
getFallbackDecisionForFace("Arial Black", "bold", renderAll),
).toEqual({
kind: "face_missing",
substituteFamily: "Bacasime Antique",
evidenceId: "baskerville-old-face",
generic: "serif",
substituteFamily: "Archivo Black",
evidenceId: "arial-black",
generic: "sans-serif",
});
});

Expand Down Expand Up @@ -252,9 +252,9 @@ describe("face-aware lookups (Regular-only safety)", () => {
`Calibri Light ${face}`,
).toBe("Carlito");
}
// ...while a genuinely face-scoped Regular-only row still gates bold to face_missing.
// ...while a genuinely uncovered face still gates to face_missing.
expect(
getFallbackDecisionForFace("Baskerville Old Face", "bold", {
getFallbackDecisionForFace("Arial Black", "bold", {
canRenderFamily: () => true,
}).kind,
).toBe("face_missing");
Expand Down Expand Up @@ -322,10 +322,12 @@ describe("selected visual fallback rows", () => {
["Arial Black", "Archivo Black", "substitute"],
["Arial Rounded MT Bold", "Ubuntu", "category_fallback"],
["Bookman Old Style", "TeX Gyre Bonum", "substitute"],
["Brush Script MT", "Oregano Italic", "category_fallback"],
["Century", "C059", "substitute"],
["Comic Sans MS", "Comic Relief", "category_fallback"],
["Garamond", "Cardo", "category_fallback"],
["Gill Sans MT Condensed", "PT Sans Narrow", "category_fallback"],
["Lucida Console", "Noto Sans Mono", "category_fallback"],
["Tahoma", "Noto Sans", "category_fallback"],
["Trebuchet MS", "PT Sans", "category_fallback"],
] as const;
Expand Down Expand Up @@ -360,6 +362,14 @@ describe("selected visual fallback rows", () => {
faces: { regular: true, bold: true, italic: false, boldItalic: false },
});

expect(
getRenderableFallbackForFace("Brush Script MT", "bold", renderAll),
).toMatchObject({
substituteFamily: "Oregano Italic",
faceSource: { kind: "synthetic", from: "regular" },
faces: { regular: true, bold: false, italic: false, boldItalic: false },
});

expect(
getRenderableFallbackForFace(
"Gill Sans MT Condensed",
Expand All @@ -371,6 +381,42 @@ describe("selected visual fallback rows", () => {
faceSource: { kind: "synthetic", from: "regular" },
faces: { regular: true, bold: true, italic: false, boldItalic: false },
});

expect(
getRenderableFallbackForFace("Lucida Console", "boldItalic", renderAll),
).toMatchObject({
substituteFamily: "Noto Sans Mono",
faceSource: { kind: "synthetic", from: "bold" },
faces: { regular: true, bold: true, italic: false, boldItalic: false },
});
});

test("Lucida Console keeps cell-width evidence for real Noto Sans Mono faces", () => {
for (const face of ["regular", "bold"] as const) {
expect(
getRenderableFallbackForFace("Lucida Console", face, renderAll),
`Lucida Console ${face}`,
).toMatchObject({
substituteFamily: "Noto Sans Mono",
verdict: "cell_width_only",
lineBreakSafe: true,
});
expect(
getRenderableFallbackForFace("Lucida Console", face, renderAll)
?.faceSource,
).toBeUndefined();
}

for (const face of ["italic", "boldItalic"] as const) {
expect(
getRenderableFallbackForFace("Lucida Console", face, renderAll),
`Lucida Console ${face}`,
).toMatchObject({
substituteFamily: "Noto Sans Mono",
verdict: "visual_only",
lineBreakSafe: false,
});
}
});
});

Expand Down Expand Up @@ -436,6 +482,10 @@ describe("advance measurement basis", () => {
SUBSTITUTION_EVIDENCE.find((row) => row.evidenceId === "consolas")
?.advance?.basis,
).toBe("monospace_cell");
expect(
SUBSTITUTION_EVIDENCE.find((row) => row.evidenceId === "lucida-console")
?.advance?.basis,
).toBe("monospace_cell");
expect(
SUBSTITUTION_EVIDENCE.find((row) => row.evidenceId === "calibri")?.advance
?.basis,
Expand Down
98 changes: 85 additions & 13 deletions packages/fallbacks/records.json
Original file line number Diff line number Diff line change
Expand Up @@ -638,29 +638,48 @@
"evidenceId": "lucida-console",
"generic": "monospace",
"logicalFamily": "Lucida Console",
"physicalFamily": "Cousine",
"verdict": "cell_width_only",
"physicalFamily": "Noto Sans Mono",
"verdict": "visual_only",
"faces": {
"regular": false,
"bold": false,
"regular": true,
"bold": true,
"italic": false,
"boldItalic": false
},
"faceSources": {
"italic": {
"kind": "synthetic",
"from": "regular"
},
"boldItalic": {
"kind": "synthetic",
"from": "bold"
}
},
"gates": {
"static": "not_run",
"metric": "not_run",
"static": "pass",
"metric": "pass",
"layout": "not_run",
"ship": "not_run"
"ship": "fail"
},
"policyAction": "category_fallback",
"measurementRefs": ["lucida-console__cousine#analytic_advance#2026-06-03"],
"measurementRefs": [
"lucida-console__noto-sans-mono#monospace_cell#analytic_advance#2026-06-09",
"lucida-console__noto-sans-mono#visual_review#2026-06-09"
],
"exportRule": "preserve_original_name",
"advance": {
"basis": "monospace_cell",
"meanDelta": 0.004050000000000001,
"maxDelta": 0.004050000000000001
"meanDelta": 0.00254,
"maxDelta": 0.00303
},
"candidateLicense": "OFL-1.1"
"candidateLicense": "OFL-1.1",
"faceVerdicts": {
"regular": "cell_width_only",
"bold": "cell_width_only",
"italic": "visual_only",
"boldItalic": "visual_only"
}
},
{
"evidenceId": "gill-sans-mt-condensed",
Expand Down Expand Up @@ -817,6 +836,20 @@
"italic": false,
"boldItalic": false
},
"faceSources": {
"bold": {
"kind": "synthetic",
"from": "regular"
},
"italic": {
"kind": "synthetic",
"from": "regular"
},
"boldItalic": {
"kind": "synthetic",
"from": "regular"
}
},
"gates": {
"static": "pass",
"metric": "fail",
Expand All @@ -825,7 +858,8 @@
},
"policyAction": "substitute",
"measurementRefs": [
"baskerville-old-face_regular__bacasime-antique#regular#w400#7dac1e5f#analytic_advance#2026-06-05"
"baskerville-old-face_regular__bacasime-antique#regular#w400#7dac1e5f#analytic_advance#2026-06-05",
"baskerville-old-face__bacasime-antique#synthetic_faces#visual_review#2026-06-09"
],
"exportRule": "preserve_original_name",
"advance": {
Expand All @@ -835,7 +869,10 @@
},
"candidateLicense": "OFL-1.1",
"faceVerdicts": {
"regular": "visual_only"
"regular": "visual_only",
"bold": "visual_only",
"italic": "visual_only",
"boldItalic": "visual_only"
},
"glyphExceptions": [
{
Expand All @@ -846,6 +883,41 @@
}
]
},
{
"evidenceId": "brush-script-mt",
"generic": "serif",
"logicalFamily": "Brush Script MT",
"physicalFamily": "Oregano Italic",
"verdict": "visual_only",
"faces": {
"regular": true,
"bold": false,
"italic": false,
"boldItalic": false
},
"faceSources": {
"bold": {
"kind": "synthetic",
"from": "regular"
}
},
"gates": {
"static": "pass",
"metric": "fail",
"layout": "not_run",
"ship": "fail"
},
"policyAction": "category_fallback",
"measurementRefs": [
"brush-script-mt__oregano-italic#visual_review#2026-06-09"
],
"exportRule": "preserve_original_name",
"candidateLicense": "OFL-1.1",
"faceVerdicts": {
"regular": "visual_only",
"bold": "visual_only"
}
},
{
"evidenceId": "cooper-black",
"generic": "serif",
Expand Down
Loading
Loading