diff --git a/hugolib/integrationtest_builder.go b/hugolib/integrationtest_builder.go
index 3c2f1ad74..f28407fa1 100644
--- a/hugolib/integrationtest_builder.go
+++ b/hugolib/integrationtest_builder.go
@@ -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()
diff --git a/internal/warpc/katex.go b/internal/warpc/katex.go
index 23ca726ac..75c20117f 100644
--- a/internal/warpc/katex.go
+++ b/internal/warpc/katex.go
@@ -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 {
diff --git a/tpl/transform/transform.go b/tpl/transform/transform.go
index bc6d97cf2..e8765bace 100644
--- a/tpl/transform/transform.go
+++ b/tpl/transform/transform.go
@@ -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()
diff --git a/tpl/transform/transform_integration_test.go b/tpl/transform/transform_integration_test.go
index 2b3c7d40e..298097879 100644
--- a/tpl/transform/transform_integration_test.go
+++ b/tpl/transform/transform_integration_test.go
@@ -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", `a %`)
+
+ // 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", `a %`)
+
+ // 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")
+}