diff --git a/exampleSite/content/docs/guide/latex.md b/exampleSite/content/docs/guide/latex.md index 849d719..0238bd2 100644 --- a/exampleSite/content/docs/guide/latex.md +++ b/exampleSite/content/docs/guide/latex.md @@ -3,32 +3,35 @@ title: "LaTeX" weight: 4 --- -By default, \(\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. +LaTeX math expressions are rendered using \(\KaTeX\) by default. Simply start including them in your Markdown content without any manual configurations. -## Example +## Usage -Both inline and separate paragraph LaTeX math expressions are supported in the Markdown content. +You can use LaTeX for both inline expressions and for larger blocks of text. -### Inline +### Inline Math + +To include an expression within a line of text, wrap it in `\(` and `\)` delimiters. ```markdown {filename="page.md"} -This \(\sigma(z) = \frac{1}{1 + e^{-z}}\) is inline. +This \(\sigma(z) = \frac{1}{1 + e^{-z}}\) is an inline expression. ``` -This \( \sigma(z) = \frac{1}{1 + e^{-z}} \) is inline. +This \( \sigma(z) = \frac{1}{1 + e^{-z}} \) is an inline expression. -### Separate Paragraph +### Display Math + +For expressions that you want to stand on their own in a separate paragraph, use `$$` delimiters. ```markdown {filename="page.md"} -$$F(\omega) = \int_{-\infty}^{\infty} f(t) e^{-j\omega t} \, dt$$ +$$F(\omega) = \int_{-\infty}^{\infty} f(t)\, e^{-j \omega t} \, dt$$ ``` will be rendered as: -$$F(\omega) = \int\_{-\infty}^{\infty} f(t) e^{-j\omega t} \, dt$$ +$$F(\omega) = \int_{-\infty}^{\infty} f(t)\, e^{-j \omega t} \, dt$$ -For example, using the aligned environment: +You can also use LaTeX environments like `aligned` for multi-line expressions. ```latex {filename="page.md"} $$ @@ -52,6 +55,23 @@ $$ \end{aligned} $$ +For a list of supported functions, see [KaTeX supported functions](https://katex.org/docs/supported.html). + +### Chemistry Expressions + +The [mhchem][mhchem] extension is enabled by default, allowing you to easily render chemistry equations and formulas. + +Inline: \(\ce{H2O}\) is water. + +Separate paragraph: + +```markdown {filename="page.md"} +$$\ce{Hg^2+ ->[I-] HgI2 ->[I-] [Hg^{II}I4]^2-}$$ +``` + +will be rendered as: + +$$\ce{Hg^2+ ->[I-] HgI2 ->[I-] [Hg^{II}I4]^2-}$$ ## Configuration @@ -69,35 +89,47 @@ markup: enable: true ``` -## Supported Functions +### Math Engine -For a list of supported functions, see [KaTeX supported functions](https://katex.org/docs/supported.html). +[KaTeX][katex] is the default engine used to render LaTeX math expressions during the build process supported by [Hugo][hugo-transform-tomath]. -## Chemistry +The default is KaTeX, but you can also switch to [MathJax][mathjax] if you need features only available in MathJax. -Chemistry expressions are supported via [mhchem](https://mhchem.github.io/MathJax-mhchem/) extension. +#### KaTeX -Inline: \(\ce{H2O}\) is water. +The default setup requires no configuration. Hugo fetches the KaTeX CSS from the CDN. +If you need to pin a specific version of KaTeX or use local assets, you can do so in your `hugo.yaml` file. -Separate paragraph: +##### Override CDN base URL -```markdown {filename="page.md"} -$$\ce{Hg^2+ ->[I-] HgI2 ->[I-] [Hg^{II}I4]^2-}$$ +```yaml {filename="hugo.yaml"} +params: + math: + engine: katex + katex: + base: "https://cdn.jsdelivr.net/npm/katex@0.16.22/dist" ``` -will be rendered as: +##### Use local assets -$$\ce{Hg^2+ ->[I-] HgI2 ->[I-] [Hg^{II}I4]^2-}$$ +You can also place the css file under `assets` and publish additional font files required by KaTeX. +```yaml {filename="hugo.yaml"} +params: + math: + engine: katex + katex: + css: "css/katex.min.css" + assets: + - "fonts/KaTeX_Main-Regular.woff2" + # Add other font files here +``` -## Math Engine +It will load the KaTeX CSS file from `assets/css/katex.min.css` instead of downloading from CDN. -### MathJax +#### MathJax -By default, [KaTeX][katex] is used for rendering LaTeX math expressions during the build process, which is preferred. -Alternatively, you can use [MathJax][mathjax] to render math expressions. - -To use it instead, add the following to the configuration `hugo.yaml` file: +Alternatively, you can use [MathJax][mathjax] to render math expressions: ```yaml {filename="hugo.yaml"} params: @@ -105,5 +137,10 @@ params: engine: mathjax ``` +> [!NOTE] +> You can further customize MathJax (for example, adjust loader options, or change the CDN/source) by overriding the template at `layouts/_partials/scripts/mathjax.html` in your project. Hugo will use your version instead of the theme's default. + [katex]: https://katex.org/ [mathjax]: https://www.mathjax.org/ +[mhchem]: https://mhchem.github.io/MathJax-mhchem/ +[hugo-transform-tomath]: https://gohugo.io/functions/transform/tomath/ diff --git a/layouts/_partials/head.html b/layouts/_partials/head.html index 0848533..e3430ba 100644 --- a/layouts/_partials/head.html +++ b/layouts/_partials/head.html @@ -83,27 +83,11 @@ } - + {{ $noop := .WordCount -}} {{- $engine := site.Params.math.engine | default "katex" -}} {{ if and (.Page.Store.Get "hasMath") (eq $engine "katex") -}} - - {{ $katexBaseUrl := "https://cdn.jsdelivr.net/npm/katex@latest/dist" }} - {{ $katexCssUrl := printf "%s/katex%s.css" $katexBaseUrl (cond hugo.IsProduction ".min" "") -}} - {{ $katexFontPattern := "url(fonts/" }} - {{ $katexFontSubstituted := printf "url(%s/fonts/" $katexBaseUrl }} - - {{ with try (resources.GetRemote $katexCssUrl) -}} - {{ with .Err -}} - {{ errorf "Could not retrieve KaTeX css file from %s. Reason: %s." $katexCssUrl . -}} - {{ else with .Value -}} - {{ $katexCssContent := strings.Replace .Content $katexFontPattern $katexFontSubstituted }} - {{ with resources.FromString (printf "css/katex%s.css" (cond hugo.IsProduction ".min" "")) $katexCssContent -}} - {{ $cssHash := . | fingerprint "sha512" -}} - - {{ end -}} - {{ end -}} - {{ end -}} + {{ partialCached "scripts/katex.html" . -}} {{ else if and (.Page.Store.Get "hasMath") (eq $engine "mathjax") -}} {{ partialCached "scripts/mathjax.html" . -}} {{ end -}} diff --git a/layouts/_partials/scripts/katex.html b/layouts/_partials/scripts/katex.html new file mode 100644 index 0000000..69e7384 --- /dev/null +++ b/layouts/_partials/scripts/katex.html @@ -0,0 +1,88 @@ +{{- /* KaTeX CSS loader + + Behavior (driven by site.params.math.katex): + - base (remote URL) + optional css: + - Construct remote CSS URL: "{{ base }}/{{ css | default "katex[.min].css" }}". + - Fetch via resources.GetRemote, rewrite font URLs to "{{ base }}/fonts/...". + - Build and fingerprint; emit . + - base (local path or not set) + css (asset path): + - Read CSS from Hugo assets via resources.Get; DO NOT rewrite font URLs. + - Build and fingerprint; emit . + - base (local path) only (no css): + - Link directly to "{{ base }}/katex[.min].css" (no processing). + - Nothing set: + - Default to CDN latest base; same as remote path above. + + Additional: + - assets: optional list to publish extra assets. CSS/JS get tags with integrity (JS loads async). +*/ -}} +{{- $noop := .WordCount -}} + +{{- $katexBase := "https://cdn.jsdelivr.net/npm/katex@latest/dist" -}} +{{- with site.Params.math.katex.base -}} + {{- $katexBase = . -}} +{{- end -}} + +{{- $katexCssAsset := "" -}} +{{- with site.Params.math.katex.css -}} + {{- $katexCssAsset = . -}} +{{- end -}} + +{{- $s := newScratch -}} +{{- $isRemoteBase := or (strings.HasPrefix $katexBase "http://") (strings.HasPrefix $katexBase "https://") -}} + +{{- /* CSS retrieval consolidated: get raw CSS from either local asset or remote, then process once */ -}} +{{- $minSuffix := cond hugo.IsProduction ".min" "" -}} +{{- if $isRemoteBase -}} + {{- $cssPath := cond (ne $katexCssAsset "") $katexCssAsset (printf "katex%s.css" $minSuffix) -}} + {{- $katexCssUrl := printf "%s/%s" $katexBase $cssPath -}} + {{- with try (resources.GetRemote $katexCssUrl) -}} + {{- with .Err -}} + {{- errorf "Could not retrieve KaTeX css file from %s. Reason: %s." $katexCssUrl . -}} + {{- else with .Value -}} + {{- $s.Set "katexCssValue" .Content -}} + {{- end -}} + {{- end -}} +{{- else if $katexCssAsset -}} + {{- with resources.Get $katexCssAsset -}} + {{- $s.Set "katexCssValue" .Content -}} + {{- else -}} + {{- errorf "KaTeX css asset not found at %q" $katexCssAsset -}} + {{- end -}} +{{- end -}} + +{{- with $s.Get "katexCssValue" -}} + {{- $cssContent := . -}} + {{- if $isRemoteBase -}} + {{- $fontPattern := "url(fonts/" -}} + {{- $fontSub := printf "url(%s/fonts/" $katexBase -}} + {{- $cssContent = strings.Replace $cssContent $fontPattern $fontSub -}} + {{- end -}} + {{- with resources.FromString (printf "css/katex%s.css" $minSuffix) $cssContent -}} + {{- $css := . | fingerprint "sha512" -}} + + {{- end -}} +{{- else -}} + {{- if not $isRemoteBase -}} + {{- $cssPath := cond (ne $katexCssAsset "") $katexCssAsset (printf "katex%s.css" $minSuffix) -}} + + {{- end -}} +{{- end -}} + +{{- /* Optionally publish files (fonts, css, js, etc.) from assets and emit tags for css/js with integrity and crossorigin */ -}} +{{- with site.Params.math.katex.assets -}} + {{- range . -}} + {{- with resources.Get . -}} + {{- $name := .Name | lower -}} + {{- if strings.HasSuffix $name ".css" -}} + {{- $built := . | fingerprint "sha512" -}} + + {{- else if or (strings.HasSuffix $name ".js") (strings.HasSuffix $name ".mjs") -}} + {{- $built := . | fingerprint "sha512" -}} + + {{- else -}} + {{- .Publish -}} + {{- end -}} + {{- end -}} + {{- end -}} +{{- end -}} diff --git a/layouts/_partials/scripts/mathjax.html b/layouts/_partials/scripts/mathjax.html index cc129af..a05b543 100644 --- a/layouts/_partials/scripts/mathjax.html +++ b/layouts/_partials/scripts/mathjax.html @@ -1,6 +1,5 @@ {{/* MathJax */}} -{{ $mathjaxVersion := site.Params.math.mathjaxVersion | default "3" -}} -{{ $mathjaxJsUrl := printf "https://cdn.jsdelivr.net/npm/mathjax@%s/es5/tex-chtml.js" $mathjaxVersion -}} +{{ $mathjaxJsUrl := "https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js" -}}