markup/goldmark: Use Ordinal to create default lineanchors
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Fri, 25 Feb 2022 06:45:37 +0000 (07:45 +0100)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Fri, 25 Feb 2022 16:22:43 +0000 (17:22 +0100)
The `Ordinal` starts at 0, so with a `hl-` prefix, this gives `hl-0-1` as a starting point.

Fixes #9567

markup/goldmark/convert_test.go
markup/highlight/config.go
markup/highlight/highlight.go

index 2227d6187cb1998efbb7056fc53c40af2fd44a62..83d97f222b42e6fa04fb6520fc26b84839545742 100644 (file)
@@ -288,6 +288,20 @@ func TestConvertAttributes(t *testing.T) {
                        "```bash {linenos=table, anchorlinenos=true, lineanchors=org-coderef--xyz}\necho 'foo';\n```",
                        "<div class=\"highlight\"><div class=\"chroma\">\n<table class=\"lntable\"><tr><td class=\"lntd\">\n<pre tabindex=\"0\" class=\"chroma\"><code><span class=\"lnt\" id=\"org-coderef--xyz-1\"><a style=\"outline: none; text-decoration:none; color:inherit\" href=\"#org-coderef--xyz-1\">1</a>\n</span></code></pre></td>\n<td class=\"lntd\">\n<pre tabindex=\"0\" class=\"chroma\"><code class=\"language-bash\" data-lang=\"bash\"><span class=\"line\"><span class=\"cl\"><span class=\"nb\">echo</span> <span class=\"s1\">&#39;foo&#39;</span><span class=\"p\">;</span>\n</span></span></code></pre></td></tr></table>\n</div>\n</div>",
                },
