johnfactotum / foliate-js

Render e-books in the browser
https://johnfactotum.github.io/foliate-js/reader.html
MIT License
318 stars 43 forks source link

MathML does not render correctly #1

Closed smith558 closed 1 year ago

smith558 commented 1 year ago

Issue

MathML (https://www.w3.org/Math/) is not being rendered correctly.

Example

example code:

<div data-type="equation" id="simple_equation">
<h5><span class="label">Equation 5-7. </span>A simple equation example</h5>
<math display="block" xmlns="http://www.w3.org/1998/Math/MathML">
<mrow>
<mtext>y</mtext>
<mo>=</mo>
<msub><mi>θ</mi> <mn>0</mn> </msub>
<mo>+</mo>
<msub><mi>θ</mi> <mn>1</mn> </msub>
<mo>×</mo>
<mtext>variable</mtext>
</mrow>
</math>
</div>

should render as (demoed in Calibre):

image

but is:

image

johnfactotum commented 1 year ago

That looks like https://github.com/johnfactotum/foliate/issues/223.

Indeed, it even has the exact same attribute data-type="equation" as the book in that issue. So looks like the exact the same issue caused by the same CSS style used by the same publisher or authoring tool.

johnfactotum commented 1 year ago

Quick and dirty solution doing basically what I said in https://github.com/johnfactotum/foliate/issues/223#issuecomment-1279931523

diff --git a/epub.js b/epub.js
index 1d0867d..f427ba1 100644
--- a/epub.js
+++ b/epub.js
@@ -530,7 +530,12 @@ class Loader {
             /@import\s*["']([^"'\n]*?)["']/gi,
             (_, url) => this.loadHref(url, href, parents)
                 .then(url => `@import "${url}"`))
-        return replacedImports.replaceAll('-epub-', '')
+        const w = window?.innerWidth ?? 800
+        const h = window?.innerHeight ?? 600
+        const replacedVwVh = replacedImports
+            .replace(/(\d*\.?\d+)vw/g, (_, d) => parseFloat(d) * w / 100 + 'px')
+            .replace(/(\d*\.?\d+)vh/g, (_, d) => parseFloat(d) * h / 100 + 'px')
+        return replacedVwVh.replaceAll('-epub-', '')
     }
     // find & replace all possible relative paths for all assets without parsing
     replaceString(str, href, parents = []) {

Which works, Though it's not really ideal as we don't have a CSS parser. Edge case: the regex might match inside font-family or content (url()s are fine as they are replaced before this).

smith558 commented 1 year ago

Hi! So I've looked at the equations again but they're still not being rendered correctly. The issue was not only about the giant font size but also about special chars not being rendered at all, subscripts not applied and so on (the more complex equations are just an illegible mess). I'd propose reopening this issue. (I took the liberty to change the title back to address the issue as a whole)

smith558 commented 1 year ago

Thanks for the super fast feedback and initial fix proposition!

johnfactotum commented 1 year ago

Well, it depends on how well your browser renders MathML. Or does it render differently from when you open the page in the browser?

smith558 commented 1 year ago

Well, it depends on how well your browser renders MathML. Or does it render differently from when you open the page in the browser?

I didn't think of that. I thought this should be dependant on the renderer. MathML is rendered just fine on actual websites for me by the browser. I will try a few browsers and get back to you. I'm not sure what you mean by "renders differently from when you open the page in the browser" tho.

johnfactotum commented 1 year ago

I'm not sure what you mean by "renders differently from when you open the page in the browser" tho.

If it's an EPUB file, you can unzip the file, and open the page in the browser. If it's a Kindle file, you can unpack it with KindleUnpack and do the same. It seems Kindle doesn't support MathML so it's probably an EPUB.

Or you could just use inspector on the viewer, and copy and paste the markup to an webpage, and open it in the browser (this depends on the markup being parsed correctly, though, so would not help if there's a bug in the book parser/loader).

I guess it would be best if you can try to make a minimal reproducer. For example, here is one I made that contains the markup in your issue text: mathml.zip.

Opening this with the demo reader (as well as unzipping and opening the page directly in browser), the equation seems to be rendered correctly in Firefox and WebKit, but not Chromium.

johnfactotum commented 1 year ago

By the way, in Chromium, MathML support is currently behind a flag, chrome://flags/#enable-experimental-web-platform-features. When enabled, the example is rendered correctly.

Also, Calibre uses MathJax, I think, which I guess can also be used in Foliate. But as even Chromium has experimental MathML support now, probably better to just use the browser's native rendering.

johnfactotum commented 1 year ago

Closing this as it's really a Chromium bug, and one that's already fixed. And the fix will be shipped in a couple of months, in Chromium 109, according to the current shipping estimate. Or one can just enable the flag now.