Fix Position for passthrough hooks

Fixes #13406
This commit is contained in:
Bjørn Erik Pedersen 2025-02-17 10:58:32 +01:00
parent 24cc25552f
commit 641403f7de
2 changed files with 78 additions and 4 deletions

View file

@ -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
}

View file

@ -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 --