gohugoio / hugo

The world’s fastest framework for building websites.
https://gohugo.io
Apache License 2.0
73.82k stars 7.4k forks source link

Implement server-side LaTeX rendering (SVG) and/or encoding (MathML) #10044

Open TTWNO opened 2 years ago

TTWNO commented 2 years ago

Hi there, I have been trying for quite some time to convert my existing blog, as well as my business SSG to Hugo. Personally, I don't really care how fast it is, my blog will never be big. However, I now have some employees that work with me, and trying to switch to Hugo has lead us to two issues that I'm going to post back-to-back, and offer a $250 CAD (~$200 USD) reward for each issue which can be PRd and merged. Not sure if you have a bounty program here, but I'd certainly be happy to contribute in this way. Personally, I don't think I'm quite savvy enough to do these features myself (even if I am a developer by trade).

This first issue is the ability to produce MathML/KaTeX server-side so the final document does not depend on Javascript. I create accessible documents for the blind, and it is extremely important to me that the documents don't get outdated because of the Javascript. There will always be tools to convert from HTML4 to HTML5, and 5 to 6, or 6 to whatever new standard comes along. The MathML source can also be converted into newer formats as things progress. However, embedding the LaTeX and hoping that a future JS script is going to just hopefully be able to handle it is not something I want to rely on. Additionally, including the same Javascript file with every finished HTML document is wasteful. I want my files to be as self-contained as possible.

Server-side MathML generation (through Jekyll+KaTeX, currently) fixes the above issue. It's just so slow, especially with some of us with older machines.

So if somebody can find a way, without including cgo, which I think I remember seeing as a deal-breaker for a previous implementation, that everyone can agree on and get into some version of Hugo down the line, I would be insanely grateful, and willing to put my money where my mouth is.

Please tell me if this is the wrong place for this, if it's inappropriate to give out bounties this way/at all, or if I'm doing anything that would be considered problematic. My goal is to make the world a more accessible place, and this is just one of the ways I'm hoping to help, even if all I can offer is a reward.

Thanks for you time,

ianmuchina commented 2 years ago

I made a demo site to solve this with zero js uing a shortcode.

Demo site: https://hugo-tests-2-git-katex-static-muchina.vercel.app/posts/post/ Site Source: https://github.com/ianmuchina/katex-api-test API Source: https://github.com/ianmuchina/katex-api-test

Currently the shortcode requires internet access. You can modify it to use a localhost url if you need offline access.

Here's how to use the shortcode in markdown.

{{<katex>}}
\sqrt{x^2+1}
{{</katex>}}

Here's the shortcode source.

<!-- layouts/shortcodes/katex.html -->
{{ $url := printf "https://katex-api-test.deno.dev/?expression=%s&rawHTML=true" (urlquery .Inner) }}
{{ with resources.GetRemote $url }}
  {{ .Content | safeHTML }}
{{ end }}

For it to work you need to import the katex css file.

/* styles.css */
@import url("https://cdn.jsdelivr.net/npm/katex@0.16.0/dist/katex.min.css");

The api responses can be put into version control to speed up subsequent builds with this config.

# config.yml
caches:
  # Cache resources infinitely
  getresource:
    dir: :resourceDir/
    maxAge: -1

Note: this is only a demo. I recommmend creating your own api that you control.

cmpute commented 1 year ago

There are some existing efforts on this: https://github.com/graemephi/goldmark-qjs-katex and https://github.com/graemephi/kahugo. Is it to merge them upstream?

jmooring commented 6 months ago

Closing in favor of #10894.

ldeso commented 6 months ago

As I understand it, #10894 is about allowing to bypass markdown generation for some delimited blocks, which would allow client-side rendering of math without using shortcodes.

Would it be possible to keep the idea of server-side rendering discussed in the present issue as a possible future improvement for Hugo?

jmooring commented 6 months ago

Reopening this, with some notes:

  1. I am renaming this issue to indicate a (for now) generic implementation
  2. The MathML implementations that I have tried have all been buggy
  3. The best rendering quality and performance that I have seen is client-side MathJax
  4. Both client-side MathJax and client-side KaTeX have accessibility features
  5. Given the wide spread client-side usage of both MathJax and KaTeX, I don't see either of them being discontinued in the foreseeable future
  6. Another server-side option that you can use today is via the MathAPI service (or your own) as described here

Items 3, 4, and 5 are covered by https://github.com/gohugoio/hugo-goldmark-extensions/issues/1.

As mentioned in https://github.com/gohugoio/hugo/issues/10894#issuecomment-1885407097, at some point we could potentially create a render hook that would allow you to pass the content captured by hugo-goldmark-extensions/passthrough through a template function. Something like:

{{ .Inner | transform.LaTeXToSVG }}
{{ .Inner | transform.LaTeXToMathML }}

That gives us a lot of flexibility.