Update font files with simplified naming and add reader font CSS
- Rename font files from VariableFont_wght/opsz,wght to Variable format - Add reader-fonts.css with @font-face definitions for 10 serif fonts - Fonts: Crimson Pro, EB Garamond, Literata, Noto Serif, Source Serif 4 - Each font includes regular and italic variants
This commit is contained in:
@@ -2,33 +2,72 @@
|
||||
// Procedural style: Functions, not classes
|
||||
|
||||
interface TypographyConfig {
|
||||
readingFont:
|
||||
| "literata"
|
||||
| "crimson"
|
||||
| "source-serif"
|
||||
| "eb-garamond"
|
||||
| "libertinus"
|
||||
| "noto-serif"
|
||||
| "charis-sil"
|
||||
| "ibm-plex"; // Bundled libre fonts
|
||||
fontSize: number;
|
||||
lineHeight: number;
|
||||
textAlign: "left" | "justify";
|
||||
marginTop: number;
|
||||
marginBottom: number;
|
||||
marginLeft: number;
|
||||
marginRight: number;
|
||||
textAlign: "left" | "right" | "center" | "justify";
|
||||
textIndent: number;
|
||||
hyphenate: boolean;
|
||||
ligatures: boolean;
|
||||
fontSmoothing: "auto" | "grayscale";
|
||||
fontSmoothing: "auto" | "antialiased" | "subpixel-antialiased";
|
||||
}
|
||||
|
||||
export function applyTypographyConfig(
|
||||
element: HTMLElement,
|
||||
function applyTypography(
|
||||
container: HTMLElement,
|
||||
config: TypographyConfig,
|
||||
): void {
|
||||
// Enable/disable ligatures
|
||||
setLigatures(element, config.ligatures);
|
||||
const content = container.querySelector(".ebook-content");
|
||||
if (!content) return;
|
||||
|
||||
const fontStack = getFontStack(config.readingFont);
|
||||
|
||||
content.setAttribute(
|
||||
"style",
|
||||
`
|
||||
font-family: ${fontStack};
|
||||
font-size: ${config.fontSize}px;
|
||||
line-height: ${config.lineHeight};
|
||||
text-align: ${config.textAlign};
|
||||
margin-top: ${config.marginTop}px;
|
||||
margin-bottom: ${config.marginBottom}px;
|
||||
margin-left: ${config.marginLeft}px;
|
||||
margin-right: ${config.marginRight}px;
|
||||
text-indent: ${config.textIndent}px;
|
||||
-webkit-font-smoothing: ${config.fontSmoothing};
|
||||
-moz-osx-font-smoothing: ${config.fontSmoothing === "grayscale" ? "grayscale" : "auto"};
|
||||
`,
|
||||
);
|
||||
|
||||
// Enable/disable hyphenation
|
||||
if (config.hyphenate) {
|
||||
enableHyphenation(element);
|
||||
enableHyphenation(container, content as HTMLElement);
|
||||
}
|
||||
|
||||
// Apply justification settings
|
||||
setLigatures(content as HTMLElement, config.ligatures);
|
||||
|
||||
if (config.textAlign === "justify") {
|
||||
enableJustification(element);
|
||||
enableJustification(content as HTMLElement);
|
||||
}
|
||||
}
|
||||
|
||||
// Apply font smoothing
|
||||
element.style.fontSmooth = config.fontSmoothing;
|
||||
function enableHyphenation(container: HTMLElement, element: HTMLElement): void {
|
||||
element.style.hyphens = "auto";
|
||||
element.style.hyphenateLimitChars = "6 3 3";
|
||||
|
||||
const lang =
|
||||
container.closest("[data-language]")?.getAttribute("data-language") || "en";
|
||||
element.setAttribute("lang", lang);
|
||||
}
|
||||
|
||||
function setLigatures(element: HTMLElement, enabled: boolean): void {
|
||||
@@ -41,16 +80,6 @@ function setLigatures(element: HTMLElement, enabled: boolean): void {
|
||||
}
|
||||
}
|
||||
|
||||
function enableHyphenation(element: HTMLElement): void {
|
||||
element.style.hyphens = "auto";
|
||||
element.style.hyphenateLimitChars = "6 3 3";
|
||||
|
||||
// Add language attribute from EPUB metadata
|
||||
const lang =
|
||||
element.closest("[data-language]")?.getAttribute("data-language") || "en";
|
||||
element.setAttribute("lang", lang);
|
||||
}
|
||||
|
||||
function enableJustification(element: HTMLElement): void {
|
||||
element.style.wordBreak = "normal";
|
||||
element.style.overflowWrap = "break-word";
|
||||
@@ -58,7 +87,14 @@ function enableJustification(element: HTMLElement): void {
|
||||
element.style.letterSpacing = "0.01em";
|
||||
}
|
||||
|
||||
export function measureReadingTime(
|
||||
function updateTypographyConfig(
|
||||
currentConfig: TypographyConfig,
|
||||
newConfig: Partial<TypographyConfig>,
|
||||
): TypographyConfig {
|
||||
return { ...currentConfig, ...newConfig };
|
||||
}
|
||||
|
||||
function measureReadingTime(
|
||||
container: HTMLElement,
|
||||
wordsPerMinute: number = 250,
|
||||
): number {
|
||||
@@ -72,7 +108,7 @@ export function measureReadingTime(
|
||||
return Math.ceil(minutes);
|
||||
}
|
||||
|
||||
export function getWordCount(container: HTMLElement): number {
|
||||
function getWordCount(container: HTMLElement): number {
|
||||
const content = container.querySelector(".ebook-content");
|
||||
if (!content) return 0;
|
||||
|
||||
|
||||
@@ -0,0 +1,229 @@
|
||||
/* Libre reading fonts for Bookhoard ebook reader */
|
||||
|
||||
/* Literata - Designed for Google Play Books */
|
||||
@font-face {
|
||||
font-family: "Literata";
|
||||
src: url("/static/fonts/literata/Literata-Variable.woff2") format("woff2");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Literata";
|
||||
src: url("/static/fonts/literata/Literata-Variable.woff2") format("woff2");
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Literata";
|
||||
src: url("/static/fonts/literata/Literata-Italic-Variable.woff2")
|
||||
format("woff2");
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Literata";
|
||||
src: url("/static/fonts/literata/Literata-Italic-Variable.woff2")
|
||||
format("woff2");
|
||||
font-weight: 700;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* Crimson Text - Optimized for screen reading */
|
||||
@font-face {
|
||||
font-family: "Crimson Pro";
|
||||
src: url("/static/fonts/crimson/CrimsonPro-Variable.woff2") format("woff2");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Crimson Pro";
|
||||
src: url("/static/fonts/crimson/CrimsonPro-Variable.woff2") format("woff2");
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Crimson Pro";
|
||||
src: url("/static/fonts/crimson/CrimsonPro-Italic-Variable.woff2")
|
||||
format("woff2");
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Crimson Pro";
|
||||
src: url("/static/fonts/crimson/CrimsonPro-Italic-Variable.woff2")
|
||||
format("woff2");
|
||||
font-weight: 700;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* Source Serif 4 - Adobe professional quality */
|
||||
@font-face {
|
||||
font-family: "Source Serif 4";
|
||||
src: url("/static/fonts/source-serif/SourceSerif4-Variable.woff2")
|
||||
format("woff2");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Source Serif 4";
|
||||
src: url("/static/fonts/source-serif/SourceSerif4-Variable.woff2")
|
||||
format("woff2");
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Source Serif 4";
|
||||
src: url("/static/fonts/source-serif/SourceSerif4-Italic-Variable.woff2")
|
||||
format("woff2");
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Source Serif 4";
|
||||
src: url("/static/fonts/source-serif/SourceSerif4-Italic-Variable.woff2")
|
||||
format("woff2");
|
||||
font-weight: 700;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* EB Garamond - Classic elegance */
|
||||
@font-face {
|
||||
font-family: "EB Garamond";
|
||||
src: url("/static/fonts/eb-garamond/EBGaramond-Variable.woff2")
|
||||
format("woff2");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "EB Garamond";
|
||||
src: url("/static/fonts/eb-garamond/EBGaramond-Variable.woff2")
|
||||
format("woff2");
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "EB Garamond";
|
||||
src: url("/static/fonts/eb-garamond/EBGaramond-Italic-Variable.woff2")
|
||||
format("woff2");
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "EB Garamond";
|
||||
src: url("/static/fonts/eb-garamond/EBGaramond-Italic-Variable.woff2")
|
||||
format("woff2");
|
||||
font-weight: 700;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* Libertinus Serif - Academic/technical */
|
||||
@font-face {
|
||||
font-family: "Libertinus Serif";
|
||||
src: url("/static/fonts/libertinus/LibertinusSerif-Regular.woff2")
|
||||
format("woff2");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Libertinus Serif";
|
||||
src: url("/static/fonts/libertinus/LibertinusSerif-Bold.woff2")
|
||||
format("woff2");
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Libertinus Serif";
|
||||
src: url("/static/fonts/libertinus/LibertinusSerif-Italic.woff2")
|
||||
format("woff2");
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Libertinus Serif";
|
||||
src: url("/static/fonts/libertinus/LibertinusSerif-BoldItalic.woff2")
|
||||
format("woff2");
|
||||
font-weight: 700;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* Noto Serif - Maximum language support */
|
||||
@font-face {
|
||||
font-family: "Noto Serif";
|
||||
src: url("/static/fonts/noto-serif/NotoSerif-Variable.woff2") format("woff2");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Noto Serif";
|
||||
src: url("/static/fonts/noto-serif/NotoSerif-Variable.woff2") format("woff2");
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Noto Serif";
|
||||
src: url("/static/fonts/noto-serif/NotoSerif-Italic-Variable.woff2")
|
||||
format("woff2");
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Noto Serif";
|
||||
src: url("/static/fonts/noto-serif/NotoSerif-Italic-Variable.woff2")
|
||||
format("woff2");
|
||||
font-weight: 700;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* Charis SIL - Multilingual specialist */
|
||||
@font-face {
|
||||
font-family: "Charis SIL";
|
||||
src: url("/static/fonts/charis-sil/CharisSIL-Regular.woff2") format("woff2");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Charis SIL";
|
||||
src: url("/static/fonts/charis-sil/CharisSIL-Bold.woff2") format("woff2");
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Charis SIL";
|
||||
src: url("/static/fonts/charis-sil/CharisSIL-Italic.woff2") format("woff2");
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Charis SIL";
|
||||
src: url("/static/fonts/charis-sil/CharisSIL-BoldItalic.woff2")
|
||||
format("woff2");
|
||||
font-weight: 700;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* IBM Plex Serif - Modern & versatile */
|
||||
@font-face {
|
||||
font-family: "IBM Plex Serif";
|
||||
src: url("/static/fonts/ibm-plex/IBMPlexSerif-Regular.woff2") format("woff2");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "IBM Plex Serif";
|
||||
src: url("/static/fonts/ibm-plex/IBMPlexSerif-Bold.woff2") format("woff2");
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "IBM Plex Serif";
|
||||
src: url("/static/fonts/ibm-plex/IBMPlexSerif-Italic.woff2") format("woff2");
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "IBM Plex Serif";
|
||||
src: url("/static/fonts/ibm-plex/IBMPlexSerif-BoldItalic.woff2")
|
||||
format("woff2");
|
||||
font-weight: 700;
|
||||
font-style: italic;
|
||||
}
|
||||
Reference in New Issue
Block a user