]> git.maquefel.me Git - brevno-suite/hugo/commitdiff
tpl/transform: Expose the KaTeX strict option
authorJoe Mooring <joe.mooring@veriphor.com>
Fri, 23 May 2025 15:22:25 +0000 (08:22 -0700)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Fri, 23 May 2025 17:21:38 +0000 (19:21 +0200)
Closes #13729

hugolib/integrationtest_builder.go
internal/warpc/katex.go
tpl/transform/transform.go
tpl/transform/transform_integration_test.go

index 3c2f1ad747c998daf12fb69d4c4df832e7303d35..f28407fa19da4f93cae030e48f08d27b7236cedd 100644 (file)
@@ -263,7 +263,7 @@ func (s *IntegrationTestBuilder) AssertLogContains(els ...string) {
        }
 }
 
-// AssertLogNotContains asserts that the last build log does matches the given regular expressions.
+// AssertLogMatches asserts that the last build log matches the given regular expressions.
 // The regular expressions can be negated with a "! " prefix.
 func (s *IntegrationTestBuilder) AssertLogMatches(expression string) {
        s.Helper()
index 23ca726ac60867220f3a15676d4255264484e08b..75c20117ffc6ab3505f9c1ca669c140e5fb84fc4 100644 (file)
@@ -45,7 +45,7 @@ type KatexOptions struct {
        // A color string given in the format "#XXX" or "#XXXXXX"
        ErrorColor string `json:"errorColor"`
 
-       //  A collection of custom macros.
+       // A collection of custom macros.
        Macros map[string]string `json:"macros,omitempty"`
 
        // Specifies a minimum thickness, in ems, for fraction lines.
@@ -53,6 +53,22 @@ type KatexOptions struct {
 
        // If true, KaTeX will throw a ParseError when it encounters an unsupported command.
        ThrowOnError bool `json:"throwOnError"`
+
+       // Controls how KaTeX handles LaTeX features that offer convenience but
+       // aren't officially supported, one of error (default), ignore, or warn.
+       //
+       //  - error: Throws an error when convenient, unsupported LaTeX features
+       //    are encountered.
+       //  - ignore: Allows convenient, unsupported LaTeX features without any
+       //    feedback.
+       //  - warn: Emits a warning when convenient, unsupported LaTeX features are
+       //    encountered.
+       //
+       // The "newLineInDisplayMode" error code, which flags the use of \\
+       // or \newline in display mode outside an array or tabular environment, is
+       // intentionally designed not to throw an error, despite this behavior
+       // being questionable.
+       Strict string `json:"strict"`
 }
 
 type KatexOutput struct {
index bc6d97cf25eade22851b50a5da645cda8214c77e..e8765bace021aa7832347b7f7d7db552e90d4526 100644 (file)
@@ -19,6 +19,7 @@ import (
        "context"
        "encoding/xml"
        "errors"
+       "fmt"
        "html"
        "html/template"
        "io"
@@ -234,6 +235,7 @@ func (ns *Namespace) ToMath(ctx context.Context, args ...any) (template.HTML, er
                        MinRuleThickness: 0.04,
                        ErrorColor:       "#cc0000",
                        ThrowOnError:     true,
+                       Strict:           "error",
                },
        }
 
@@ -243,6 +245,13 @@ func (ns *Namespace) ToMath(ctx context.Context, args ...any) (template.HTML, er
                }
        }
 
+       switch katexInput.Options.Strict {
+       case "error", "ignore", "warn":
+               // Valid strict mode, continue
+       default:
+               return "", fmt.Errorf("invalid strict mode; expected one of error, ignore, or warn; received %s", katexInput.Options.Strict)
+       }
+
        s := hashing.HashString(args...)
        key := "tomath/" + s[:2] + "/" + s[2:]
        fileCache := ns.deps.ResourceSpec.FileCaches.MiscCache()
index 2b3c7d40e4d70320f708ed2532623803ff7f2e39..298097879b9275e3eddbbe6f6ae2c1bd720869eb 100644 (file)
@@ -495,3 +495,44 @@ DATA
                }
        }
 }
+
+// Issue 13729
+func TestToMathStrictMode(t *testing.T) {
+       t.Parallel()
+
+       files := `
+-- hugo.toml --
+disableKinds = ['page','rss','section','sitemap','taxonomy','term']
+-- layouts/all.html --
+{{ transform.ToMath "a %" dict }}
+-- foo --
+`
+
+       // strict mode: default
+       f := strings.ReplaceAll(files, "dict", "")
+       b, err := hugolib.TestE(t, f)
+       b.Assert(err.Error(), qt.Contains, "[commentAtEnd]")
+
+       // strict mode: error
+       f = strings.ReplaceAll(files, "dict", `(dict "strict" "error")`)
+       b, err = hugolib.TestE(t, f)
+       b.Assert(err.Error(), qt.Contains, "[commentAtEnd]")
+
+       // strict mode: ignore
+       f = strings.ReplaceAll(files, "dict", `(dict "strict" "ignore")`)
+       b = hugolib.Test(t, f, hugolib.TestOptWarn())
+       b.AssertLogMatches("")
+       b.AssertFileContent("public/index.html", `<annotation encoding="application/x-tex">a %</annotation>`)
+
+       // strict: warn
+       // TODO: see https://github.com/gohugoio/hugo/issues/13735
+       // f = strings.ReplaceAll(files, "dict", `(dict "strict" "warn")`)
+       // b = hugolib.Test(t, f, hugolib.TestOptWarn())
+       // b.AssertLogMatches("[commentAtEnd]")
+       // b.AssertFileContent("public/index.html", `<annotation encoding="application/x-tex">a %</annotation>`)
+
+       // strict mode: invalid value
+       f = strings.ReplaceAll(files, "dict", `(dict "strict" "foo")`)
+       b, err = hugolib.TestE(t, f)
+       b.Assert(err.Error(), qt.Contains, "invalid strict mode")
+}