diff options
author | Bjørn Erik Pedersen <[email protected]> | 2022-05-30 20:42:46 +0200 |
---|---|---|
committer | Bjørn Erik Pedersen <[email protected]> | 2022-05-31 09:05:54 +0200 |
commit | 6f7bf3f2d7eda178d0dba4a6bf3dfa50229df7ae (patch) | |
tree | 781580c54bed6942f1844def43750b027d8bbc76 | |
parent | 9e904d756be02ca30e4cd9abb1eae8ba01f9c8af (diff) | |
download | hugo-6f7bf3f2d7eda178d0dba4a6bf3dfa50229df7ae.tar.gz hugo-6f7bf3f2d7eda178d0dba4a6bf3dfa50229df7ae.zip |
Fix indentation in highlight shortcode
This commit adds a new `.InnerDeindent` method to the shortcode context, which is `.Inner` with any
indendation removed. This is then used in the built-in `highlight` shortcode to prevent the extra
whitespace getting hightlighted.
Fixes #4717
-rw-r--r-- | docs/content/en/variables/shortcodes.md | 4 | ||||
-rw-r--r-- | hugolib/shortcode.go | 29 | ||||
-rw-r--r-- | hugolib/shortcode_test.go | 44 | ||||
-rw-r--r-- | tpl/tplimpl/embedded/templates/shortcodes/highlight.html | 2 | ||||
-rw-r--r-- | tpl/tplimpl/template_ast_transformers.go | 2 |
5 files changed, 78 insertions, 3 deletions
diff --git a/docs/content/en/variables/shortcodes.md b/docs/content/en/variables/shortcodes.md index 14eb2aca2..37ae30629 100644 --- a/docs/content/en/variables/shortcodes.md +++ b/docs/content/en/variables/shortcodes.md @@ -45,4 +45,8 @@ toc: false [markdownshortcode]: /content-management/shortcodes/#shortcodes-with-markdown [shortcodes]: /templates/shortcode-templates/ +.InnerDeindent {{< new-in "0.100.0" >}} +: Gets the `.Inner` with any indentation removed. This is what's used in the built-in `{{</* highlight */>}}` shortcode. + + diff --git a/hugolib/shortcode.go b/hugolib/shortcode.go index 366875b88..33767fc68 100644 --- a/hugolib/shortcode.go +++ b/hugolib/shortcode.go @@ -62,6 +62,12 @@ type ShortcodeWithPage struct { // this ordinal will represent the position of this shortcode in the page content. Ordinal int + // Indentation before the opening shortcode in the source. + indentation string + + innerDeindentInit sync.Once + innerDeindent template.HTML + // pos is the position in bytes in the source file. Used for error logging. posInit sync.Once posOffset int @@ -70,6 +76,27 @@ type ShortcodeWithPage struct { scratch *maps.Scratch } +// InnerDeindent returns the (potentially de-indented) inner content of the shortcode. +func (scp *ShortcodeWithPage) InnerDeindent() template.HTML { + if scp.indentation == "" { + return scp.Inner + } + scp.innerDeindentInit.Do(func() { + b := bp.GetBuffer() + text.VisitLinesAfter(string(scp.Inner), func(s string) { + if strings.HasPrefix(s, scp.indentation) { + b.WriteString(strings.TrimPrefix(s, scp.indentation)) + } else { + b.WriteString(s) + } + }) + scp.innerDeindent = template.HTML(b.String()) + bp.PutBuffer(b) + }) + + return scp.innerDeindent +} + // Position returns this shortcode's detailed position. Note that this information // may be expensive to calculate, so only use this in error situations. func (scp *ShortcodeWithPage) Position() text.Position { @@ -326,7 +353,7 @@ func renderShortcode( hasVariants = hasVariants || more } - data := &ShortcodeWithPage{Ordinal: sc.ordinal, posOffset: sc.pos, Params: sc.params, Page: newPageForShortcode(p), Parent: parent, Name: sc.name} + data := &ShortcodeWithPage{Ordinal: sc.ordinal, posOffset: sc.pos, indentation: sc.indentation, Params: sc.params, Page: newPageForShortcode(p), Parent: parent, Name: sc.name} if sc.params != nil { data.IsNamedParams = reflect.TypeOf(sc.params).Kind() == reflect.Map } diff --git a/hugolib/shortcode_test.go b/hugolib/shortcode_test.go index 15c27a42e..5b8a5c295 100644 --- a/hugolib/shortcode_test.go +++ b/hugolib/shortcode_test.go @@ -1009,3 +1009,47 @@ echo "foo"; b.AssertFileContent("public/p1/index.html", "<pre><code>echo "foo";\n</code></pre>") } + +func TestShortcodeHighlightDeindent(t *testing.T) { + t.Parallel() + + files := ` +-- config.toml -- +[markup] +[markup.highlight] +codeFences = true +noClasses = false +-- content/p1.md -- +--- +title: "p1" +--- + +## Indent 5 Spaces + + {{< highlight bash >}} + line 1; + line 2; + line 3; + {{< /highlight >}} + +-- layouts/_default/single.html -- +{{ .Content }} +` + + b := NewIntegrationTestBuilder( + IntegrationTestConfig{ + T: t, + TxtarString: files, + Running: true, + }, + ).Build() + + b.AssertFileContent("public/p1/index.html", ` +<pre><code> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">line 1<span class="p">;</span> +</span></span><span class="line"><span class="cl">line 2<span class="p">;</span> +</span></span><span class="line"><span class="cl">line 3<span class="p">;</span></span></span></code></pre></div> +</code></pre> + + `) + +} diff --git a/tpl/tplimpl/embedded/templates/shortcodes/highlight.html b/tpl/tplimpl/embedded/templates/shortcodes/highlight.html index b063f92ad..54e92bb09 100644 --- a/tpl/tplimpl/embedded/templates/shortcodes/highlight.html +++ b/tpl/tplimpl/embedded/templates/shortcodes/highlight.html @@ -1 +1 @@ -{{ if len .Params | eq 2 }}{{ highlight (trim .Inner "\n\r") (.Get 0) (.Get 1) }}{{ else }}{{ highlight (trim .Inner "\n\r") (.Get 0) "" }}{{ end }}
\ No newline at end of file +{{ if len .Params | eq 2 }}{{ highlight (trim .InnerDeindent "\n\r") (.Get 0) (.Get 1) }}{{ else }}{{ highlight (trim .InnerDeindent "\n\r") (.Get 0) "" }}{{ end }}
\ No newline at end of file diff --git a/tpl/tplimpl/template_ast_transformers.go b/tpl/tplimpl/template_ast_transformers.go index dee1fd6c2..bc02d93ac 100644 --- a/tpl/tplimpl/template_ast_transformers.go +++ b/tpl/tplimpl/template_ast_transformers.go @@ -272,7 +272,7 @@ func (c *templateContext) collectInner(n *parse.CommandNode) { idents = nt.Ident } - if c.hasIdent(idents, "Inner") { + if c.hasIdent(idents, "Inner") || c.hasIdent(idents, "InnerDeindent") { c.t.parseInfo.IsInner = true break } |