* releaser: Bump versions for release of 0.146.3
* tpl: Make any layout set in front matter higher priority
* tpl: Fix it so embedded render-codeblock-goat is used even if custom render-codeblock exists
* releaser: Prepare repository for 0.147.0-DEV
- Packaging improvements:
* Add patch remove-wasm-tomath.patch refs boo#1241131 hugo needs a package for
dependency javy JS to WebAssembly toolchain (Rust)
- Original patch by darix
- Removes JS to WASM functionality used for server-side rendering of LaTeX to MathML
- .wasm compiled binaries already being removed, see previous changelog
- Imposes unmet dependency on javy JS to WASM toolchain
- Drop patch if and when a javy package is available boo#1241131
OBS-URL: https://build.opensuse.org/package/show/devel:languages:go/hugo?expand=0&rev=193
396 lines
12 KiB
Diff
396 lines
12 KiB
Diff
commit 9265a26eaddc6402751973cbdefbd779173b5a14
|
|
Author: Jeff Kowalczyk <jkowalczyk@suse.com>
|
|
Date: Sun Apr 13 14:19:13 2025 -0700
|
|
|
|
Remove warpc and javy dep supporting ToMath() LaTex to MathML
|
|
|
|
Upstream Hugo added a feature render LaTex to MathML server-side. Remove the
|
|
functionality in Hugo related to this feature. Original patchset by darix.
|
|
|
|
While useful, ToMath() brings along a dependency on the javy JS to WebAssembly
|
|
toolchain implemented in Rust. Upstream ships precompiled .wasm binaries, but we
|
|
cannot ship these in OBS built packages. These .wasm binaries are already being
|
|
removed as a packaging step, see package changelog.
|
|
|
|
There is currently no RPM package available for javy. If and when a javy package
|
|
built in OBS is available, drop this patch.
|
|
|
|
Upstream has declined suggestions to not ship precompiled .wasm in the source
|
|
distribution. See deleted comments from darix on:
|
|
|
|
hugo#12736 transform.ToMath, WASI/Wasm modules feedback thread
|
|
https://github.com/gohugoio/hugo/issues/12736
|
|
|
|
diff --git a/deps/deps.go b/deps/deps.go
|
|
index d0d6d95f..b6009a39 100644
|
|
--- a/deps/deps.go
|
|
+++ b/deps/deps.go
|
|
@@ -25,7 +25,6 @@ import (
|
|
"github.com/gohugoio/hugo/hugofs"
|
|
"github.com/gohugoio/hugo/identity"
|
|
"github.com/gohugoio/hugo/internal/js"
|
|
- "github.com/gohugoio/hugo/internal/warpc"
|
|
"github.com/gohugoio/hugo/media"
|
|
"github.com/gohugoio/hugo/resources/page"
|
|
"github.com/gohugoio/hugo/resources/postpub"
|
|
@@ -101,10 +100,6 @@ type Deps struct {
|
|
// Misc counters.
|
|
Counters *Counters
|
|
|
|
- // Holds RPC dispatchers for Katex etc.
|
|
- // TODO(bep) rethink this re. a plugin setup, but this will have to do for now.
|
|
- WasmDispatchers *warpc.Dispatchers
|
|
-
|
|
// The JS batcher client.
|
|
JSBatcherClient js.BatcherClient
|
|
|
|
@@ -380,9 +375,6 @@ func (d *Deps) Close() error {
|
|
if d.MemCache != nil {
|
|
d.MemCache.Stop()
|
|
}
|
|
- if d.WasmDispatchers != nil {
|
|
- d.WasmDispatchers.Close()
|
|
- }
|
|
return d.BuildClosers.Close()
|
|
}
|
|
|
|
diff --git a/hugolib/site.go b/hugolib/site.go
|
|
index 728b036d..6bce24db 100644
|
|
--- a/hugolib/site.go
|
|
+++ b/hugolib/site.go
|
|
@@ -43,7 +43,6 @@ import (
|
|
"github.com/gohugoio/hugo/hugolib/doctree"
|
|
"github.com/gohugoio/hugo/hugolib/pagesfromdata"
|
|
"github.com/gohugoio/hugo/internal/js/esbuild"
|
|
- "github.com/gohugoio/hugo/internal/warpc"
|
|
"github.com/gohugoio/hugo/langs/i18n"
|
|
"github.com/gohugoio/hugo/modules"
|
|
"github.com/gohugoio/hugo/resources"
|
|
@@ -197,15 +196,6 @@ func NewHugoSites(cfg deps.DepsCfg) (*HugoSites, error) {
|
|
Counters: &deps.Counters{},
|
|
MemCache: memCache,
|
|
TranslationProvider: i18n.NewTranslationProvider(),
|
|
- WasmDispatchers: warpc.AllDispatchers(
|
|
- warpc.Options{
|
|
- CompilationCacheDir: filepath.Join(conf.Dirs().CacheDir, "_warpc"),
|
|
-
|
|
- // Katex is relatively slow.
|
|
- PoolSize: 8,
|
|
- Infof: logger.InfoCommand("wasm").Logf,
|
|
- },
|
|
- ),
|
|
}
|
|
|
|
if err := firstSiteDeps.Init(); err != nil {
|
|
diff --git a/tpl/transform/transform.go b/tpl/transform/transform.go
|
|
index bc6d97cf..654bf0e1 100644
|
|
--- a/tpl/transform/transform.go
|
|
+++ b/tpl/transform/transform.go
|
|
@@ -18,10 +18,8 @@ import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/xml"
|
|
- "errors"
|
|
"html"
|
|
"html/template"
|
|
- "io"
|
|
"strings"
|
|
"sync/atomic"
|
|
|
|
@@ -30,15 +28,11 @@ import (
|
|
"github.com/bep/goportabletext"
|
|
|
|
"github.com/gohugoio/hugo/cache/dynacache"
|
|
- "github.com/gohugoio/hugo/common/hashing"
|
|
- "github.com/gohugoio/hugo/common/hugio"
|
|
- "github.com/gohugoio/hugo/internal/warpc"
|
|
"github.com/gohugoio/hugo/markup/converter/hooks"
|
|
"github.com/gohugoio/hugo/markup/highlight"
|
|
"github.com/gohugoio/hugo/markup/highlight/chromalexers"
|
|
"github.com/gohugoio/hugo/resources"
|
|
"github.com/gohugoio/hugo/tpl"
|
|
- "github.com/mitchellh/mapstructure"
|
|
|
|
"github.com/gohugoio/hugo/deps"
|
|
"github.com/gohugoio/hugo/helpers"
|
|
@@ -216,72 +210,6 @@ func (ns *Namespace) PortableText(v any) (string, error) {
|
|
return buf.String(), nil
|
|
}
|
|
|
|
-// ToMath converts a LaTeX string to math in the given format, default MathML.
|
|
-// This uses KaTeX to render the math, see https://katex.org/.
|
|
-func (ns *Namespace) ToMath(ctx context.Context, args ...any) (template.HTML, error) {
|
|
- if len(args) < 1 {
|
|
- return "", errors.New("must provide at least one argument")
|
|
- }
|
|
- expression, err := cast.ToStringE(args[0])
|
|
- if err != nil {
|
|
- return "", err
|
|
- }
|
|
-
|
|
- katexInput := warpc.KatexInput{
|
|
- Expression: expression,
|
|
- Options: warpc.KatexOptions{
|
|
- Output: "mathml",
|
|
- MinRuleThickness: 0.04,
|
|
- ErrorColor: "#cc0000",
|
|
- ThrowOnError: true,
|
|
- },
|
|
- }
|
|
-
|
|
- if len(args) > 1 {
|
|
- if err := mapstructure.WeakDecode(args[1], &katexInput.Options); err != nil {
|
|
- return "", err
|
|
- }
|
|
- }
|
|
-
|
|
- s := hashing.HashString(args...)
|
|
- key := "tomath/" + s[:2] + "/" + s[2:]
|
|
- fileCache := ns.deps.ResourceSpec.FileCaches.MiscCache()
|
|
-
|
|
- v, err := ns.cacheMath.GetOrCreate(key, func(string) (template.HTML, error) {
|
|
- _, r, err := fileCache.GetOrCreate(key, func() (io.ReadCloser, error) {
|
|
- message := warpc.Message[warpc.KatexInput]{
|
|
- Header: warpc.Header{
|
|
- Version: 1,
|
|
- ID: ns.id.Add(1),
|
|
- },
|
|
- Data: katexInput,
|
|
- }
|
|
-
|
|
- k, err := ns.deps.WasmDispatchers.Katex()
|
|
- if err != nil {
|
|
- return nil, err
|
|
- }
|
|
- result, err := k.Execute(ctx, message)
|
|
- if err != nil {
|
|
- return nil, err
|
|
- }
|
|
- return hugio.NewReadSeekerNoOpCloserFromString(result.Data.Output), nil
|
|
- })
|
|
- if err != nil {
|
|
- return "", err
|
|
- }
|
|
-
|
|
- s, err := hugio.ReadString(r)
|
|
-
|
|
- return template.HTML(s), err
|
|
- })
|
|
- if err != nil {
|
|
- return "", err
|
|
- }
|
|
-
|
|
- return v, nil
|
|
-}
|
|
-
|
|
// For internal use.
|
|
func (ns *Namespace) Reset() {
|
|
ns.cacheUnmarshal.Clear()
|
|
diff --git a/tpl/transform/transform_integration_test.go b/tpl/transform/transform_integration_test.go
|
|
index ceb80309..6fe4aa0a 100644
|
|
--- a/tpl/transform/transform_integration_test.go
|
|
+++ b/tpl/transform/transform_integration_test.go
|
|
@@ -136,202 +136,6 @@ Scar,"a "dead cat",11
|
|
`)
|
|
}
|
|
|
|
-func TestToMath(t *testing.T) {
|
|
- files := `
|
|
--- hugo.toml --
|
|
-disableKinds = ['page','rss','section','sitemap','taxonomy','term']
|
|
--- layouts/index.html --
|
|
-{{ transform.ToMath "c = \\pm\\sqrt{a^2 + b^2}" }}
|
|
- `
|
|
- b := hugolib.Test(t, files)
|
|
-
|
|
- b.AssertFileContent("public/index.html", `
|
|
-<span class="katex"><math
|
|
- `)
|
|
-}
|
|
-
|
|
-func TestToMathError(t *testing.T) {
|
|
- t.Run("Default", func(t *testing.T) {
|
|
- files := `
|
|
--- hugo.toml --
|
|
-disableKinds = ['page','rss','section','sitemap','taxonomy','term']
|
|
--- layouts/index.html --
|
|
-{{ transform.ToMath "c = \\foo{a^2 + b^2}" }}
|
|
- `
|
|
- b, err := hugolib.TestE(t, files, hugolib.TestOptWarn())
|
|
-
|
|
- b.Assert(err, qt.IsNotNil)
|
|
- b.Assert(err.Error(), qt.Contains, "KaTeX parse error: Undefined control sequence: \\foo")
|
|
- })
|
|
-
|
|
- t.Run("Disable ThrowOnError", func(t *testing.T) {
|
|
- files := `
|
|
--- hugo.toml --
|
|
-disableKinds = ['page','rss','section','sitemap','taxonomy','term']
|
|
--- layouts/index.html --
|
|
-{{ $opts := dict "throwOnError" false }}
|
|
-{{ transform.ToMath "c = \\foo{a^2 + b^2}" $opts }}
|
|
- `
|
|
- b, err := hugolib.TestE(t, files, hugolib.TestOptWarn())
|
|
-
|
|
- b.Assert(err, qt.IsNil)
|
|
- b.AssertFileContent("public/index.html", `#cc0000`) // Error color
|
|
- })
|
|
-
|
|
- t.Run("Handle in template", func(t *testing.T) {
|
|
- files := `
|
|
--- hugo.toml --
|
|
-disableKinds = ['page','rss','section','sitemap','taxonomy','term']
|
|
--- layouts/index.html --
|
|
-{{ with try (transform.ToMath "c = \\foo{a^2 + b^2}") }}
|
|
- {{ with .Err }}
|
|
- {{ warnf "error: %s" . }}
|
|
- {{ else }}
|
|
- {{ .Value }}
|
|
- {{ end }}
|
|
-{{ end }}
|
|
- `
|
|
- b, err := hugolib.TestE(t, files, hugolib.TestOptWarn())
|
|
-
|
|
- b.Assert(err, qt.IsNil)
|
|
- b.AssertLogContains("WARN error: template: index.html:1:22: executing \"index.html\" at <transform.ToMath>: error calling ToMath: KaTeX parse error: Undefined control sequence: \\foo at position 5: c = \\̲f̲o̲o̲{a^2 + b^2}")
|
|
- })
|
|
-
|
|
- // See issue 13239.
|
|
- t.Run("Handle in template, old Err construct", func(t *testing.T) {
|
|
- files := `
|
|
--- hugo.toml --
|
|
-disableKinds = ['page','rss','section','sitemap','taxonomy','term']
|
|
--- layouts/index.html --
|
|
-{{ with transform.ToMath "c = \\pm\\sqrt{a^2 + b^2}" }}
|
|
- {{ with .Err }}
|
|
- {{ warnf "error: %s" . }}
|
|
- {{ else }}
|
|
- {{ . }}
|
|
- {{ end }}
|
|
-{{ end }}
|
|
- `
|
|
- b, err := hugolib.TestE(t, files, hugolib.TestOptWarn())
|
|
-
|
|
- b.Assert(err, qt.IsNotNil)
|
|
- b.Assert(err.Error(), qt.Contains, "the return type of transform.ToMath was changed in Hugo v0.141.0 and the error handling replaced with a new try keyword, see https://gohugo.io/functions/go-template/try/")
|
|
- })
|
|
-}
|
|
-
|
|
-func TestToMathBigAndManyExpressions(t *testing.T) {
|
|
- filesTemplate := `
|
|
--- hugo.toml --
|
|
-disableKinds = ['rss','section','sitemap','taxonomy','term']
|
|
-[markup.goldmark.extensions.passthrough]
|
|
-enable = true
|
|
-[markup.goldmark.extensions.passthrough.delimiters]
|
|
-block = [['\[', '\]'], ['$$', '$$']]
|
|
-inline = [['\(', '\)'], ['$', '$']]
|
|
--- content/p1.md --
|
|
-P1_CONTENT
|
|
--- layouts/index.html --
|
|
-Home.
|
|
--- layouts/_default/single.html --
|
|
-Content: {{ .Content }}|
|
|
--- layouts/_default/_markup/render-passthrough.html --
|
|
-{{ $opts := dict "throwOnError" false "displayMode" true }}
|
|
-{{ transform.ToMath .Inner $opts }}
|
|
- `
|
|
-
|
|
- t.Run("Very large file with many complex KaTeX expressions", func(t *testing.T) {
|
|
- files := strings.ReplaceAll(filesTemplate, "P1_CONTENT", "sourcefilename: testdata/large-katex.md")
|
|
- b := hugolib.Test(t, files)
|
|
- b.AssertFileContent("public/p1/index.html", `
|
|
- <span class="katex"><math
|
|
- `)
|
|
- })
|
|
-
|
|
- t.Run("Large and complex expression", func(t *testing.T) {
|
|
- // This is pulled from the file above, which times out for some reason.
|
|
- largeAndComplexeExpressions := `\begin{align*} \frac{\pi^2}{6}&=\frac{4}{3}\frac{(\arcsin 1)^2}{2}\\ &=\frac{4}{3}\int_0^1\frac{\arcsin x}{\sqrt{1-x^2}}\,dx\\ &=\frac{4}{3}\int_0^1\frac{x+\sum_{n=1}^{\infty}\frac{(2n-1)!!}{(2n)!!}\frac{x^{2n+1}}{2n+1}}{\sqrt{1-x^2}}\,dx\\ &=\frac{4}{3}\int_0^1\frac{x}{\sqrt{1-x^2}}\,dx +\frac{4}{3}\sum_{n=1}^{\infty}\frac{(2n-1)!!}{(2n)!!(2n+1)}\int_0^1x^{2n}\frac{x}{\sqrt{1-x^2}}\,dx\\ &=\frac{4}{3}+\frac{4}{3}\sum_{n=1}^{\infty}\frac{(2n-1)!!}{(2n)!!(2n+1)}\left[\frac{(2n)!!}{(2n+1)!!}\right]\\ &=\frac{4}{3}\sum_{n=0}^{\infty}\frac{1}{(2n+1)^2}\\ &=\frac{4}{3}\left(\sum_{n=1}^{\infty}\frac{1}{n^2}-\frac{1}{4}\sum_{n=1}^{\infty}\frac{1}{n^2}\right)\\ &=\sum_{n=1}^{\infty}\frac{1}{n^2} \end{align*}`
|
|
- files := strings.ReplaceAll(filesTemplate, "P1_CONTENT", fmt.Sprintf(`---
|
|
-title: p1
|
|
----
|
|
-
|
|
-$$%s$$
|
|
- `, largeAndComplexeExpressions))
|
|
-
|
|
- b := hugolib.Test(t, files)
|
|
- b.AssertFileContent("public/p1/index.html", `
|
|
- <span class="katex"><math
|
|
- `)
|
|
- })
|
|
-}
|
|
-
|
|
-// Issue #13406.
|
|
-func TestToMathRenderHookPosition(t *testing.T) {
|
|
- filesTemplate := `
|
|
--- hugo.toml --
|
|
-disableKinds = ['rss','section','sitemap','taxonomy','term']
|
|
-[markup.goldmark.extensions.passthrough]
|
|
-enable = true
|
|
-[markup.goldmark.extensions.passthrough.delimiters]
|
|
-block = [['\[', '\]'], ['$$', '$$']]
|
|
-inline = [['\(', '\)'], ['$', '$']]
|
|
--- content/p1.md --
|
|
----
|
|
-title: p1
|
|
----
|
|
-
|
|
-Block:
|
|
-
|
|
-$$1+2$$
|
|
-
|
|
-Some inline $1+3$ math.
|
|
-
|
|
--- layouts/index.html --
|
|
-Home.
|
|
--- layouts/_default/single.html --
|
|
-Content: {{ .Content }}|
|
|
--- layouts/_default/_markup/render-passthrough.html --
|
|
-{{ $opts := dict "throwOnError" true "displayMode" true }}
|
|
-{{- with try (transform.ToMath .Inner $opts ) }}
|
|
- {{- with .Err }}
|
|
- {{ errorf "KaTeX: %s: see %s." . $.Position }}
|
|
- {{- else }}
|
|
- {{- .Value }}
|
|
- {{- end }}
|
|
-{{- end -}}
|
|
-
|
|
-`
|
|
-
|
|
- // Block math.
|
|
- files := strings.Replace(filesTemplate, "$$1+2$$", "$$\\foo1+2$$", 1)
|
|
- b, err := hugolib.TestE(t, files)
|
|
- b.Assert(err, qt.IsNotNil)
|
|
- b.AssertLogContains("p1.md:6:1")
|
|
-
|
|
- // Inline math.
|
|
- files = strings.Replace(filesTemplate, "$1+3$", "$\\foo1+3$", 1)
|
|
- b, err = hugolib.TestE(t, files)
|
|
- b.Assert(err, qt.IsNotNil)
|
|
- b.AssertLogContains("p1.md:8:13")
|
|
-}
|
|
-
|
|
-func TestToMathMacros(t *testing.T) {
|
|
- files := `
|
|
--- hugo.toml --
|
|
-disableKinds = ['page','rss','section','sitemap','taxonomy','term']
|
|
--- layouts/index.html --
|
|
-{{ $macros := dict
|
|
- "\\addBar" "\\bar{#1}"
|
|
- "\\bold" "\\mathbf{#1}"
|
|
-}}
|
|
-{{ $opts := dict "macros" $macros }}
|
|
-{{ transform.ToMath "\\addBar{y} + \\bold{H}" $opts }}
|
|
- `
|
|
- b := hugolib.Test(t, files)
|
|
-
|
|
- b.AssertFileContent("public/index.html", `
|
|
-<mi>y</mi>
|
|
- `)
|
|
-}
|
|
-
|
|
// Issue #12977
|
|
func TestUnmarshalWithIndentedYAML(t *testing.T) {
|
|
t.Parallel()
|