+               {
+                       "Code block, CodeFences=true,lineanchors, default ordinal",
+                       func(conf *markup_config.Config) {
+                               withBlockAttributes(conf)
+                               conf.Highlight.CodeFences = true
+                               conf.Highlight.NoClasses = false
+                       },
+                       "```bash {linenos=inline, anchorlinenos=true}\necho 'foo';\nnecho 'bar';\n```\n\n```bash {linenos=inline, anchorlinenos=true}\necho 'baz';\nnecho 'qux';\n```",
+                       []string{
+                               "<span class=\"ln\" id=\"hl-0-1\"><a style=\"outline: none; text-decoration:none; color:inherit\" href=\"#hl-0-1\">1</a></span><span class=\"cl\"><span class=\"nb\">echo</span> <span class=\"s1\">&#39;foo&#39;</span>",
+                               "<span class=\"ln\" id=\"hl-0-2\"><a style=\"outline: none; text-decoration:none; color:inherit\" href=\"#hl-0-2\">2</a></span><span class=\"cl\">necho <span class=\"s1\">&#39;bar&#39;</span>",
+                               "<span class=\"ln\" id=\"hl-1-2\"><a style=\"outline: none; text-decoration:none; color:inherit\" href=\"#hl-1-2\">2</a></span><span class=\"cl\">necho <span class=\"s1\">&#39;qux&#39;</span>",
+                       },
+               },
                {
                        "Paragraph",
                        withBlockAttributes,
index 86ac02c3d99c04b26ce83fd7cdda40521a653f16..7b336f580bff1fe0430af8d66d81fb6b7b66d567 100644 (file)
@@ -23,10 +23,19 @@ import (
        "github.com/spf13/cast"
 
        "github.com/gohugoio/hugo/config"
+       "github.com/gohugoio/hugo/markup/converter/hooks"
 
        "github.com/mitchellh/mapstructure"
 )
 
+const (
+       lineanchorsKey = "lineanchors"
+       lineNosKey     = "linenos"
+       hlLinesKey     = "hl_lines"
+       linosStartKey  = "linenostart"
+       noHlKey        = "nohl"
+)
+
 var DefaultConfig = Config{
        // The highlighter style to use.
        // See https://xyproto.github.io/splash/docs/all.html
@@ -38,7 +47,6 @@ var DefaultConfig = Config{
        TabWidth:           4,
 }
 
-//
 type Config struct {
        Style string
 
@@ -133,6 +141,16 @@ func applyOptionsFromMap(optsm map[string]interface{}, cfg *Config) error {
        return mapstructure.WeakDecode(optsm, cfg)
 }
 
+func applyOptionsFromCodeBlockContext(ctx hooks.CodeblockContext, cfg *Config) error {
+       if cfg.LineAnchors == "" {
+               const lineAnchorPrefix = "hl-"
+               // Set it to the ordinal with a prefix.
+               cfg.LineAnchors = fmt.Sprintf("%s%d", lineAnchorPrefix, ctx.Ordinal())
+       }
+
+       return nil
+}
+
 // ApplyLegacyConfig applies legacy config from back when we had
 // Pygments.
 func ApplyLegacyConfig(cfg config.Provider, conf *Config) error {
@@ -191,13 +209,6 @@ func normalizeHighlightOptions(m map[string]interface{}) {
                return
        }
 
-       const (
-               lineNosKey    = "linenos"
-               hlLinesKey    = "hl_lines"
-               linosStartKey = "linenostart"
-               noHlKey       = "nohl"
-       )
-
        baseLineNumber := 1
        if v, ok := m[linosStartKey]; ok {
                baseLineNumber = cast.ToInt(v)
index e9cbeb3c991cddf7d98a10eb7b5990d6a9b123be..6013ba1c8b1fc003f8c6ff86eb57815b1c200ca7 100644 (file)
@@ -18,7 +18,6 @@ import (
        gohtml "html"
        "html/template"
        "io"
-       "strconv"
        "strings"
 
        "github.com/alecthomas/chroma"
@@ -98,6 +97,10 @@ func (h chromaHighlighter) HighlightCodeBlock(ctx hooks.CodeblockContext, opts i
                return HightlightResult{}, err
        }
 
+       if err := applyOptionsFromCodeBlockContext(ctx, &cfg); err != nil {
+               return HightlightResult{}, err
+       }
+
        err := highlight(&b, ctx.Code(), ctx.Lang(), attributes, cfg)
        if err != nil {
                return HightlightResult{}, err
@@ -116,6 +119,10 @@ func (h chromaHighlighter) RenderCodeblock(w hugio.FlexiWriter, ctx hooks.Codebl
                return err
        }
 
+       if err := applyOptionsFromCodeBlockContext(ctx, &cfg); err != nil {
+               return err
+       }
+
        return highlight(w, ctx.Code(), ctx.Lang(), attributes, cfg)
 }
 
@@ -133,31 +140,6 @@ func (h HightlightResult) Highlighted() template.HTML {
        return h.Body
 }
 
-func (h chromaHighlighter) toHighlightOptionsAttributes(ctx hooks.CodeblockContext) (map[string]interface{}, map[string]interface{}) {
-       attributes := ctx.Attributes()
-       if attributes == nil || len(attributes) == 0 {
-               return nil, nil
-       }
-
-       options := make(map[string]interface{})
-       attrs := make(map[string]interface{})
-
-       for k, v := range attributes {
-               klow := strings.ToLower(k)
-               if chromaHightlightProcessingAttributes[klow] {
-                       options[klow] = v
-               } else {
-                       attrs[k] = v
-               }
-       }
-       const lineanchorsKey = "lineanchors"
-       if _, found := options[lineanchorsKey]; !found {
-               // Set it to the ordinal.
-               options[lineanchorsKey] = strconv.Itoa(ctx.Ordinal())
-       }
-       return options, attrs
-}
-
 func highlight(w hugio.FlexiWriter, code, lang string, attributes []attributes.Attribute, cfg Config) error {
        var lexer chroma.Lexer
        if lang != "" {