]> git.maquefel.me Git - brevno-suite/hugo/commitdiff
Fix indentation in highlight shortcode
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Mon, 30 May 2022 18:42:46 +0000 (20:42 +0200)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Tue, 31 May 2022 07:05:54 +0000 (09:05 +0200)
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

docs/content/en/variables/shortcodes.md
hugolib/shortcode.go
hugolib/shortcode_test.go
tpl/tplimpl/embedded/templates/shortcodes/highlight.html
tpl/tplimpl/template_ast_transformers.go

index 14eb2aca2344337b1eeb61659e4dcd3b7b907da5..37ae30629e4d05afd6e73546361ed4ba08b08ce6 100644 (file)
@@ -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.
+
+
 
index 366875b88a5781a0dc5d2f31d3d3aea108cd3d30..33767fc68111d49d8fbdc1544aaf39523e01ccd9 100644 (file)
@@ -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
        }
index 15c27a42e010765ec2439803fce6eb192f137c4b..5b8a5c2959a3e841baf614cf4ddf8ea85e9d103c 100644 (file)
@@ -1009,3 +1009,47 @@ echo "foo";
        b.AssertFileContent("public/p1/index.html", "<pre><code>echo &quot;foo&quot;;\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>
+
+       `)
+
+}
index b063f92ad04efba4a55f6778d606953a63f1e4ec..54e92bb090f2d40a830b448d040993778214f75e 100644 (file)
@@ -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
index dee1fd6c2ecc030208d63e8f3379dd8e060e7d76..bc02d93ac35d756fb1aa6d1ec17a080e2d1ca59d 100644 (file)
@@ -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
                }