mirror of
https://github.com/bookorbit/bookorbit.git
synced 2026-11-03 00:11:37 -06:00
fix(reader): scale publisher font sizes with the reader text size
Rewrite absolute publisher font sizes (keywords and px/pt lengths) as each EPUB loads so they follow the reader's root size, falling back to the original value when the reader applies no styles. Skip fixed-layout books and SVG content, and cover the rewrite and the foliate loader hook with regression tests. Fixes #1276
This commit is contained in:
@@ -11,6 +11,7 @@ const NS = {
|
||||
NCX: 'http://www.daisy.org/z3986/2005/ncx/',
|
||||
XLINK: 'http://www.w3.org/1999/xlink',
|
||||
SMIL: 'http://www.w3.org/ns/SMIL',
|
||||
SVG: 'http://www.w3.org/2000/svg',
|
||||
}
|
||||
|
||||
const MIME = {
|
||||
@@ -118,6 +119,11 @@ const resolveURL = (url, relativeTo) => {
|
||||
|
||||
const isExternal = (uri) => /^(?!blob)\w+:/i.test(uri)
|
||||
|
||||
const isInSVG = (el) => {
|
||||
for (let node = el; node; node = node.parentElement) if (node.namespaceURI === NS.SVG) return true
|
||||
return false
|
||||
}
|
||||
|
||||
// like `path.relative()` in Node.js
|
||||
const pathRelative = (from, to) => {
|
||||
if (!from) return to
|
||||
@@ -958,16 +964,32 @@ class Loader {
|
||||
),
|
||||
)
|
||||
// replace inline styles
|
||||
for (const el of doc.querySelectorAll('style')) if (el.textContent) el.textContent = await this.replaceCSS(el.textContent, href, parents)
|
||||
for (const el of doc.querySelectorAll('[style]')) el.setAttribute('style', await this.replaceCSS(el.getAttribute('style'), href, parents))
|
||||
for (const el of doc.querySelectorAll('style')) {
|
||||
if (!el.textContent) continue
|
||||
const css = await this.replaceCSS(el.textContent, href, parents)
|
||||
el.textContent = isInSVG(el) ? css : await this.transformCSS(css, href)
|
||||
}
|
||||
for (const el of doc.querySelectorAll('[style]')) {
|
||||
const css = await this.replaceCSS(el.getAttribute('style'), href, parents)
|
||||
el.setAttribute('style', isInSVG(el) ? css : await this.transformCSS(css, href))
|
||||
}
|
||||
// TODO: replace inline scripts? probably not worth the trouble
|
||||
const result = new XMLSerializer().serializeToString(doc)
|
||||
return this.createURL(href, result, item.mediaType, parent)
|
||||
}
|
||||
|
||||
const result = mediaType === MIME.CSS ? await this.replaceCSS(str, href, parents) : await this.replaceString(str, href, parents)
|
||||
const result =
|
||||
mediaType === MIME.CSS ? await this.transformCSS(await this.replaceCSS(str, href, parents), href) : await this.replaceString(str, href, parents)
|
||||
return this.createURL(href, result, mediaType, parent)
|
||||
}
|
||||
// Lets the host rewrite book CSS before it is used. CSS that styles SVG is never passed here,
|
||||
// because its sizes belong to the drawing's coordinate system rather than to the text.
|
||||
async transformCSS(css, href) {
|
||||
const detail = { data: css }
|
||||
Object.defineProperty(detail, 'name', { value: href })
|
||||
this.eventTarget.dispatchEvent(new CustomEvent('css', { detail }))
|
||||
return await detail.data
|
||||
}
|
||||
async replaceCSS(str, href, parents = []) {
|
||||
// For url() references, use direct URLs for fonts and images (lazy loading)
|
||||
// This avoids fetching all fonts/images upfront - browser fetches on-demand
|
||||
|
||||
Reference in New Issue
Block a user