fix(reader): 移动端 useBookFonts 不应强制阅读器字体到 body - #756
Open
k6G52m4Dz75W wants to merge 3 commits into
Open
k6G52m4Dz75W wants to merge 3 commits into
k6G52m4Dz75W wants to merge 3 commits into
Conversation
The mobile reader.template.html always emitted an unconditional
':root:not(.vrtl):not(.vltr) body { font-family: var(--readany-font-family)
!important }' in baseStyles. Even with useBookFonts enabled (default), this
pinned the reader font on body and overrode the book's own font-family set on
body, so embedded EPUB fonts never rendered on mobile.
Align with the desktop implementation: when useBookFonts is on, emit only a
zero-specificity ':where(html)' fallback so body INHERITS the reader font but
the book's own font-family (on html, body, or any element) wins where
specified. When disabled, force reader font on html/body and every descendant.
reader.html is regenerated by build:reader during prebuild, so only the
template source changes here.
Verified on Android emulator: book fonts now render with useBookFonts enabled.
The pre/code/kbd/samp monospace rule was unconditional !important on both ends, so with useBookFonts enabled (default) a book's own code font — e.g. an embedded @font-face on pre — never rendered, the same class of bug PR codedogQBY#756 fixed for the body font. The monospace rule now swaps sides with the same toggle: - useBookFonts on: :where(pre, code, kbd, samp) at zero specificity with no !important, so any book declaration wins; without one the monospace chain still applies as the fallback. - useBookFonts off (override): html body :is(pre, code, kbd, samp) with !important. !important alone is not enough: specificity still breaks ties between important author declarations, so a plain 'pre, code, kbd' at (0,0,1) loses to an authored 'body pre { ... !important }' at (0,0,2); (0,0,3) outranks both. Mirrors readest#6047 (code-font cascade hardening) on top of the appearance-branch :where approach. Verified the resolved cascade in headless Chromium across 7 scenarios: book code/body fonts win when honored, fallbacks still apply, and the override beats authored !important rules at equal and higher specificity on both ends.
k6G52m4Dz75W
force-pushed
the
fix/mobile-usebookfonts-clean
branch
from
September 11, 2026 15:56
cf03cf2 to
1e1e521
Compare
… contract test
Addresses the 6 findings from the OCR review of the code-font work:
- Restore the horizontal-writing guard (:root:not(.vrtl):not(.vltr)) on
the forced overrides in the mobile template. The pre-existing rules
were scoped to horizontal documents and the vertical branch must keep
its own behavior — the unscoped 'html, body' / 'body *' rules from the
previous commit leaked into vertical mode (OCR medium).
- Inner code/kbd/samp inside a pre now get a zero-specificity
'font-family: inherit' instead of just being excluded from the
monospace fallback: the UA stylesheet's own 'code { font-family:
monospace }' is a direct declaration, which beats inheritance, so
exclusion alone still cut '<pre><code>' off from the book's font
declared on pre (OCR low, verified in a real engine). Any author
declaration on the element still wins the inherit.
- Add usebook-fonts-contract.test.ts pinning the rule shapes for both
toggle states across the template, the generated artifact, and the
desktop generator — the triplicated recipe previously had no
automated coverage and could drift silently (OCR low x2).
Verified in headless Chromium: 15 scenarios pass covering both toggle
states, inner-code inheritance, UA-default interception, the vertical
guard, and override-vs-authored-important at equal and higher
specificity.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
问题
移动端阅读器(
reader.template.html)的baseStyles中有一条无条件规则:即使
useBookFonts处于启用状态(默认开启),这条规则仍把阅读器字体强制应用到body,覆盖书在body上指定的font-family。因此 epub 嵌入字体在移动端从不生效(很多 epub 在body上指定字体)。桌面端已正确处理(
useBookFonts启用时用:where(html)零特异性兜底,书字体优先),移动端未对齐。修复
对齐桌面端实现(
FoliateViewer.tsx):useBookFonts启用(默认):只注入:where(html) { font-family: var(--readany-font-family); }—— 零特异性,只影响html;body继承 html 字体,书在html/body/任何元素上指定的字体优先。useBookFonts关闭:强制html, body+ 所有后代使用阅读器字体。reader.html由build:reader在 prebuild 时自动生成,故本次仅改动模板源码reader.template.html。验证
body { font-family: "BookEmbeddedFont" }时,"Reader Font", sans-serif(阅读器字体覆盖书)BookEmbeddedFont, serif(书嵌入字体生效)useBookFonts启用时书字体正常渲染。说明
useBookFonts功能的移动端 bug 修复,仅改动 1 个文件(reader.template.html)。变更增补 1:代码字体层叠修复(pre/code/kbd/samp)
body 字体之外,审查中发现等宽规则
pre, code, kbd, samp { ... !important }在双端都是无条件
!important——同一族 bug:useBookFonts 开启(默认)时,书自带的代码字体(如嵌入的 @font-face 等宽字体)同样永远无法渲染。
等宽规则现改为随 useBookFonts 开关切换方向:
:where(pre, :not(pre) > code, :not(pre) > kbd, :not(pre) > samp)零特异性、无
!important——书的任何声明都赢,未声明时等宽链兜底;html body :is(pre, code, kbd, samp)+!important。仅
!important不够:特异性在 important 声明之间仍然生效,裸pre, code, kbd(0,0,1)会输给书内body pre { ... !important }(0,0,2);(0,0,3) 同时压过两者。
方案对齐 readest#6047 的代码字体加固(其测试思路也被借鉴:在真实引擎中断言
resolved cascade,而非检查选择器文本)。
变更增补 2:代码审查修复(垂直守卫 / 内层继承 / 契约测试)
经 open-code-review 两轮审查后落地三项修正:
:root:not(.vrtl):not(.vltr)前缀(与既有规则一致)。垂直排版的文档保持原有行为,不受本 PR 影响。
<pre><code>内层继承断裂:UA 样式表自带code { font-family: monospace }直接声明,而任何直接声明都压过继承,所以书在
pre上声明的嵌入代码字体传不到内层code。现为内层元素注入零特异性
:where(pre :is(code, kbd, samp)) { font-family: inherit }恢复继承链;书内任何针对元素的声明仍然优先于它。独立行内 code 不受影响,
保持等宽兜底。
usebook-fonts-contract.test.ts:将两态规则形状在三处副本(模板 / 再生产物 / 桌面生成器)中的一致性钉死,防止这类
特异性配方在未来被单点修改而静默漂移。
验证增补
<pre><code>继承、UA 默认样式拦截、垂直守卫、覆盖与书内!important的特异性决胜(同级与更高级)、书内 code 级声明压过inherit 规则;
tsc --noEmit干净;