]> git.maquefel.me Git - brevno-suite/hugo/commitdiff
markup/highlight: Add hl_inline option
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Wed, 15 Jun 2022 11:51:29 +0000 (13:51 +0200)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Wed, 15 Jun 2022 18:04:20 +0000 (20:04 +0200)
Closes #9442
Closes #9635
Closes #9638

markup/highlight/config.go
markup/highlight/highlight.go
markup/highlight/integration_test.go [new file with mode: 0644]
markup/internal/attributes/attributes.go

index 80991f21bce51db8f23699114d8dcf1d25dedeaf..d55958d355b58f0d1eeca481ddedb5e72de96aee 100644 (file)
@@ -72,6 +72,9 @@ type Config struct {
        // A space separated list of line numbers, e.g. “3-8 10-20”.
        Hl_Lines string
 
+       // If set, the markup will not be wrapped in any container.
+       Hl_inline bool
+
        // A parsed and ready to use list of line ranges.
        HL_lines_parsed [][2]int `json:"-"`
 
@@ -93,6 +96,7 @@ func (cfg Config) ToHTMLOptions() []html.Option {
                html.LineNumbersInTable(cfg.LineNumbersInTable),
                html.WithClasses(!cfg.NoClasses),
                html.LinkableLineNumbers(cfg.AnchorLineNos, lineAnchors),
+               html.InlineCode(cfg.Hl_inline),
        }
 
        if cfg.Hl_Lines != "" || cfg.HL_lines_parsed != nil {
index 7e5704132804cfedb02a22828d62fcd93499f241..5b19d6e8e66000f8428b81492381027bb78f8f7e 100644 (file)
@@ -88,6 +88,7 @@ func (h chromaHighlighter) HighlightCodeBlock(ctx hooks.CodeblockContext, opts a
        var b strings.Builder
 
        attributes := ctx.(hooks.AttributesOptionsSliceProvider).AttributesSlice()
+
        options := ctx.Options()
 
        if err := applyOptionsFromMap(options, &cfg); err != nil {
@@ -108,8 +109,13 @@ func (h chromaHighlighter) HighlightCodeBlock(ctx hooks.CodeblockContext, opts a
                return HightlightResult{}, err
        }
 
+       highlighted := b.String()
+       if high == 0 {
+               high = len(highlighted)
+       }
+
        return HightlightResult{
-               highlighted: template.HTML(b.String()),
+               highlighted: template.HTML(highlighted),
                innerLow:    low,
                innerHigh:   high,
        }, nil
@@ -117,6 +123,7 @@ func (h chromaHighlighter) HighlightCodeBlock(ctx hooks.CodeblockContext, opts a
 
 func (h chromaHighlighter) RenderCodeblock(w hugio.FlexiWriter, ctx hooks.CodeblockContext) error {
        cfg := h.cfg
+
        attributes := ctx.(hooks.AttributesOptionsSliceProvider).AttributesSlice()
 
        if err := applyOptionsFromMap(ctx.Options(), &cfg); err != nil {
@@ -158,8 +165,6 @@ func (h HightlightResult) Inner() template.HTML {
 }
 
 func highlight(fw hugio.FlexiWriter, code, lang string, attributes []attributes.Attribute, cfg Config) (int, int, error) {
-       var low, high int
-
        var lexer chroma.Lexer
        if lang != "" {
                lexer = lexers.Get(lang)
@@ -176,11 +181,15 @@ func highlight(fw hugio.FlexiWriter, code, lang string, attributes []attributes.
        w := &byteCountFlexiWriter{delegate: fw}
 
        if lexer == nil {
-               wrapper := getPreWrapper(lang, w)
-               fmt.Fprint(w, wrapper.Start(true, ""))
-               fmt.Fprint(w, gohtml.EscapeString(code))
-               fmt.Fprint(w, wrapper.End(true))
-               return low, high, nil
+               if cfg.Hl_inline {
+                       fmt.Fprint(w, fmt.Sprintf("<code%s>%s</code>", inlineCodeAttrs(lang), gohtml.EscapeString(code)))
+               } else {
+                       preWrapper := getPreWrapper(lang, w)
+                       fmt.Fprint(w, preWrapper.Start(true, ""))
+                       fmt.Fprint(w, gohtml.EscapeString(code))
+                       fmt.Fprint(w, preWrapper.End(true))
+               }
+               return 0, 0, nil
        }
 
        style := styles.Get(cfg.Style)
@@ -194,20 +203,51 @@ func highlight(fw hugio.FlexiWriter, code, lang string, attributes []attributes.
                return 0, 0, err
        }
 
+       if !cfg.Hl_inline {
+               writeDivStart(w, attributes)
+       }
+
        options := cfg.ToHTMLOptions()
-       preWrapper := getPreWrapper(lang, w)
-       options = append(options, html.WithPreWrapper(preWrapper))
+       var wrapper html.PreWrapper
+
+       if cfg.Hl_inline {
+               wrapper = startEnd{
+                       start: func(code bool, styleAttr string) string {
+                               if code {
+                                       return fmt.Sprintf(`<code%s>`, inlineCodeAttrs(lang))
+                               }
+                               return ``
+                       },
+                       end: func(code bool) string {
+                               if code {
+                                       return `</code>`
+                               }
+
+                               return ``
+                       },
+               }
 
-       formatter := html.New(options...)
+       } else {
+               wrapper = getPreWrapper(lang, w)
+       }
+
+       options = append(options, html.WithPreWrapper(wrapper))
 
-       writeDivStart(w, attributes)
+       formatter := html.New(options...)
 
        if err := formatter.Format(w, style, iterator); err != nil {
                return 0, 0, err
        }
-       writeDivEnd(w)
 
-       return preWrapper.low, preWrapper.high, nil
+       if !cfg.Hl_inline {
+               writeDivEnd(w)
+       }
+
+       if p, ok := wrapper.(*preWrapper); ok {
+               return p.low, p.high, nil
+       }
+
+       return 0, 0, nil
 }
 
 func getPreWrapper(language string, writeCounter *byteCountFlexiWriter) *preWrapper {
@@ -232,6 +272,12 @@ func (p *preWrapper) Start(code bool, styleAttr string) string {
        return w.String()
 }
 
+func inlineCodeAttrs(lang string) string {
+       if lang == "" {
+       }
+       return fmt.Sprintf(` class="code-inline language-%s"`, lang)
+}
+
 func WritePreStart(w io.Writer, language, styleAttr string) {
        fmt.Fprintf(w, `<pre tabindex="0"%s>`, styleAttr)
        fmt.Fprint(w, "<code")
@@ -249,6 +295,19 @@ func (p *preWrapper) End(code bool) string {
        return preEnd
 }
 
+type startEnd struct {
+       start func(code bool, styleAttr string) string
+       end   func(code bool) string
+}
+
+func (s startEnd) Start(code bool, styleAttr string) string {
+       return s.start(code, styleAttr)
+}
+
+func (s startEnd) End(code bool) string {
+       return s.end(code)
+}
+
 func WritePreEnd(w io.Writer) {
        fmt.Fprint(w, preEnd)
 }
diff --git a/markup/highlight/integration_test.go b/markup/highlight/integration_test.go
new file mode 100644 (file)
index 0000000..2b4379b
--- /dev/null
@@ -0,0 +1,85 @@
+// Copyright 2022 The Hugo Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package highlight_test
+
+import (
+       "testing"
+
+       "github.com/gohugoio/hugo/hugolib"
+)
+
+func TestHighlightInline(t *testing.T) {
+       t.Parallel()
+
+       files := `
+-- config.toml --
+[markup]
+[markup.highlight]
+codeFences = true
+noClasses = false
+-- content/p1.md --
+---
+title: "p1"
+---
+
+## Inline in Shortcode
+
+Inline:{{< highlight emacs "hl_inline=true" >}}(message "this highlight shortcode"){{< /highlight >}}:End.
+Inline Unknown:{{< highlight foo "hl_inline=true" >}}(message "this highlight shortcode"){{< /highlight >}}:End.
+
+## Inline in code block
+
+Not sure if this makes sense, but add a test for it:
+
+§§§bash {hl_inline=true}
+(message "highlight me")
+§§§
+
+## HighlightCodeBlock in hook
+
+§§§html
+(message "highlight me 2")
+§§§
+
+## Unknown lexer
+
+§§§foo {hl_inline=true}
+(message "highlight me 3")
+§§§
+
+
+-- layouts/_default/_markup/render-codeblock-html.html --
+{{ $opts := dict "hl_inline" true }}
+{{ $result := transform.HighlightCodeBlock . $opts }}
+HighlightCodeBlock: Wrapped:{{ $result.Wrapped  }}|Inner:{{ $result.Inner }}
+-- layouts/_default/single.html --
+{{ .Content }}
+`
+
+       b := hugolib.NewIntegrationTestBuilder(
+               hugolib.IntegrationTestConfig{
+                       T:           t,
+                       TxtarString: files,
+                       NeedsOsFS:   false,
+               },
+       ).Build()
+
+       b.AssertFileContent("public/p1/index.html",
+               "Inline:<code class=\"code-inline language-emacs\"><span class=\"p\">(</span><span class=\"nf\">message</span> <span class=\"s\">&#34;this highlight shortcode&#34;</span><span class=\"p\">)</span></code>:End.",
+               "Inline Unknown:<code class=\"code-inline language-foo\">(message &#34;this highlight shortcode&#34;)</code>:End.",
+               "Not sure if this makes sense, but add a test for it:</p>\n<code class=\"code-inline language-bash\"><span class=\"o\">(</span>message <span class=\"s2\">&#34;highlight me&#34;</span><span class=\"o\">)</span>\n</code>",
+               "HighlightCodeBlock: Wrapped:<code class=\"code-inline language-html\">(message &#34;highlight me 2&#34;)</code>|Inner:<code class=\"code-inline language-html\">(message &#34;highlight me 2&#34;)</code>",
+               "<code class=\"code-inline language-foo\">(message &#34;highlight me 3&#34;)\n</code>",
+       )
+}
index edf857822049f2cbeb60528698b69cece93867f2..6887409834e9f4b108fb003d1b9aedc8800e6bf1 100644 (file)
@@ -30,6 +30,7 @@ var chromaHightlightProcessingAttributes = map[string]bool{
        "anchorLineNos":      true,
        "guessSyntax":        true,
        "hl_Lines":           true,
+       "hl_inline":          true,
        "lineAnchors":        true,
        "lineNos":            true,
        "lineNoStart":        true,