mirror of
https://github.com/gohugoio/hugo.git
synced 2026-08-24 15:28:54 +00:00
markup/highlight: Allow overriding type and code via options
Treat type and code as highlighting options in both transform.Highlight and transform.HighlightCodeBlock. The type option overrides the language and code overrides the code, so the two functions now share the same options handling. transform.Highlight's LANG argument is now optional: transform.Highlight CODE [LANG] [OPTIONS] Fixes #11872 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -94,21 +94,50 @@ func (ns *Namespace) Emojify(s any) (template.HTML, error) {
|
||||
return template.HTML(helpers.Emojify([]byte(ss))), nil
|
||||
}
|
||||
|
||||
// Highlight returns a copy of s as an HTML string with syntax
|
||||
// Highlight returns a copy of CODE as an HTML string with syntax
|
||||
// highlighting applied.
|
||||
func (ns *Namespace) Highlight(s any, lang string, opts ...any) (template.HTML, error) {
|
||||
ss, err := cast.ToStringE(s)
|
||||
//
|
||||
// transform.Highlight CODE [LANG] [OPTIONS]
|
||||
//
|
||||
// LANG is optional; it can also be set via the type option in OPTIONS, which
|
||||
// makes this work the same way as HighlightCodeBlock.
|
||||
func (ns *Namespace) Highlight(s any, args ...any) (template.HTML, error) {
|
||||
code, err := cast.ToStringE(s)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var optsv any
|
||||
if len(opts) > 0 {
|
||||
optsv = opts[0]
|
||||
var lang string
|
||||
var opts any
|
||||
|
||||
switch len(args) {
|
||||
case 0:
|
||||
case 1:
|
||||
// A single argument is either OPTIONS (a map or option string) or LANG.
|
||||
if _, ok := args[0].(map[string]any); ok {
|
||||
opts = args[0]
|
||||
} else {
|
||||
var arg string
|
||||
if arg, err = cast.ToStringE(args[0]); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if strings.Contains(arg, "=") || strings.Contains(arg, ",") {
|
||||
opts = arg
|
||||
} else {
|
||||
lang = arg
|
||||
}
|
||||
}
|
||||
case 2:
|
||||
if lang, err = cast.ToStringE(args[0]); err != nil {
|
||||
return "", err
|
||||
}
|
||||
opts = args[1]
|
||||
default:
|
||||
return "", errors.New("transform.Highlight: expects at most 3 arguments")
|
||||
}
|
||||
|
||||
hl := ns.deps.ContentSpec.Converters.GetHighlighter()
|
||||
highlighted, err := hl.Highlight(ss, lang, optsv)
|
||||
highlighted, err := hl.Highlight(code, lang, opts)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
@@ -103,6 +103,34 @@ disableKinds = ['page','rss','section','sitemap','taxonomy','term']
|
||||
b.Assert(err.Error(), qt.Contains, "error calling highlight: invalid Highlight option: 0")
|
||||
}
|
||||
|
||||
// transform.Highlight: LANG is optional and may be set via the type option, and
|
||||
// the code option overrides CODE — consistent with transform.HighlightCodeBlock.
|
||||
// See issue 11872.
|
||||
func TestHighlightTypeAndCodeOptions(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
files := `
|
||||
-- hugo.toml --
|
||||
disableKinds = ['page','rss','section','sitemap','taxonomy','term']
|
||||
[markup.highlight]
|
||||
noClasses = false
|
||||
-- layouts/home.html --
|
||||
lang:{{ transform.Highlight "i = 42" "go" }}
|
||||
type:{{ transform.Highlight "i = 42" (dict "type" "go") }}
|
||||
code:{{ transform.Highlight "" (dict "type" "go" "code" "i = 42") }}
|
||||
`
|
||||
|
||||
b := hugolib.Test(t, files)
|
||||
|
||||
want := `<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="nx">i</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="mi">42</span></span></span></code></pre></div>`
|
||||
|
||||
b.AssertFileContent("public/index.html",
|
||||
"lang:"+want,
|
||||
"type:"+want,
|
||||
"code:"+want,
|
||||
)
|
||||
}
|
||||
|
||||
// Issue #11884
|
||||
func TestUnmarshalCSVLazyDecoding(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
Reference in New Issue
Block a user