forked from akai/readest
PR #4383 inlined custom `@font-face` rules at the very front of the iframe stylesheet, ahead of the `@namespace epub` declaration that lived inside `getPageLayoutStyles`. Per the CSS spec a `@namespace` rule is only honored when it precedes every style and `@font-face` rule; a misplaced one is silently ignored. That dropped the namespaced `aside[epub|type~="footnote"]` hide rule, so EPUBs whose footnote `<aside>` carries a `border: 3px #333 double` rendered a stray horizontal line below the annotation marker — but only for users who had custom fonts loaded (otherwise `customFontFaces` is empty and `@namespace` stayed first). Hoist the `@namespace` declaration to the very start of the assembled stylesheet, before the inlined custom `@font-face` rules, and drop it from `getPageLayoutStyles`. Custom faces still precede the `--serif`/`--sans-serif` font lists that reference them, preserving #4383's first-paint behavior. Verified in Chromium against the reported book's CSS: the aside goes from `display: block` (3px double border visible) back to `display: none`. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -790,13 +790,26 @@ describe('custom @font-face inlining (via getStyles)', () => {
|
||||
expect(css).toContain('blob:http://localhost/my-test-font');
|
||||
});
|
||||
|
||||
it('inlines the @font-face rules ahead of the rest of the stylesheet', () => {
|
||||
it('keeps @namespace epub ahead of every @font-face rule (#4438)', () => {
|
||||
const vs = makeViewSettings();
|
||||
const css = getStyles(vs, theme, [makeCustomFont()]);
|
||||
// Paginator writes this CSS into the iframe before its first paint,
|
||||
// so the custom @font-face must precede the font-family declarations
|
||||
// that reference it (layout styles begin with `@namespace epub`).
|
||||
expect(css.indexOf('@font-face')).toBeLessThan(css.indexOf('@namespace epub'));
|
||||
// A `@namespace` rule is only honored when it precedes all style and
|
||||
// `@font-face` rules; a misplaced one is silently ignored, which drops
|
||||
// the namespaced `aside[epub|type~="footnote"]` selector and reveals the
|
||||
// footnote aside's border as a stray horizontal line (#4438). The custom
|
||||
// `@font-face` rules must therefore come after the namespace declaration.
|
||||
expect(css).toContain('@namespace epub');
|
||||
expect(css).toContain('@font-face');
|
||||
expect(css.indexOf('@namespace epub')).toBeLessThan(css.indexOf('@font-face'));
|
||||
});
|
||||
|
||||
it('still inlines custom @font-face ahead of the font-family declarations', () => {
|
||||
const vs = makeViewSettings();
|
||||
const css = getStyles(vs, theme, [makeCustomFont()]);
|
||||
// Paginator writes this CSS into the iframe before its first paint, so the
|
||||
// custom `@font-face` rules should still precede the `--serif`/`--sans-serif`
|
||||
// font lists that reference them.
|
||||
expect(css.indexOf('@font-face')).toBeLessThan(css.indexOf('--serif:'));
|
||||
});
|
||||
|
||||
it('emits one @font-face per loaded font', () => {
|
||||
|
||||
@@ -347,7 +347,6 @@ const getPageLayoutStyles = (
|
||||
writingMode: string,
|
||||
vertical: boolean,
|
||||
) => `
|
||||
@namespace epub "http://www.idpf.org/2007/ops";
|
||||
html {
|
||||
--margin-top: ${marginTop}px;
|
||||
--margin-right: ${marginRight}px;
|
||||
@@ -867,7 +866,13 @@ export const getStyles = (
|
||||
const warichuStyles = getWarichuStyles();
|
||||
const rubyStyles = getRubyStyles();
|
||||
const userStylesheet = viewSettings.userStylesheet!;
|
||||
return `${customFontFaces}\n${pageLayoutStyles}\n${paragraphLayoutStyles}\n${fontStyles}\n${colorStyles}\n${translationStyles}\n${warichuStyles}\n${rubyStyles}\n${userStylesheet}`;
|
||||
// The `@namespace` declaration must lead the stylesheet: a `@namespace` rule
|
||||
// placed after any style or `@font-face` rule is invalid and silently ignored,
|
||||
// which drops the namespaced `aside[epub|type~="footnote"]` selector and lets
|
||||
// the footnote aside's border show as a stray horizontal line (#4438). Keep it
|
||||
// ahead of the inlined custom `@font-face` rules.
|
||||
const epubNamespace = `@namespace epub "http://www.idpf.org/2007/ops";`;
|
||||
return `${epubNamespace}\n${customFontFaces}\n${pageLayoutStyles}\n${paragraphLayoutStyles}\n${fontStyles}\n${colorStyles}\n${translationStyles}\n${warichuStyles}\n${rubyStyles}\n${userStylesheet}`;
|
||||
};
|
||||
|
||||
// Build a CSS chunk of `@font-face` rules for the given user custom
|
||||
|
||||
Reference in New Issue
Block a user