Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Options to choose different LaTeX rendering services (p.e. with svg output) and offline conversion with MathJax #144

Open
alexpacini opened this issue Nov 14, 2013 · 33 comments

Comments

@alexpacini
Copy link

Hi,
I would like to suggest some enhancements to the LaTeX section.

  • A drop-down menu to choose from multiple services: I suggest to add
<img src="https://latex.codecogs.com/svg.latex?{urlmathcode}" alt="{mathcode}">

It works pretty well and the output is in svg format.

  • I would like to have the possibility to choose from pure TeX delimiters as
    $ ... $ and $$ ... $$ for the centred environment
    and pure LaTeX delimiters as
    \( ... )\ and \[ ... \] for the centred environment
  • Can you strip out the white space between the opening delimiter and the first LaTeX formula character? (If I leave the space, I don't get the formula rendered)
  • Is it possible to use MathJax for converting LaTeX to svg? (or even to another format, for example chosen by a check box).
    I have seen something interesting on MathJax's Website especially with the configuration TeX-AMS-MML_SVG.js

Thank You,
Alex

@joanpau
Copy link

joanpau commented Nov 26, 2013

+1 for MathJax rendering support.
But, is it possible to support it at all?

@alexpacini
Copy link
Author

I think it is possible only by using svg, the "usual way" is certainly not supported by Gmail and family.

@joanpau
Copy link

joanpau commented Nov 29, 2013

So there is no way of using Mathjax in GMail with web fonts or utf characters (like here) instead of images. Is that true?

@alexpacini
Copy link
Author

Well, actually I am not sure, but when I see HTML-with-CSS to lay out the mathematics I ever think that probably there will be some problems with the email providers. I said svg because it should be the easy way.
A further investigation, I am sure, could be useful.

@adam-p
Copy link
Owner

adam-p commented Nov 29, 2013

I've been fooling around with this a bit, but I haven't found a solution I'm very happy with. I'll note what I've found below. Note that I've only tested with Gmail-in-Chrome and Thunderbird. Also note that I'm not a math guy and I don't really know much about LaTeX/TeX, SVG, Mathjax, etc.

SVG images loaded remotely seem to work fine

That means you can have SVG math by setting this in Markdown Here's math option:

<img src="https://latex.codecogs.com/svg.latex?{urlmathcode}" alt="{mathcode}">

There are at least a few shortcomings with this, mostly privacy related:

  1. It means Codecogs gets all your super secret math formulae. (Whereas the default math renderer is Google, so if you use Gmail there isn't an additional organization privy to your secret.)
  2. In theory, Codecogs would be able to link you to your friends. If you render a unique-ish formula on your computer, email it, and then your friend renders it on her computer, then Codecogs can reasonably assume that the person at your IP address is working with the person at your friend's IP address on that formula. I'm not saying they would, of course, but they could. And they could use cookies to connect all of the formulae you render on a particular computer+browser together.
  3. I haven't read Codecogs' terms of use.

And to repeat: I haven't tested anywhere else.

Inline SVG does not work

Gmail-web strips it out before sending and won't render it if it receives it. With Tbird you can't actually see it in the compose window after rendering, but it does send and you can see it after receiving it. For the record, here's the SVG I used (just a \Lambda):

<svg height='12.3' preserveAspectRatio='xMinYMin' version='1.1' viewBox='0 0 14.6873 12.3' width='14.6873' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'><defs><path d='M5.172 -8.352C5.088 -8.52 5.064 -8.568 4.896 -8.568C4.716 -8.568 4.692 -8.52 4.608 -8.352L0.6 -0.24C0.576 -0.204 0.552 -0.132 0.552 -0.084C0.552 -0.012 0.564 -0 0.804 -0H8.976C9.216 -0 9.228 -0.012 9.228 -0.084C9.228 -0.132 9.204 -0.204 9.18 -0.24L5.172 -8.352ZM4.524 -7.464L7.8 -0.828H1.26L4.524 -7.464Z' id='g21'/></defs><g id='page1' transform='matrix(1.5 0 0 1.5 -84.937 -86.7)'><use x='56.6248' xlink:href='#g21' y='66'/></g></svg>

Here's a pretty comprehensive test of SVG in various email clients: http://conference.createsend.com/screens/r/06A83737A07C505E. Mixed results, but not good enough.

SVG as img with data URI... is weird

For testing I used this:

<img src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0nMS4wJyBlbmNvZGluZz0nSVNPLTg4NTktMSc/Pg0KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4NCjxzdmcgaGVpZ2h0PScxMi4zJyBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSd4TWluWU1pbicgdmVyc2lvbj0nMS4xJyB2aWV3Qm94PScwIDAgMTQuNjg3MyAxMi4zJyB3aWR0aD0nMTQuNjg3MycgeG1sbnM9J2h0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnJyB4bWxuczp4bGluaz0naHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayc+PGRlZnM+PHBhdGggZD0nTTUuMTcyIC04LjM1MkM1LjA4OCAtOC41MiA1LjA2NCAtOC41NjggNC44OTYgLTguNTY4QzQuNzE2IC04LjU2OCA0LjY5MiAtOC41MiA0LjYwOCAtOC4zNTJMMC42IC0wLjI0QzAuNTc2IC0wLjIwNCAwLjU1MiAtMC4xMzIgMC41NTIgLTAuMDg0QzAuNTUyIC0wLjAxMiAwLjU2NCAtMCAwLjgwNCAtMEg4Ljk3NkM5LjIxNiAtMCA5LjIyOCAtMC4wMTIgOS4yMjggLTAuMDg0QzkuMjI4IC0wLjEzMiA5LjIwNCAtMC4yMDQgOS4xOCAtMC4yNEw1LjE3MiAtOC4zNTJaTTQuNTI0IC03LjQ2NEw3LjggLTAuODI4SDEuMjZMNC41MjQgLTcuNDY0WicgaWQ9J2cyMScvPjwvZGVmcz48ZyBpZD0ncGFnZTEnIHRyYW5zZm9ybT0nbWF0cml4KDEuNSAwIDAgMS41IC04NC45MzcgLTg2LjcpJz48dXNlIHg9JzU2LjYyNDgnIHhsaW5rOmhyZWY9JyNnMjEnIHk9JzY2Jy8+PC9nPjwvc3ZnPg==" />

Which is a base64 encoding of this:

<?xml version='1.0' encoding='ISO-8859-1'?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg height='12.3' preserveAspectRatio='xMinYMin' version='1.1' viewBox='0 0 14.6873 12.3' width='14.6873' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'><defs><path d='M5.172 -8.352C5.088 -8.52 5.064 -8.568 4.896 -8.568C4.716 -8.568 4.692 -8.52 4.608 -8.352L0.6 -0.24C0.576 -0.204 0.552 -0.132 0.552 -0.084C0.552 -0.012 0.564 -0 0.804 -0H8.976C9.216 -0 9.228 -0.012 9.228 -0.084C9.228 -0.132 9.204 -0.204 9.18 -0.24L5.172 -8.352ZM4.524 -7.464L7.8 -0.828H1.26L4.524 -7.464Z' id='g21'/></defs><g id='page1' transform='matrix(1.5 0 0 1.5 -84.937 -86.7)'><use x='56.6248' xlink:href='#g21' y='66'/></g></svg>

Which is what you get from curl "https://latex.codecogs.com/svg.latex?\\Delta" minus the script tag. (Because if this doesn't work without the script tag, then it doesn't work.)

Sending from Chrome: Renders okay in compose. Is not stripped from message on send. Does not render in Chrome when viewing. Does render in Tbird when viewing.

Sending from Tbird: Renders okay in compose. Does render in Chrome when viewing. Does not render in Tbird when viewing.

Yes, you read that right. If you send from Chrome, you can read it in Tbird but not Chrome. If you send from Tbird, you can read it in Chrome but not Tbird. Hilarious.

When sending from Chrome the raw email looks like this:

Content-Type: multipart/alternative; boundary=089e0111da24160ebf04ec57de1d

--089e0111da24160ebf04ec57de1d
Content-Type: text/plain; charset=UTF-8



--089e0111da24160ebf04ec57de1d
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div class=3D"markdown-here-wrapper" id=3D"markdown-here-w=
rapper-705721" style><p style=3D"margin:1.2em 0px!important"><img src=3D"da=
ta:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0nMS4wJyBlbmNvZGluZz0nSVNPLTg4NTk=
tMSc/Pg0KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaH=
R0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4NCjxzdmcga=
GVpZ2h0PScxMi4zJyBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSd4TWluWU1pbicgdmVyc2lvbj0nMS4x=
JyB2aWV3Qm94PScwIDAgMTQuNjg3MyAxMi4zJyB3aWR0aD0nMTQuNjg3MycgeG1sbnM9J2h0dHA=
6Ly93d3cudzMub3JnLzIwMDAvc3ZnJyB4bWxuczp4bGluaz0naHR0cDovL3d3dy53My5vcmcvMT=
k5OS94bGluayc+PGRlZnM+PHBhdGggZD0nTTUuMTcyIC04LjM1MkM1LjA4OCAtOC41MiA1LjA2N=
CAtOC41NjggNC44OTYgLTguNTY4QzQuNzE2IC04LjU2OCA0LjY5MiAtOC41MiA0LjYwOCAtOC4z=
NTJMMC42IC0wLjI0QzAuNTc2IC0wLjIwNCAwLjU1MiAtMC4xMzIgMC41NTIgLTAuMDg0QzAuNTU=
yIC0wLjAxMiAwLjU2NCAtMCAwLjgwNCAtMEg4Ljk3NkM5LjIxNiAtMCA5LjIyOCAtMC4wMTIgOS=
4yMjggLTAuMDg0QzkuMjI4IC0wLjEzMiA5LjIwNCAtMC4yMDQgOS4xOCAtMC4yNEw1LjE3MiAtO=
C4zNTJaTTQuNTI0IC03LjQ2NEw3LjggLTAuODI4SDEuMjZMNC41MjQgLTcuNDY0WicgaWQ9J2cy=
MScvPjwvZGVmcz48ZyBpZD0ncGFnZTEnIHRyYW5zZm9ybT0nbWF0cml4KDEuNSAwIDAgMS41IC0=
4NC45MzcgLTg2LjcpJz48dXNlIHg9JzU2LjYyNDgnIHhsaW5rOmhyZWY9JyNnMjEnIHk9JzY2Jy=
8+PC9nPjwvc3ZnPg=3D=3D"></p>

</div></div>

--089e0111da24160ebf04ec57de1d--

When sending from Tbird it looks like this:

Content-Type: multipart/alternative;
 boundary="------------010600010002020304090107"

This is a multi-part message in MIME format.
--------------010600010002020304090107
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit


--------------010600010002020304090107
Content-Type: multipart/related;
 boundary="------------010105080606030104090106"


--------------010105080606030104090106
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

<html>
  <head>

    <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <div style=""
data-md-original="%26lt%3Bimg%20src%3D%22data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPD94bWwgdmVyc2lvbj0nMS4wJyBlbmNvZGluZz0nSVNPLTg4NTktMSc%2FPg0KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4NCjxzdmcgaGVpZ2h0PScxMi4zJyBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSd4TWluWU1pbicgdmVyc2lvbj0nMS4xJyB2aWV3Qm94PScwIDAgMTQuNjg3MyAxMi4zJyB3aWR0aD0nMTQuNjg3MycgeG1sbnM9J2h0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnJyB4bWxuczp4bGluaz0naHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayc%2BPGRlZnM%2BPHBhdGggZD0nTTUuMTcyIC04LjM1MkM1LjA4OCAtOC41MiA1LjA2NCAtOC41NjggNC44OTYgLTguNTY4QzQuNzE2IC04LjU2OCA0LjY5MiAtOC41MiA0LjYwOCAtOC4zNTJMMC42IC0wLjI0QzAuNTc2IC0wLjIwNCAwLjU1MiAtMC4xMzIgMC41NTIgLTAuMDg0QzAuNTUyIC0wLjAxMiAwLjU2NCAtMCAwLjgwNCAtMEg4Ljk3NkM5LjIxNiAtMCA5LjIyOCAtMC4wMTIgOS4yMjggLTAuMDg0QzkuMjI4IC0wLjEzMiA5LjIwNCAtMC4yMDQgOS4xOCAtMC4yNEw1LjE3MiAtOC4zNTJaTTQuNTI0IC03LjQ2NEw3LjggLTAuODI4SDEuMjZMNC41MjQgLTcuNDY0WicgaWQ9J2cyMScvPjwvZGVmcz48ZyBpZD0ncGFnZTEnIHRyYW5z
Zm9ybT0nbWF0cml4KDEuNSAwIDAgMS41IC04NC45MzcgLTg2LjcpJz48dXNlIHg9JzU2LjYyNDgnIHhsaW5rOmhyZWY9JyNnMjEnIHk9JzY2Jy8%2BPC9nPjwvc3ZnPg%3D%3D%22%20%2F%26gt%3B%3Cbr%3E%3Cbr%3E"
      class="markdown-here-wrapper" data-md-url="Thunderbird"
      id="markdown-here-wrapper-909745">
      <p style="margin: 1.2em 0px ! important;"><img
          src="cid:[email protected]"></p>
    </div>
  </body>
</html>

--------------010105080606030104090106
Content-Type: image/svg+xml;
 name="hgdichdi.svg"
Content-Transfer-Encoding: base64
Content-ID: <[email protected]>
Content-Disposition: inline;
 filename="hgdichdi.svg"

PD94bWwgdmVyc2lvbj0nMS4wJyBlbmNvZGluZz0nSVNPLTg4NTktMSc/Pg0KPCFET0NUWVBF
IHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5v
cmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4NCjxzdmcgaGVpZ2h0PScxMi4z
JyBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSd4TWluWU1pbicgdmVyc2lvbj0nMS4xJyB2aWV3Qm94
PScwIDAgMTQuNjg3MyAxMi4zJyB3aWR0aD0nMTQuNjg3MycgeG1sbnM9J2h0dHA6Ly93d3cu
dzMub3JnLzIwMDAvc3ZnJyB4bWxuczp4bGluaz0naHR0cDovL3d3dy53My5vcmcvMTk5OS94
bGluayc+PGRlZnM+PHBhdGggZD0nTTUuMTcyIC04LjM1MkM1LjA4OCAtOC41MiA1LjA2NCAt
OC41NjggNC44OTYgLTguNTY4QzQuNzE2IC04LjU2OCA0LjY5MiAtOC41MiA0LjYwOCAtOC4z
NTJMMC42IC0wLjI0QzAuNTc2IC0wLjIwNCAwLjU1MiAtMC4xMzIgMC41NTIgLTAuMDg0QzAu
NTUyIC0wLjAxMiAwLjU2NCAtMCAwLjgwNCAtMEg4Ljk3NkM5LjIxNiAtMCA5LjIyOCAtMC4w
MTIgOS4yMjggLTAuMDg0QzkuMjI4IC0wLjEzMiA5LjIwNCAtMC4yMDQgOS4xOCAtMC4yNEw1
LjE3MiAtOC4zNTJaTTQuNTI0IC03LjQ2NEw3LjggLTAuODI4SDEuMjZMNC41MjQgLTcuNDY0
WicgaWQ9J2cyMScvPjwvZGVmcz48ZyBpZD0ncGFnZTEnIHRyYW5zZm9ybT0nbWF0cml4KDEu
NSAwIDAgMS41IC04NC45MzcgLTg2LjcpJz48dXNlIHg9JzU2LjYyNDgnIHhsaW5rOmhyZWY9
JyNnMjEnIHk9JzY2Jy8+PC9nPjwvc3ZnPg==
--------------010105080606030104090106--

--------------010600010002020304090107--

Tbird is modifying the email so that the image refers to an attachment. Which it then chokes on.

I have no idea how to do that refer-to-image-attachment thing in the Chrome web interface. Even if it were desirable.

This StackOverflow answer suggests that webmail clients do not support data URI images in email at all.

(I also tested some different SVG and some variations on the SVG above, but to no better results.)

Latex to Unicode

I followed the link @joanpau gave above. My conclusion regarding it is: Works fine for very simple stuff, but not at all for complex stuff. The example Latex they have on that page sends and reads fine, but the quadratic equation ends up looking like this: -b±√(b²-4ac)\over2a

Rendering math to image

In theory it's possible to render the SVG to an image (or maybe directly from Tex to PNG). But... then what? Data URI images in webmail don't work, and I have no idea how to do image attachments in webmail (without crazy minified JS hacking that ain't gonna happen).

A ridiculous idea: You give MDH access to a S3 bucket you own. MDH renders the math to an image, uploads it to S3, puts an <img> in your email that references the S3-hosted image. Ugh.

HTML+CSS

I haven't looked into this at all. Maybe I will, but I'd sure appreciate if someone else could and report back on how it goes.

Conclusions?

If it seems like enough people are comfortable with the privacy implications of using Codecogs I could add it as an option. But there still needs to be more mail-client testing done.

And... that's about the only conclusion I have. I/you/someone should still look into HTML+CSS. I hope someone else does it, because I'm feeling pretty burnt out of spending hours and hours researching this feature that I don't even use myself.

Miscellaneous

This project uses Mathjax headless to do TeX-->SVG: https://github.com/agrbin/svgtex (See its wiki for more usage info.)

@adam-p
Copy link
Owner

adam-p commented Nov 29, 2013

Forgot to add...

Non-email considerations

Markdown Here is used (with varying degrees of success) in more places than just email. What about SVG support in Google Groups, Evernote, Blogger, TinyMCE, etc.?

If the target supports it, we could think about rendering directly to <svg>, or to <img> with data URI.

@alexpacini
Copy link
Author

Pretty comprehensive explanation.
Actually, I would never write a secret paper completely by email. That's just to write few formulas and it is why codecogs seems fine.
At the moment everything is more complicated that what I thought and, in my actual opinion, it is better to write long mathematics in a different way, e.g. directly by LaTeX and by giving the pdf.

Thank you,
Alex

@adam-p
Copy link
Owner

adam-p commented Nov 30, 2013

If Codecogs is fine, then does <img src="https://latex.codecogs.com/svg.latex?{urlmathcode}" alt="{mathcode}"> do what you need?

@alexpacini
Copy link
Author

For what regards me, it is enough.

Alex

@joanpau
Copy link

joanpau commented Dec 2, 2013

Very good summary of the current state of the different options, Adam.
I support your conclusions. I think that until the technology for rendering (complex) math as characters in browsers and mail clients is no mature enough, this feature does not deserve a great effort.
Furthermore, if there is already a suboptimal solution based on (externally hosted) images, that's by far more than acceptable.

@adam-p
Copy link
Owner

adam-p commented Dec 3, 2013

I added info about this to the Hints and Tips wiki page.

Leaving this open as there's more in the original issue to think about and discuss.

@cben
Copy link

cben commented Nov 26, 2014

[The following is long and includes ideas that might be too much work for Markdown Here; I'm just doing a brain dump on how pretty math could be sent in emails at all...]

SVG is bad default

Alas, when Gmail switched to proxying and transcoding all images (which is good for privacy),
they completely dropped SVG support :-( To add offense to injury, gmail even breaks the alt text!
Generally SVG support is pretty sad across email clients.

Oh, and there is no reliable way to fall back from SVG to something else if it's unsupported.

Must leave Google chart API

But a bigger problem with the google chart TeX api is that it's been deprecated since 2012 and is expected to stop working around April 2015, retroactively breaking all math using it for external images!

So I think it's better to switch to something else like CodeCogs (with PNG) right now. I can't probe they're not evil but CodeCogs have been serving math around the web for ages, and GmailTeX uses them.
It's unclear from their site if they officially support using their image api not via their editor. De-facto, it's widely used but anyway per http://www.codecogs.com/latex/usage.php you should ask them first.

In the long term, the healthiest option would be embedding the image with data: URI so the result doesn't depend on any external service (also loading should be faster).
But email clients strike again — data URI support is worse than external images. I wanted to say future-proofed self-contained output is more important than pandering to current breakage but it doesn't look acceptable...
[There is a well supported way to embed images — reference attached images with href="cid:..." —but that's not an option for MH]

MathML

Not here yet — only works on most of Apple's stuff and Thunderbird.
Notably, it's sanitized out by Gmail and some other webmails even if your browser supports it :-(

A reliable fallback to something else should be possible, so an ideal solution would employ it.

Unicode/CSS "native" rendering of math

MathJax's current HTML+CSS output is highly non-portable but both KaTeX and MathJax's upcoming CommonHTML output a stable HTML.
These are fast, non-pixelated, private and should be more accessible and copy-pastable than SVG — sounds perfect (as perfect as can be without MathML), right?
Unfortunately there are 2 blockers:

  1. CSS inlining — email clients support style="..." much better than linked CSS and even for non-email uses Markdown Here wants to generate a self-contained HTML fragment anyway. I tried to simply pass KaTeX through a couple online css inliners and the result looked horribly wrong in gmail. I believe it's doable but quite a lot of work.
  2. Web Font support. "HTML+CSS" is a misnomer, both KaTeX and MathJax also heavily rely on web fonts. Web fonts (of any kind, embedded or external) are barely supported in email clients.
    Many platforms nowdays have some native math fonts (STIX / Cambria Math) but metrics differ, and you can't do good layout with CSS without known metrics...

That said, while we can't have perfect-looking HTML+CSS math in email, it's not hard to produce something more readable than plain text! Some would say even than PNGs.
GmailTeX does this in its "simple math" mode but it's quite limited.

Bottom line

Kudos to Mozilla and Apple for supporting practically everything above but that's not enough.

AFAICT the only safe way to send math that everybody can view (up to image blocking) is still PNG :-(
And it seems we'll have to keep hrefing external images.
But not from Google's Chart API because that's going down soon!

Unicode + HTML + CSS might be workable but there is no immediately usable implemetations.

Improving PNGs

If we're stuck with PNG, could we make them suck less?

  1. More pixels, so they're not embarrasingly ugly on retina displays.
  2. Correct size relative to text. Currently we don't set any size attributes on the img tag, pixel size depends on formula bounding box but the displayed size is going to depend randomly on reciever's font size. We should at least be using em or ex units (which requires the formula renderer to tell us how big it should be, or us mearsuring the pixels after it loads).
  3. Correct baseline position. (This really requires the math renderer to tell us the right baseline.)

@adam-p
Copy link
Owner

adam-p commented Nov 27, 2014

Great research and analysis, @cben . Thanks for that.

Some notes...

But a bigger problem with the google chart TeX api is that it's been deprecated since 2012 and is expected to stop working around April 2015, retroactively breaking all math using it for external images!

I don't suppose Gmail's proxying of images will save the Chart API images after that API is dropped, eh? (Not that either answer helps us...)

CodeCogs ... you should ask them first.

Yeah. I'll do that now-ish.

[There is a well supported way to embed images — reference attached images with href="cid:..." —but that's not an option for MH]

I really wish we could figure this out...

The Gmail web client uses src="cid:..." when you paste an image, or drag-drop it, or upload it from your computer -- but not when you specify a URL.

I have tried and failed in the past to get Chrome pasting-from-clipboard working.

Maybe if we reversed engineered the (minified, horrible) Gmail JS? Maybe there's a point where we could just stick in image bytes and they would end up in a cid image?

Another possibility is using the Gmail API. Like... wait until the user clicks "Send", intercept it, and create a raw email and send it via the API? Sounds like a crap user experience (no more Undo Send, etc.). And a lot of work.

Seriously: How do we trick Gmail into treating our images as if they were pasted?

... CommonHTML ...

I can't quite tell if you're saying it's sufficiently win-tastic or not. Is this a thing for us to look at more?

... Unicode ...

That reminded me of the crazy awesomeness that is Zalgo -- which is rendered well by Gmail. Someone (who isn't me) should use that for math stuff.

But yeah, I hope the magical "Unicode + HTML + CSS" future comes soon.

To quote myself, a year ago:

A ridiculous idea: You give MDH access to a S3 bucket you own. MDH renders the math to an image, uploads it to S3, puts an <img> in your email that references the S3-hosted image. Ugh.

Maybe... not totally ridiculous? It allows you to be the master of the availability of your images. Instead of S3, use GDrive. Lots of work.


I am pretty convinced by your "suck less" list. And your argument for CodeCogs over Google Chart API.

@cben
Copy link

cben commented Dec 10, 2014

I don't suppose Gmail's proxying of images will save the Chart API images
after that API is dropped, eh? (Not that either answer helps us...)

No, gmail's proxy is more of a short-term cache than mirror — some people
saw repeated requests to original image on re-opening the email hours
later.

It might be a fun excercise to write a browser extension "resurrecting"
google's API (by mathjax and/or rewriting to CodeCogs?) after it dies.

... CommonHTML ...

I can't quite tell if you're saying it's sufficiently win-tastic or not.
Is this a thing for us to look at more?

Not yet, and it will require significant effort.
At least wait until MathJax 2.5 arrives and/or KaTeX matures to support
much more math constructs.

Switching Mathjax to some "average" metrics for platform fonts shouldn't be
hard. (Though unpredictable unicode coverage is a pretty much unsolvable
issue.)

But making CSS layout work across email readers will be a nightmare. I'm
new to the whole CSS-in-email mess but a short reading suggests problems
with such basic properties as margin (outlook.com) and display (desktop
outlook, gmail), which makes it nearly hopeless...

@cben
Copy link

cben commented Dec 11, 2014

Also, I did some tests to confirm Gmail doesn't like data URI png images.
(It was a well-documented fact, but I couldn't find conclusive tests after the image proxy was implemented).

Results: Still broken. The image shows fine during compose (I inserted via DOM inspector) and are not stripped on send, but are not shown when reading via gmail. ALT text does show in gmail.

Connecting to gmail via thunderbird shows all data uri images fine.

Raw mails: https://gist.github.com/cben/664583043a2af239fa9d

@adam-p
Copy link
Owner

adam-p commented Dec 13, 2014

On the CodeCogs front: I have exchanged a couple of emails with them, and it looks like they'll be fine with MDH using their API. (Just trying to nail down when it's okay to start.)

@adam-p
Copy link
Owner

adam-p commented Mar 15, 2015

I created a new issue for switching to CodeCogs: #261. I intend to do it in the next release.


I also had a bad idea: Instead of creating image links to Google Charts or to CodeCogs, etc., create them to an intermediate service (that I run or the user themselves could run). That service would look at the requesting user agent (Gmail in Chrome? Thunderbird? Postbox? Evernote in Firefox?) and decide which rendering to provide (indicating format with mimetype). That way we wouldn't be restricted to the least common denominator -- instead we could return the optimal choice for each platform. (Would have to be an image, though. Not fancy MathJax JS stuff.)

There are a bunch of really good reasons to not do this. 1) It adds another privacy compromise. 2) Running a server, bleh. 3) Figuring out and maintaining "optimal" choices.

Can we even tell what is requesting?

Thunderbird receiving:

Accept-Language: en-US,en;q=0.5
Connect-Time: 1
Accept-Encoding: gzip, deflate
Accept: image/png,image/*;q=0.8,*/*;q=0.5
Connection: close
X-Request-Id: e2462045-b85c-4373-bd89-b862dba58a81
Via: 1.1 vegur
Total-Route-Time: 0
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:31.0) Gecko/20100101 Thunderbird/31.5.0
Host: requestb.in

Gmail+Chrome composing:

Accept-Language: en-US,en;q=0.8,ja;q=0.6,ko;q=0.4
Connect-Time: 3
Accept-Encoding: gzip, deflate, sdch
Accept: image/webp,*/*;q=0.8
Host: requestb.in
Dnt: 1
X-Request-Id: 45accc18-7244-406d-8905-9700f8914f3a
Via: 1.1 vegur
Total-Route-Time: 0
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.89 Safari/537.36
Connection: close

Gmail+Chrome receiving:

Connect-Time: 3
Accept-Encoding: gzip,deflate
Host: requestb.in
X-Request-Id: c4259f01-10be-4686-87da-3078cc96ed1a
Via: 1.1 vegur
Total-Route-Time: 2
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:11.0) Gecko Firefox/11.0 (via ggpht.com GoogleImageProxy)
Connection: close

Firefox+Yahoo receiving:

Accept-Language: en-US,en;q=0.5
Total-Route-Time: 0
Accept-Encoding: gzip, deflate
Accept: image/png,image/*;q=0.8,*/*;q=0.5
Connection: close
Dnt: 1
X-Request-Id: c393f6b0-5668-464b-997c-3a23ae16c175
Via: 1.1 vegur
Connect-Time: 0
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0
Cookie: session=eyJyZWNlbnQiOlsiMWkxb3BkdzEiXX0.B-cuwQ.CQ511AR4VinZPLawrbKAJR_ig24
Host: requestb.in

Chrome+Outlook.com receiving:

Total-Route-Time: 0
Accept-Language: en-ca,en,en
Host: requestb.in
X-Request-Id: f8c9a26b-b823-4dd3-92da-8ebaf85a2287
Via: 1.1 vegur
Connect-Time: 2
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.89 Safari/537.36
Connection: close

Chrome+Evernote composing:

Accept: image/webp,*/*;q=0.8
Total-Route-Time: 0
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.89 Safari/537.36
X-Request-Id: 3a95184f-68f6-47bf-9dcc-533a0bd2e446
Accept-Encoding: gzip, deflate, sdch
Connection: close
Via: 1.1 vegur
Dnt: 1
Host: requestb.in
Accept-Language: en-US,en;q=0.8,ja;q=0.6,ko;q=0.4
Connect-Time: 3

Well, that's not hopeful. Thunderbird is obvious from the user agent, Gmail-receiving (but not browser) is obvious from the GoogleImageProxy, the browser being used is obvious for the others, but... that's about it.

Maybe there's some kind of overall fingerprint for each combination? Like, maybe Yahoo+Firefox has a set of headers and header values that can consistently distinguish it from the other services? Seems like a big, fragile hassle.

I think I can safely put this idea out of my head.

@cben
Copy link

cben commented Mar 15, 2015 via email

@adam-p
Copy link
Owner

adam-p commented Mar 15, 2015

Mostly for SVG vs. PNG. Yeah, not much gain for quite a bit of pain.

Regarding retina clients: When replacing with CodeCogs, I plan on getting a higher DPI image and then explicitly setting the size on it.

@adam-p
Copy link
Owner

adam-p commented Mar 16, 2015

Regarding retina clients: When replacing with CodeCogs, I plan on getting a higher DPI image and then explicitly setting the size on it.

I revoke that statement. I can't figure out a way to satisfactorily size the higher DPI image (in a way that works everywhere). At least until/unless we have both inline and block math -- then the inline can be height: 1em, and the block can be... something else.

@cben
Copy link

cben commented Mar 16, 2015

Let's have inline&block then :-) Anything I can help?

Does height: 1em work reliably? And what about height: 1ex?
Inline math is the hard one, as getting x-height/ascending/descending right matters a lot to readability, and I'd love to understand that irrespective of retina.

@cben
Copy link

cben commented Mar 16, 2015

Ah, perhaps I see what you mean: math should have different size depending on formula, e.g. $x$ vs $x^{a^b}$. Charts API and CodeCogs retuns appropriately sized image (in pixels), which automatically looks approximately good size next to specific font (say 16px)...
But setting height forces all images to same height, which is wrong, except for very simple math that doesn't ascend/descend. Did you mean that by "inline"?

How about interrogating the returned image size and scaling the em/ex height appropriately?

@cben
Copy link

cben commented Mar 16, 2015

Also, re-reading this thread notice MathML works not only in ThunderBird but also on iOS and Apple Mail!
http://www.maths-informatique-jeux.com/blog/frederic/?post/2012/11/14/Writing-mathematics-in-emails
mathml ipod

Perhaps MathML with PNG fallback is doable and sufficient.
(I actually don't have any Apple devices, my HiDPI are linuxes and androids, but I applaud Apple for supporting all the good stuff. And sematically including MathML in the mail is the Right Thing. And CodeCogs can even generate it for us. Now just to find a fallback method that works in email...)

@cben
Copy link

cben commented Mar 17, 2015

How about interrogating the returned image size and scaling the em/ex
height appropriately?

Configuring this actually works (only tested in Gmail in Chrome though):

{mathcode}

(testing .height instead of .naturalHeight because it’s more portable and
should be equivalent in a fresh unstyled image [
http://www.jacklmoore.com/notes/naturalwidth-and-naturalheight-in-ie/]
It also works with svg.latex, though needs a different factor.)

It turns:

header $a$ bar $a^b_c$

subsubheader $a$ bar $a^b_c$

foo $a$ baz $a^b$ bas $a_c$ bar $a^b_c$ quux

into (I hope GH Issues will let the images through):
header [image: a] bar [image: a^b_c] subsubheader [image: a] bar [image:
a^b_c]

foo [image: a] baz [image: a^b] bas [image: a_c] bar [image: a^b_c] quux

I think the header-relative sizing is already a win!

Moreover, I believe it should match any font used by any viewer (that
supports ex height units).
The arbitrary this.height/12 factor (which should perhaps be 13–14)
pertains to the font size produced by CodeCogs.

Removing the debugging \bg_green triggers a strange size anomaly:
header [image: a] bar [image: a^b_c]subsubheader [image: a] bar [image:
a^b_c]

foo [image: a] baz [image: a^b] bas [image: a_c] bar [image: a^b_c] quux

It took me a lot of time to understand why CodeCogs oversizes some small
images.
Here are all the letters:

$a$ $b$ $c$ $d$ $e$ $f$ $g$ $h$ $i$ $j$ $k$ $l$ $m$ $n$ $o$ $p$ $q$ $r$ $s$
$t$ $u$ $v$ $w$ $x$ $y$ $z$

without dpi and without setting style.height set at all:

[image: a] [image: b] [image: c] [image: d] [image: e] [image: f] [image: g]
[image: h] [image: i] [image: j] [image: k] [image: l] [image: m] [image:
n] [image: o] [image: p] [image: q] [image: r] [image: s] [image: t] [image:
u] [image: v] [image: w] [image: x] [image: y] [image: z]

and with \dpi{200}:

[image: a] [image: b] [image: c] [image: d] [image: e] [image: f] [image: g]
[image: h] [image: i] [image: j] [image: k] [image: l] [image: m] [image:
n] [image: o] [image: p] [image: q] [image: r] [image: s] [image: t] [image:
u] [image: v] [image: w] [image: x] [image: y] [image: z]

Aha! CodeCogs really crops to the minimal box containing any paint, which
depends even on the letter used.
That's why using a non-transparent bg helps?

And then what? They upscale it if it's too small?! But not for all
letters (why is a big and c small)?

/home/beni/Downloads/a.png: PNG image data, 26 x 26, 4-bit colormap,
non-interlaced

/home/beni/Downloads/b.png: PNG image data, 13 x 24, 4-bit colormap,
non-interlaced

/home/beni/Downloads/c.png: PNG image data, 13 x 15, 4-bit colormap,
non-interlaced
There is more weirdness and non-reproducibility going on, and I suspect
I've done too many thousand requests over the last hour, so I'll stop here
for now.

@cben
Copy link

cben commented Mar 17, 2015

Sorry, I hoped gmail rich text could survive into github, but it seems github took the text/plain version
Above comment with unmangled IMG tags:
http://codepen.io/cben/full/ogQqLP

@cben
Copy link

cben commented Mar 17, 2015

Playing with other options in the CodeCogs editor, I think it's a bug on their end, and a bewilderingly random one. The "inline" checkbox seems to help but some math is still oversized. Using gif instead of png seemed to help but then I discovered that while a and aq are normal, aa is supersized — even with bg_white:
gif a gif aa
(Github sanitizes style attributes here, but I don't need those - the issue is with the images themselves - some have more pixels.)
Another "workaround" that I noticed worked at some point is wrapping {} around the math. For some reason it mostly helps - but ${n}$ is still supersized...

The bottom line is that standard dpi seems to work fine but at this point I'm not sure what to trust.

@adam-p
Copy link
Owner

adam-p commented Mar 18, 2015

Epic investigation. I love when someone else goes down the rabbit hole.

Your inline JS resize idea is great. A couple things, though:

  1. It doesn't work in the MDH options Preview because of iframe security restrictions. This isn't a problem in Gmail, since it doesn't put the compose area in an iframe (anymore -- it once did), but there are probably other places that use a src-less iframe. Anyway, we could get around it with JS in the extension.
  2. For some reason Gmail strips the height style and replaces it with min-height. However, it leaves and respects max-height. So your JS needs to be something like: this.style.height=this.style.maxHeight=this.style.minHeight=(this.height/18+'ex').

The size variation is utterly bizarre. Any chance you want to post to the CodeCogs forum, suggesting that it's broken?

In exchange for that effort, I'll offer you this data point and possible solution to our woes: If you render to GIF instead of PNG (so, gif.latex), and you use \inline, the letters look... perfect.

image

But if you don't use \inline... rubbish:

image

Note that I have a plain letter x around the $x$. And I'm using vertical-align: middle, which I think does a pretty good (or acceptable) job of making the different heights and below-the-line letters look more sensible.

Here it is without the vertical-align: middle:

image

Here's some more numeric evidence of wackiness (and a cool CodeCogs trick):

# 'a' inline at 300dpi
$ curl "http://latex.codecogs.com/gif.json?%5Cinline%20%5Cdpi%7B300%7D%20a"
>> ParseEqn({ "latex": { "type":"gif", "equation":"a", "site":"file", "file":"56129c80c955fda42022169d43317b83_16.gif", "url":"http://latex.codecogs.com/eq/56/12/56129c80c955fda42022169d43317b83_16.gif", "width":"22", "height":"20", "baseline":"1"} });

# 'a' not inline at 300dpi
$ curl "http://latex.codecogs.com/gif.json?%5Cdpi%7B300%7D%20a"
>> ParseEqn({ "latex": { "type":"gif", "equation":"a", "site":"file", "file":"ad9fca8dc07e6221bd68105cee111b86_16.gif", "url":"http://latex.codecogs.com/eq/ad/9f/ad9fca8dc07e6221bd68105cee111b86_16.gif", "width":"23", "height":"22" } });

# 'c' inline at 300dpi
$ curl "http://latex.codecogs.com/gif.json?%5Cinline%20%5Cdpi%7B300%7D%20c"
>> ParseEqn({ "latex": { "type":"gif", "equation":"c", "site":"file", "file":"89173b6c921f925664199cb083b525c5_36.gif", "url":"http://latex.codecogs.com/eq/89/17/89173b6c921f925664199cb083b525c5_36.gif", "width":"19", "height":"20", "baseline":"1"} });

# 'c' not inline at 300dpi
$ curl "http://latex.codecogs.com/gif.json?%5Cdpi%7B300%7D%20c"
>> ParseEqn({ "latex": { "type":"gif", "equation":"c", "site":"file", "file":"4a63d47c580007a4b45bd7b4325a7f88_36.gif", "url":"http://latex.codecogs.com/eq/4a/63/4a63d47c580007a4b45bd7b4325a7f88_36.gif", "width":"40", "height":"47" } });

'a' is 20 vs. 22. 'c' is 20 vs. 47. What the hell.

(I learned about the gif.json thing in this CodeCogs forum post. Also note the "baseline" in the inline response. It's 1 for 'c' and 4 for 'j', for example. It's also 4 for the quadratic equation. I think that, in theory, we could use that value for shifting the images. However, I'm not sure how to use that value. Setting a negative margin-bottom gets stripped by Gmail. And... I don't know any other ways.)


Recap:

Inline GIF ftw.

You should totally post to the CodeCogs forum, @cben.

@adam-p
Copy link
Owner

adam-p commented Mar 18, 2015

More vertical-align stuff...

I modified the test alphabet by adding the plain letter beside each math letter.

With no vertical-align set (so using the baseline default):
image

With vertical-align: middle:
image

(I fooled around with some other vertical-align values, but they look worse.)

Tall letters -- like 't' and 'k' -- get worse, but the letters with "descenders" -- like 'j' and 'y' -- look a lot better.

I think it's a net gain...? But barely.

@adam-p
Copy link
Owner

adam-p commented Mar 18, 2015

Regarding what I meant by "inline" and "block": I mean the former in the sense of "inline with normal text" and the latter to mean "standing by itself". (Say we had say $...$ for inline math and $$...$$ for block math.)

I would be pretty comfortable forcing the inline math to 1em (kind of thing) and then letting the block math be whatever height makes sense (height*300/110, say, if we use 300dpi and 110dpi is "normal").

(In theory, I suppose, the code could detect math that is by itself in a paragraph versus math that's in a paragraph with other text. Hmm. Seems like a lot of work, though.)

(For the record, I never use the math feature, so it's all hypothetical to me. People who actually use it have more valuable opinions.)

P.S. This is really the wrong issue for these discussions. But too late now...

@adam-p
Copy link
Owner

adam-p commented Mar 18, 2015

Receiving an email in Thunderbird with the height set (either just height or max-height etc.) looks crappy:

image

Without the height set is not similarly cut off:

image

This high-dpi stuff is making me insane.

@cben
Copy link

cben commented Mar 18, 2015

P.S. This is really the wrong issue for these discussions. But too late now...

Oops. Will continue on #261. Will report on CodeCogs forum.

wtianyi added a commit to wtianyi/markdown-here that referenced this issue Oct 28, 2020
1. Update `marked.js` to the latest release
2. After the update of `marked.js`, the customization made by @adam-p
for math treatment is lost. Instead of adapting those, I decided to use
Katex instead for math rendering.

   Note that this is not a generic solution and doesn't align perfectly
   with the goal of Markdown Here. See discussions such as
   adam-p#144 (comment)
@upsidedowntext
Copy link

@drdrjacobs
Copy link

So are we any closer these days to the HTML + CSS promised land?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants