]> git.maquefel.me Git - brevno-suite/hugo/commitdiff
markup/highlight: Allow lineNos to be true, false, "inline", or "table"
authorJoe Mooring <joe.mooring@veriphor.com>
Wed, 23 Apr 2025 02:42:04 +0000 (19:42 -0700)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Thu, 12 Feb 2026 18:34:39 +0000 (19:34 +0100)
Closes #13481

markup/highlight/config.go
markup/highlight/highlight.go
markup/highlight/highlight_integration_test.go

index fff9bfeca8354d21d2e4f953b0e8d2d29bd51da8..6407cdff66a179e583b54b5e3aad9bbe946ab27e 100644 (file)
@@ -60,7 +60,7 @@ type Config struct {
        NoClasses bool
 
        // When set, line numbers will be printed.
-       LineNos            bool
+       LineNos            any
        LineNumbersInTable bool
 
        // When set, add links to line numbers
@@ -85,16 +85,44 @@ type Config struct {
        GuessSyntax bool
 }
 
-func (cfg Config) toHTMLOptions() []html.Option {
-       var lineAnchors string
+const errLineNosMsg = `lineNos must be one of true, false, "inline", or "table"; got %[1]v (%[1]T)`
+
+func (cfg Config) toHTMLOptions() ([]html.Option, error) {
+       var (
+               lineAnchors string
+               lineNos     bool
+               inTable     = cfg.LineNumbersInTable
+       )
+
        if cfg.LineAnchors != "" {
                lineAnchors = cfg.LineAnchors + "-"
        }
+
+       switch v := cfg.LineNos.(type) {
+       case string:
+               switch v {
+               case "inline":
+                       lineNos = true
+                       inTable = false
+               case "table":
+                       lineNos = true
+                       inTable = true
+               default:
+                       return nil, fmt.Errorf(errLineNosMsg, v)
+               }
+       case bool:
+               lineNos = v
+       case nil:
+               lineNos = false
+       default:
+               return nil, fmt.Errorf(errLineNosMsg, v)
+       }
+
        options := []html.Option{
                html.TabWidth(cfg.TabWidth),
-               html.WithLineNumbers(cfg.LineNos),
+               html.WithLineNumbers(lineNos),
                html.BaseLineNumber(cfg.LineNoStart),
-               html.LineNumbersInTable(cfg.LineNumbersInTable),
+               html.LineNumbersInTable(inTable),
                html.WithClasses(!cfg.NoClasses),
                html.WithLinkableLineNumbers(cfg.AnchorLineNos, lineAnchors),
                html.InlineCode(cfg.Hl_inline),
@@ -117,7 +145,7 @@ func (cfg Config) toHTMLOptions() []html.Option {
                }
        }
 
-       return options
+       return options, nil
 }
 
 func applyOptions(opts any, cfg *Config) error {
index ee07fb9ad797259e0f5cf8ef620d455218c91d6c..8fe30425433309bba6ce1187dc1dedbfb767fdef 100644 (file)
@@ -205,7 +205,11 @@ func highlight(fw hugio.FlexiWriter, code, lang string, attributes []attributes.
                writeDivStart(w, attributes, cfg.WrapperClass)
        }
 
-       options := cfg.toHTMLOptions()
+       options, err := cfg.toHTMLOptions()
+       if err != nil {
+               return 0, 0, err
+       }
+
        var wrapper html.PreWrapper
 
        if cfg.Hl_inline {
index a737d9a6a79779d825d8203964e0b335b335c469..19779fd2fe694007fb97abeacc8317ab06b0f109 100644 (file)
 package highlight_test
 
 import (
+       "strings"
        "testing"
 
+       qt "github.com/frankban/quicktest"
        "github.com/gohugoio/hugo/hugolib"
 )
 
@@ -129,3 +131,74 @@ xəx := 0
                 <div class="highlight no-prose"><pre
        `)
 }
+
+func TestHighlightLineNos(t *testing.T) {
+       t.Parallel()
+
+       files := `
+-- config.toml --
+disableKinds = ['page','rss','section','sitemap','taxonomy','term']
+[markup.highlight]
+noClasses = false
+lineNoStart = 42
+#LINENOS
+-- content/_index.md --
+---
+title: home
+---
+§§§go
+aaa
+§§§
+-- layouts/index.html --
+{{ .Content }}
+`
+
+       b := hugolib.Test(t, files)
+       b.AssertFileContent("public/index.html",
+               `<span class="nx">aaa</span>`,
+               `! <table class="lntable">`,
+               `! 42`,
+       )
+
+       f := strings.ReplaceAll(files, "#LINENOS", `linenos = false`)
+       b = hugolib.Test(t, f)
+       b.AssertFileContent("public/index.html",
+               `<span class="nx">aaa</span>`,
+               `! <table class="lntable">`,
+               `! 42`,
+       )
+
+       f = strings.ReplaceAll(files, "#LINENOS", `linenos = true`)
+       b = hugolib.Test(t, f)
+       b.AssertFileContent("public/index.html",
+               `<span class="nx">aaa</span>`,
+               `<table class="lntable">`,
+               `42`,
+       )
+
+       f = strings.ReplaceAll(files, "#LINENOS", `linenos = "table"`)
+       b = hugolib.Test(t, f)
+       b.AssertFileContent("public/index.html",
+               `<span class="nx">aaa</span>`,
+               `<table class="lntable">`,
+               `42`,
+       )
+
+       f = strings.ReplaceAll(files, "#LINENOS", `linenos = "inline"`)
+       b = hugolib.Test(t, f)
+       b.AssertFileContent("public/index.html",
+               `<span class="nx">aaa</span>`,
+               `! <table class="lntable">`,
+               `42`,
+       )
+
+       want := `.* lineNos must be one of .*`
+
+       f = strings.ReplaceAll(files, "#LINENOS", `linenos = "foo"`)
+       b, err := hugolib.TestE(t, f)
+       b.Assert(err, qt.ErrorMatches, want)
+
+       f = strings.ReplaceAll(files, "#LINENOS", `linenos = 123`)
+       b, err = hugolib.TestE(t, f)
+       b.Assert(err, qt.ErrorMatches, want)
+}