chore: server side rendering of math equations (#589)

This commit is contained in:
Andreas Deininger 2025-03-30 19:05:35 +02:00 committed by GitHub
parent c74d44492e
commit b700825943
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
76 changed files with 47 additions and 81 deletions

View File

@ -1 +0,0 @@
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("katex")):"function"==typeof define&&define.amd?define(["katex"],t):"object"==typeof exports?exports.renderMathInElement=t(require("katex")):e.renderMathInElement=t(e.katex)}("undefined"!=typeof self?self:this,(function(e){return function(){"use strict";var t={771:function(t){t.exports=e}},n={};function r(e){var o=n[e];if(void 0!==o)return o.exports;var i=n[e]={exports:{}};return t[e](i,i.exports,r),i.exports}r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,{a:t}),t},r.d=function(e,t){for(var n in t)r.o(t,n)&&!r.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)};var o={};return function(){r.d(o,{default:function(){return d}});var e=r(771),t=r.n(e);const n=function(e,t,n){let r=n,o=0;const i=e.length;for(;r<t.length;){const n=t[r];if(o<=0&&t.slice(r,r+i)===e)return r;"\\"===n?r++:"{"===n?o++:"}"===n&&o--,r++}return-1},i=/^\\begin{/;var a=function(e,t){let r;const o=[],a=new RegExp("("+t.map((e=>e.left.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&"))).join("|")+")");for(;r=e.search(a),-1!==r;){r>0&&(o.push({type:"text",data:e.slice(0,r)}),e=e.slice(r));const a=t.findIndex((t=>e.startsWith(t.left)));if(r=n(t[a].right,e,t[a].left.length),-1===r)break;const l=e.slice(0,r+t[a].right.length),s=i.test(l)?l:e.slice(t[a].left.length,r);o.push({type:"math",data:s,rawData:l,display:t[a].display}),e=e.slice(r+t[a].right.length)}return""!==e&&o.push({type:"text",data:e}),o};const l=function(e,n){const r=a(e,n.delimiters);if(1===r.length&&"text"===r[0].type)return null;const o=document.createDocumentFragment();for(let e=0;e<r.length;e++)if("text"===r[e].type)o.appendChild(document.createTextNode(r[e].data));else{const i=document.createElement("span");let a=r[e].data;n.displayMode=r[e].display;try{n.preProcess&&(a=n.preProcess(a)),t().render(a,i,n)}catch(i){if(!(i instanceof t().ParseError))throw i;n.errorCallback("KaTeX auto-render: Failed to parse `"+r[e].data+"` with ",i),o.appendChild(document.createTextNode(r[e].rawData));continue}o.appendChild(i)}return o},s=function(e,t){for(let n=0;n<e.childNodes.length;n++){const r=e.childNodes[n];if(3===r.nodeType){let o=r.textContent,i=r.nextSibling,a=0;for(;i&&i.nodeType===Node.TEXT_NODE;)o+=i.textContent,i=i.nextSibling,a++;const s=l(o,t);if(s){for(let e=0;e<a;e++)r.nextSibling.remove();n+=s.childNodes.length-1,e.replaceChild(s,r)}else n+=a}else if(1===r.nodeType){const e=" "+r.className+" ";-1===t.ignoredTags.indexOf(r.nodeName.toLowerCase())&&t.ignoredClasses.every((t=>-1===e.indexOf(" "+t+" ")))&&s(r,t)}}};var d=function(e,t){if(!e)throw new Error("No element provided to render");const n={};for(const e in t)t.hasOwnProperty(e)&&(n[e]=t[e]);n.delimiters=n.delimiters||[{left:"$$",right:"$$",display:!0},{left:"\\(",right:"\\)",display:!1},{left:"\\begin{equation}",right:"\\end{equation}",display:!0},{left:"\\begin{align}",right:"\\end{align}",display:!0},{left:"\\begin{alignat}",right:"\\end{alignat}",display:!0},{left:"\\begin{gather}",right:"\\end{gather}",display:!0},{left:"\\begin{CD}",right:"\\end{CD}",display:!0},{left:"\\[",right:"\\]",display:!0}],n.ignoredTags=n.ignoredTags||["script","noscript","style","textarea","pre","code","option"],n.ignoredClasses=n.ignoredClasses||[],n.errorCallback=n.errorCallback||console.error,n.macros=n.macros||{},s(e,n)}}(),o=o.default}()}));

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -54,7 +54,7 @@ jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
env: env:
HUGO_VERSION: 0.138.0 HUGO_VERSION: 0.145.0
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
@ -146,7 +146,7 @@ run: |
3. [hextra-starter-template][hextra-starter-template]を使用していない場合、以下の設定を手動で行います: 3. [hextra-starter-template][hextra-starter-template]を使用していない場合、以下の設定を手動で行います:
- ビルドコマンドを `hugo --gc --minify` に設定します。 - ビルドコマンドを `hugo --gc --minify` に設定します。
- 公開ディレクトリを `public` に指定します。 - 公開ディレクトリを `public` に指定します。
- 環境変数 `HUGO_VERSION` を追加し、`0.138.0` に設定するか、`netlify.toml` ファイルに設定します。 - 環境変数 `HUGO_VERSION` を追加し、`0.145.0` に設定するか、`netlify.toml` ファイルに設定します。
4. デプロイします! 4. デプロイします!
詳細については、[NetlifyでのHugo](https://docs.netlify.com/integrations/frameworks/hugo/)を確認してください。 詳細については、[NetlifyでのHugo](https://docs.netlify.com/integrations/frameworks/hugo/)を確認してください。

View File

@ -54,7 +54,7 @@ jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
env: env:
HUGO_VERSION: 0.138.0 HUGO_VERSION: 0.145.0
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
@ -146,7 +146,7 @@ For more details, check out:
3. If you are not using [hextra-starter-template][hextra-starter-template], configure the following manually: 3. If you are not using [hextra-starter-template][hextra-starter-template], configure the following manually:
- Configure the Build command to `hugo --gc --minify` - Configure the Build command to `hugo --gc --minify`
- Specify the Publish directory to `public` - Specify the Publish directory to `public`
- Add Environment variable `HUGO_VERSION` and set to `0.138.0`, or alternatively, set it in `netlify.toml` file - Add Environment variable `HUGO_VERSION` and set to `0.145.0`, or alternatively, set it in `netlify.toml` file
4. Deploy! 4. Deploy!
Check [Hugo on Netlify](https://docs.netlify.com/integrations/frameworks/hugo/) for more details. Check [Hugo on Netlify](https://docs.netlify.com/integrations/frameworks/hugo/) for more details.

View File

@ -54,7 +54,7 @@ jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
env: env:
HUGO_VERSION: 0.138.0 HUGO_VERSION: 0.145.0
steps: steps:
- name: 检出 - name: 检出
uses: actions/checkout@v4 uses: actions/checkout@v4
@ -146,7 +146,7 @@ run: |
3. 如果您没有使用 [hextra-starter-template][hextra-starter-template],请手动配置以下内容: 3. 如果您没有使用 [hextra-starter-template][hextra-starter-template],请手动配置以下内容:
- 将构建命令配置为 `hugo --gc --minify` - 将构建命令配置为 `hugo --gc --minify`
- 指定发布目录为 `public` - 指定发布目录为 `public`
- 添加环境变量 `HUGO_VERSION` 并设置为 `0.138.0`,或者将其设置在 `netlify.toml` 文件中 - 添加环境变量 `HUGO_VERSION` 并设置为 `0.145.0`,或者将其设置在 `netlify.toml` 文件中
4. 部署! 4. 部署!
查看 [Netlify 上的 Hugo](https://docs.netlify.com/integrations/frameworks/hugo/) 了解更多详情。 查看 [Netlify 上的 Hugo](https://docs.netlify.com/integrations/frameworks/hugo/) 了解更多详情。

View File

@ -4,7 +4,7 @@ weight: 4
math: true math: true
--- ---
$\KaTeX$ برای رندر کردن عبارت‌های ریاضی LaTeX استفاده می‌شود. می‌توان آن را در هر صفحه با تنظیم `math` روی `true` در قسمت بالای صفحه فعال کرد. \(\KaTeX\) برای رندر کردن عبارت‌های ریاضی LaTeX استفاده می‌شود. می‌توان آن را در هر صفحه با تنظیم `math` روی `true` در قسمت بالای صفحه فعال کرد.
<!--more--> <!--more-->
@ -25,10 +25,10 @@ math: true
### درون‌خطی ### درون‌خطی
```markdown {filename="page.md"} ```markdown {filename="page.md"}
این $\sigma(z) = \frac{1}{1 + e^{-z}}$ درون‌خطی است. این \(\sigma(z) = \frac{1}{1 + e^{-z}}\) درون‌خطی است.
``` ```
این $\sigma(z) = \frac{1}{1 + e^{-z}}$ درون‌خطی است. این \(\sigma(z) = \frac{1}{1 + e^{-z}}\) درون‌خطی است.
### پاراگراف جداگانه ### پاراگراف جداگانه
@ -49,7 +49,7 @@ $$F(\omega) = \int_{-\infty}^{\infty} f(t) e^{-j\omega t} \, dt$$
عبارت‌های شیمی از طریق افزونه [mhchem](https://mhchem.github.io/MathJax-mhchem/) پشتیبانی می‌شوند. عبارت‌های شیمی از طریق افزونه [mhchem](https://mhchem.github.io/MathJax-mhchem/) پشتیبانی می‌شوند.
درون‌خطی: $\ce{H2O}$ آب است. درون‌خطی: \(\ce{H2O}\) آب است.
پاراگراف جداگانه: پاراگراف جداگانه:

View File

@ -4,7 +4,7 @@ weight: 4
math: true math: true
--- ---
$\KaTeX$ は LaTeX の数式をレンダリングするために使用されます。ページのフロントマターで `math``true` に設定することで、ページごとに有効にすることができます。 \(\KaTeX\) は LaTeX の数式をレンダリングするために使用されます。ページのフロントマターで `math``true` に設定することで、ページごとに有効にすることができます。
<!--more--> <!--more-->
@ -25,10 +25,10 @@ Markdown コンテンツ内で、インラインおよび別段落の LaTeX 数
### インライン ### インライン
```markdown {filename="page.md"} ```markdown {filename="page.md"}
これは $\sigma(z) = \frac{1}{1 + e^{-z}}$ インラインです。 これは \(\sigma(z) = \frac{1}{1 + e^{-z}}\) インラインです。
``` ```
これは $\sigma(z) = \frac{1}{1 + e^{-z}}$ インラインです。 これは \(\sigma(z) = \frac{1}{1 + e^{-z}}\) インラインです。
### 別段落 ### 別段落
@ -86,7 +86,7 @@ $$
化学式は [mhchem](https://mhchem.github.io/MathJax-mhchem/) 拡張機能を介してサポートされています。 化学式は [mhchem](https://mhchem.github.io/MathJax-mhchem/) 拡張機能を介してサポートされています。
インライン: $\ce{H2O}$ は水です。 インライン: \(\ce{H2O}\) は水です。
別段落: 別段落:

View File

@ -3,20 +3,7 @@ title: "LaTeX"
weight: 4 weight: 4
math: true math: true
--- ---
\(\KaTeX\) is used for rendering LaTeX math expressions. No manual activation is needed, you can start using LaTeX math expressions in your Markdown content right away.
$\KaTeX$ is used for rendering LaTeX math expressions. It can be enabled per page by setting `math` to `true` in the page front matter.
<!--more-->
```yaml {filename="page.md"}
---
title: "My Page with LaTeX"
math: true
---
```
When enabled, the scripts, stylesheets and fonts from KaTeX will be included automatically in your site. You can start using LaTeX math expressions in your Markdown content.
## Example ## Example
@ -25,10 +12,10 @@ Both inline and separate paragraph LaTeX math expressions are supported in the M
### Inline ### Inline
```markdown {filename="page.md"} ```markdown {filename="page.md"}
This $\sigma(z) = \frac{1}{1 + e^{-z}}$ is inline. This \(\sigma(z) = \frac{1}{1 + e^{-z}}\) is inline.
``` ```
This $\sigma(z) = \frac{1}{1 + e^{-z}}$ is inline. This \(\sigma(z) = \frac{1}{1 + e^{-z}}\) is inline.
### Separate Paragraph ### Separate Paragraph
@ -86,7 +73,7 @@ For a list of supported functions, see [KaTeX supported functions](https://katex
Chemistry expressions are supported via [mhchem](https://mhchem.github.io/MathJax-mhchem/) extension. Chemistry expressions are supported via [mhchem](https://mhchem.github.io/MathJax-mhchem/) extension.
Inline: $\ce{H2O}$ is water. Inline: \(\ce{H2O}\) is water.
Separate paragraph: Separate paragraph:

View File

@ -4,7 +4,7 @@ weight: 4
math: true math: true
--- ---
$\KaTeX$ 用于渲染 LaTeX 数学表达式。可以通过在页面前置设置中将 `math` 设置为 `true` 来启用它。 \(\KaTeX\) 用于渲染 LaTeX 数学表达式。可以通过在页面前置设置中将 `math` 设置为 `true` 来启用它。
<!--more--> <!--more-->
@ -25,10 +25,10 @@ Markdown 内容中支持内联和独立段落的 LaTeX 数学表达式。
### 内联 ### 内联
```markdown {filename="page.md"} ```markdown {filename="page.md"}
这个 $\sigma(z) = \frac{1}{1 + e^{-z}}$ 是内联的。 这个 \(\sigma(z) = \frac{1}{1 + e^{-z}}\) 是内联的。
``` ```
这个 $\sigma(z) = \frac{1}{1 + e^{-z}}$ 是内联的。 这个 \(\sigma(z) = \frac{1}{1 + e^{-z}}\) 是内联的。
### 独立段落 ### 独立段落
@ -86,7 +86,7 @@ $$
通过 [mhchem](https://mhchem.github.io/MathJax-mhchem/) 扩展支持化学表达式。 通过 [mhchem](https://mhchem.github.io/MathJax-mhchem/) 扩展支持化学表达式。
内联:$\ce{H2O}$ 是水。 内联:\(\ce{H2O}\) 是水。
独立段落: 独立段落:

View File

@ -0,0 +1,9 @@
{{- $opts := dict "output" "htmlAndMathml" "displayMode" (eq .Type "block") }}
{{- with try (transform.ToMath .Inner $opts) }}
{{- with .Err }}
{{ errorf "Unable to render mathematical markup to HTML using the transform.ToMath function. The KaTeX display engine threw the following error: %s: see %s." . $.Position }}
{{- else }}
{{- .Value }}
{{- $.Page.Store.Set "hasMath" true }}
{{- end }}
{{- end -}}

View File

@ -59,5 +59,21 @@
} }
</script> </script>
<!-- KaTeX-->
{{ $noop := .WordCount }}
{{ if .Page.Store.Get "hasMath" }}
{{ $katex_css_url := printf "https://cdn.jsdelivr.net/npm/katex@latest/dist/katex%s.css" (cond hugo.IsProduction ".min" "") -}}
{{ with try (resources.GetRemote $katex_css_url) -}}
{{ with .Err -}}
{{ errorf "Could not retrieve KaTeX css file from CDN. Reason: %s." . -}}
{{ else with.Value -}}
{{ with resources.Copy (printf "css/katex%s.css" (cond hugo.IsProduction ".min" "")) . }}
{{ $secureCSS := . | resources.Fingerprint "sha512" -}}
<link rel="stylesheet" href="{{- .RelPermalink -}}" integrity="{{- $secureCSS.Data.Integrity -}}" crossorigin="anonymous">
{{ end -}}
{{ end -}}
{{ end -}}
{{ end }}
{{ partial "custom/head-end.html" . }} {{ partial "custom/head-end.html" . }}
</head> </head>

View File

@ -8,8 +8,3 @@
{{- if (.Store.Get "hasMermaid") -}} {{- if (.Store.Get "hasMermaid") -}}
{{- partial "scripts/mermaid.html" . -}} {{- partial "scripts/mermaid.html" . -}}
{{- end -}} {{- end -}}
{{/* KaTex */}}
{{- if .Page.Params.math -}}
{{- partial "scripts/katex.html" . -}}
{{- end -}}

View File

@ -1,33 +0,0 @@
{{/* KaTex */}}
{{- $katexCSS := resources.Get "lib/katex/katex.min.css" | fingerprint -}}
{{- $katexJS := resources.Get "lib/katex/katex.min.js" | fingerprint -}}
{{- $mhchemJS := resources.Get "lib/katex/mhchem.min.js" | fingerprint -}}
{{- $katexAutoRenderJS := resources.Get "lib/katex/auto-render.min.js" | fingerprint -}}
<link type="text/css" rel="stylesheet" href="{{ $katexCSS.RelPermalink }}" integrity="{{ $katexCSS.Data.Integrity }}" />
<script defer src="{{ $katexJS.RelPermalink }}" integrity="{{ $katexJS.Data.Integrity }}"></script>
<script defer src="{{ $katexAutoRenderJS.RelPermalink }}" integrity="{{ $katexAutoRenderJS.Data.Integrity }}"></script>
<script defer src="{{ $mhchemJS.RelPermalink }}" integrity="{{ $mhchemJS.Data.Integrity }}"></script>
{{ $katexFonts := resources.Match "lib/katex/fonts/*" }}
{{- range $katexFonts -}}
{{ .Publish }}
{{- end -}}
<script>
// TODO: make render options configurable
// Reference: https://katex.org/docs/autorender#api
document.addEventListener("DOMContentLoaded", function () {
renderMathInElement(document.body, {
delimiters: [
{ left: "$$", right: "$$", display: true },
{ left: "$", right: "$", display: false },
{ left: "\\(", right: "\\)", display: false },
{ left: "\\begin{equation}", right: "\\end{equation}", display: true },
{left: "\\begin{align}", right: "\\end{align}", display: true},
{left: "\\begin{alignat}", right: "\\end{alignat}", display: true},
{left: "\\begin{gather}", right: "\\end{gather}", display: true},
{left: "\\begin{CD}", right: "\\end{CD}", display: true},
{ left: "\\[", right: "\\]", display: true },
],
throwOnError: false,
});
});
</script>

View File

@ -21,8 +21,4 @@ tasks:
desc: Download libs from CDN desc: Download libs from CDN
cmds: cmds:
- curl -o assets/lib/flexsearch/flexsearch.bundle.min.js https://cdn.jsdelivr.net/npm/flexsearch@0.7.31/dist/flexsearch.bundle.min.js - curl -o assets/lib/flexsearch/flexsearch.bundle.min.js https://cdn.jsdelivr.net/npm/flexsearch@0.7.31/dist/flexsearch.bundle.min.js
- curl -o assets/lib/katex/katex.min.js https://cdn.jsdelivr.net/npm/katex@latest/dist/katex.min.js
- curl -o assets/lib/katex/katex.min.css https://cdn.jsdelivr.net/npm/katex@latest/dist/katex.min.css
- curl -o assets/lib/katex/auto-render.min.js https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/contrib/auto-render.min.js
- curl -o assets/lib/katex/mhchem.min.js https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/contrib/mhchem.min.js
- curl -o assets/lib/mermaid/mermaid.min.js https://cdn.jsdelivr.net/npm/mermaid@11.3.0/dist/mermaid.min.js - curl -o assets/lib/mermaid/mermaid.min.js https://cdn.jsdelivr.net/npm/mermaid@11.3.0/dist/mermaid.min.js