From 641403f7de372497776dbed2fe5d01f87904b531 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Mon, 17 Feb 2025 10:58:32 +0100 Subject: [PATCH] Fix Position for passthrough hooks Fixes #13406 --- markup/goldmark/internal/render/context.go | 32 +++++++++++-- tpl/transform/transform_integration_test.go | 50 +++++++++++++++++++++ 2 files changed, 78 insertions(+), 4 deletions(-) diff --git a/markup/goldmark/internal/render/context.go b/markup/goldmark/internal/render/context.go index 27029b670..fd8e788ed 100644 --- a/markup/goldmark/internal/render/context.go +++ b/markup/goldmark/internal/render/context.go @@ -19,6 +19,7 @@ import ( "strings" "sync" + "github.com/gohugoio/hugo-goldmark-extensions/passthrough" bp "github.com/gohugoio/hugo/bufferpool" east "github.com/yuin/goldmark-emoji/ast" @@ -163,21 +164,44 @@ func (ctx *RenderContextDataHolder) DocumentContext() converter.DocumentContext // Note that this is not a copy of the source, but a slice of it, // so it assumes that the source is not mutated. func extractSourceSample(n ast.Node, src []byte) []byte { + if n.Type() == ast.TypeInline { + switch n := n.(type) { + case *passthrough.PassthroughInline: + return n.Segment.Value(src) + } + + return nil + } + var sample []byte - // Extract a source sample to use for position information. - if nn := n.FirstChild(); nn != nil { + getStartStop := func(n ast.Node) (int, int) { + if n == nil { + return 0, 0 + } + var start, stop int - for i := 0; i < nn.Lines().Len() && i < 2; i++ { - line := nn.Lines().At(i) + for i := 0; i < n.Lines().Len() && i < 2; i++ { + line := n.Lines().At(i) if i == 0 { start = line.Start } stop = line.Stop } + return start, stop + } + + start, stop := getStartStop(n) + if stop == 0 { + // Try first child. + start, stop = getStartStop(n.FirstChild()) + } + + if stop > 0 { // We do not mutate the source, so this is safe. sample = src[start:stop] } + return sample } diff --git a/tpl/transform/transform_integration_test.go b/tpl/transform/transform_integration_test.go index 276b9b059..b9a98185c 100644 --- a/tpl/transform/transform_integration_test.go +++ b/tpl/transform/transform_integration_test.go @@ -263,6 +263,56 @@ $$%s$$ }) } +// 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 --