diff --git a/public/fonts/EBGaramond-Italic-VF.ttf b/public/fonts/EBGaramond-Italic-VF.ttf new file mode 100644 index 0000000..f9ad996 Binary files /dev/null and b/public/fonts/EBGaramond-Italic-VF.ttf differ diff --git a/public/fonts/EBGaramond-OFL.txt b/public/fonts/EBGaramond-OFL.txt new file mode 100644 index 0000000..c1ec5e1 --- /dev/null +++ b/public/fonts/EBGaramond-OFL.txt @@ -0,0 +1,93 @@ +Copyright 2017 The EB Garamond Project Authors (https://github.com/octaviopardo/EBGaramond12) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +https://openfontlicense.org + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/public/fonts/EBGaramond-VF.ttf b/public/fonts/EBGaramond-VF.ttf new file mode 100644 index 0000000..52d34b8 Binary files /dev/null and b/public/fonts/EBGaramond-VF.ttf differ diff --git a/public/fonts/Fraunces-Italic-VF.ttf b/public/fonts/Fraunces-Italic-VF.ttf new file mode 100644 index 0000000..2ddf59a Binary files /dev/null and b/public/fonts/Fraunces-Italic-VF.ttf differ diff --git a/public/fonts/Fraunces-OFL.txt b/public/fonts/Fraunces-OFL.txt new file mode 100644 index 0000000..22fa7ce --- /dev/null +++ b/public/fonts/Fraunces-OFL.txt @@ -0,0 +1,93 @@ +Copyright 2018 The Fraunces Project Authors (https://github.com/undercasetype/Fraunces) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/public/fonts/Fraunces-VF.ttf b/public/fonts/Fraunces-VF.ttf new file mode 100644 index 0000000..8210f94 Binary files /dev/null and b/public/fonts/Fraunces-VF.ttf differ diff --git a/public/fonts/Lora-Italic-VF.ttf b/public/fonts/Lora-Italic-VF.ttf new file mode 100644 index 0000000..e973ccf Binary files /dev/null and b/public/fonts/Lora-Italic-VF.ttf differ diff --git a/public/fonts/Lora-OFL.txt b/public/fonts/Lora-OFL.txt new file mode 100644 index 0000000..d0ce7fe --- /dev/null +++ b/public/fonts/Lora-OFL.txt @@ -0,0 +1,93 @@ +Copyright 2011 The Lora Project Authors (https://github.com/cyrealtype/Lora-Cyrillic), with Reserved Font Name "Lora". + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +https://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/public/fonts/Lora-VF.ttf b/public/fonts/Lora-VF.ttf new file mode 100644 index 0000000..ee1914c Binary files /dev/null and b/public/fonts/Lora-VF.ttf differ diff --git a/public/fonts/SourceSerif4-Italic-VF.ttf b/public/fonts/SourceSerif4-Italic-VF.ttf new file mode 100644 index 0000000..ccb969a Binary files /dev/null and b/public/fonts/SourceSerif4-Italic-VF.ttf differ diff --git a/public/fonts/SourceSerif4-OFL.txt b/public/fonts/SourceSerif4-OFL.txt new file mode 100644 index 0000000..318074e --- /dev/null +++ b/public/fonts/SourceSerif4-OFL.txt @@ -0,0 +1,93 @@ +Copyright 2014 The Source Serif 4 Project Authors (https://github.com/adobe-fonts/source-serif) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +https://openfontlicense.org + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/public/fonts/SourceSerif4-VF.ttf b/public/fonts/SourceSerif4-VF.ttf new file mode 100644 index 0000000..40bbb58 Binary files /dev/null and b/public/fonts/SourceSerif4-VF.ttf differ diff --git a/src/import/epub.ts b/src/import/epub.ts index 55cfe63..3ba095f 100644 --- a/src/import/epub.ts +++ b/src/import/epub.ts @@ -2,6 +2,7 @@ import { invoke } from "@tauri-apps/api/core"; import { open } from "@tauri-apps/plugin-dialog"; import type { JSONContent } from "@tiptap/core"; import { type Book, type BookMetadata, type Chapter, type Cover, createCover } from "../model/book"; +import { DEFAULT_FONTS } from "../model/fonts"; export interface RawFile { path: string; @@ -515,7 +516,7 @@ export function filesToBook(files: RawFile[], fallbackName = "Imported book"): B id: crypto.randomUUID(), metadata, theme: "quiet-press", - settings: { trim: "6x9", bleed: true }, + settings: { trim: "6x9", bleed: true, fonts: DEFAULT_FONTS }, cover: findCover(opf, manifest, byPath), chapters, }; diff --git a/src/model/book.ts b/src/model/book.ts index 4e78be3..0d6d675 100644 --- a/src/model/book.ts +++ b/src/model/book.ts @@ -1,4 +1,5 @@ import type { JSONContent } from "@tiptap/core"; +import { type BookFonts, DEFAULT_FONTS } from "./fonts"; export type TrimSize = "6x9" | "5.5x8.5" | "5x8" | "a5"; export type FigurePlacement = "inline" | "full-width" | "full-page" | "float-top"; @@ -24,6 +25,7 @@ export interface BookMetadata { export interface BookSettings { trim: TrimSize; bleed: boolean; + fonts: BookFonts; } export type CoverKind = "default" | "image"; @@ -149,14 +151,14 @@ export function createCover(): Cover { } const DEFAULT_METADATA: BookMetadata = { title: "Untitled", subtitle: "", author: "", isbn: "", language: "en" }; -const DEFAULT_SETTINGS: BookSettings = { trim: "6x9", bleed: true }; +const DEFAULT_SETTINGS: BookSettings = { trim: "6x9", bleed: true, fonts: DEFAULT_FONTS }; export function normalizeBook(book: Book): Book { const chapters = (Array.isArray(book.chapters) ? book.chapters : []).filter(Boolean); return { ...book, metadata: { ...DEFAULT_METADATA, ...book.metadata }, - settings: { ...DEFAULT_SETTINGS, ...book.settings }, + settings: { ...DEFAULT_SETTINGS, ...book.settings, fonts: { ...DEFAULT_FONTS, ...book.settings?.fonts } }, cover: book.cover ? { ...createCover(), ...book.cover } : createCover(), chapters: (chapters.length ? chapters : [createChapter()]).map((c) => c.updatedAt ? c : { ...c, updatedAt: Date.now() }, diff --git a/src/model/fonts.ts b/src/model/fonts.ts new file mode 100644 index 0000000..b425a50 --- /dev/null +++ b/src/model/fonts.ts @@ -0,0 +1,98 @@ +export type FontCategory = "serif" | "sans" | "display"; + +export interface BundledFont { + id: string; + label: string; + family: string; + category: FontCategory; + regular: string; + italic?: string; + weight: string; +} + +export const BUNDLED_FONTS: BundledFont[] = [ + { id: "literata", label: "Literata", family: "Literata", category: "serif", regular: "Literata-VF.ttf", italic: "Literata-Italic-VF.ttf", weight: "200 900" }, + { id: "eb-garamond", label: "EB Garamond", family: "EB Garamond", category: "serif", regular: "EBGaramond-VF.ttf", italic: "EBGaramond-Italic-VF.ttf", weight: "400 800" }, + { id: "lora", label: "Lora", family: "Lora", category: "serif", regular: "Lora-VF.ttf", italic: "Lora-Italic-VF.ttf", weight: "400 700" }, + { id: "source-serif", label: "Source Serif 4", family: "Source Serif 4", category: "serif", regular: "SourceSerif4-VF.ttf", italic: "SourceSerif4-Italic-VF.ttf", weight: "200 900" }, + { id: "fraunces", label: "Fraunces", family: "Fraunces", category: "display", regular: "Fraunces-VF.ttf", italic: "Fraunces-Italic-VF.ttf", weight: "100 900" }, + { id: "hanken", label: "Hanken Grotesk", family: "Hanken Grotesk", category: "sans", regular: "HankenGrotesk-VF.ttf", italic: "HankenGrotesk-Italic-VF.ttf", weight: "100 900" }, +]; + +export type FontRef = + | { kind: "bundled"; id: string } + | { kind: "system"; family: string }; + +export interface BookFonts { + body: FontRef; + heading: FontRef; +} + +export interface FontPairing { + id: string; + label: string; + body: FontRef; + heading: FontRef; +} + +const bundled = (id: string): FontRef => ({ kind: "bundled", id }); + +export const FONT_PAIRINGS: FontPairing[] = [ + { id: "quiet-press", label: "Quiet Press", body: bundled("literata"), heading: bundled("literata") }, + { id: "classic", label: "Classic", body: bundled("eb-garamond"), heading: bundled("eb-garamond") }, + { id: "editorial", label: "Editorial", body: bundled("source-serif"), heading: bundled("fraunces") }, + { id: "modern", label: "Modern", body: bundled("lora"), heading: bundled("hanken") }, + { id: "contrast", label: "Contrast", body: bundled("literata"), heading: bundled("hanken") }, +]; + +export const DEFAULT_FONTS: BookFonts = { body: bundled("literata"), heading: bundled("literata") }; + +const SERIF_FALLBACK = `Georgia, "Times New Roman", serif`; +const SANS_FALLBACK = `ui-sans-serif, system-ui, -apple-system, sans-serif`; + +export function bundledFont(id: string): BundledFont | undefined { + return BUNDLED_FONTS.find((f) => f.id === id); +} + +export function fontFamilyName(ref: FontRef): string { + if (ref.kind === "system") return ref.family; + return bundledFont(ref.id)?.family ?? "Literata"; +} + +export function fontLabel(ref: FontRef): string { + if (ref.kind === "system") return ref.family; + return bundledFont(ref.id)?.label ?? ref.id; +} + +export function fontStack(ref: FontRef): string { + if (ref.kind === "bundled") { + const font = bundledFont(ref.id); + if (!font) return SERIF_FALLBACK; + return `"${font.family}", ${font.category === "sans" ? SANS_FALLBACK : SERIF_FALLBACK}`; + } + return `"${ref.family}", ${SERIF_FALLBACK}`; +} + +export function refsEqual(a: FontRef, b: FontRef): boolean { + if (a.kind !== b.kind) return false; + return a.kind === "bundled" ? a.id === (b as { id: string }).id : a.family === (b as { family: string }).family; +} + +export function pairingFor(fonts: BookFonts): string | null { + const match = FONT_PAIRINGS.find((p) => refsEqual(p.body, fonts.body) && refsEqual(p.heading, fonts.heading)); + return match?.id ?? null; +} + +export function fontsUsed(fonts: BookFonts): { bundled: BundledFont[]; system: string[] } { + const usedBundled = new Map(); + const usedSystem = new Set(); + for (const ref of [fonts.body, fonts.heading]) { + if (ref.kind === "bundled") { + const font = bundledFont(ref.id); + if (font) usedBundled.set(font.id, font); + } else { + usedSystem.add(ref.family); + } + } + return { bundled: [...usedBundled.values()], system: [...usedSystem] }; +}