Repository: gohugoio/hugo (language: go)

Issue:
lineNos in code block info string throws error with v0.93.0 and later if value is not boolean
With v0.92.2 and earlier, either of these work (note the mixed case of the key in the first example):

````text
```text {lineNos=inline}
a
```

```text {linenos=inline}
a
```
````

With v0.93.0 and later, this throws an error:

````text
```text {lineNos=inline}
a
```
````

> 1 error(s) decoding: * cannot parse 'LineNos' as bool: strconv.ParseBool: parsing "inline": invalid syntax

With boolean values, naming the key `lineNos` is not a problem. The error occurs when the value is `inline` or `table` (shorthand notation for setting both `LineNos` and `lineNumbersInTable`).

I tested all of the highlighting options in the info string, using both lower and mixed case key names. The only one that fails is `LineNos`.

Git bisect says 08fdca9d9365eaf1e496a12e2af5e18617bd0e66 is the first bad commit, though I'm not sure how helpful that is given `73 changed files with 1,882 additions and 1,981 deletions.`

I ran into this because I blanked on the key name, so I copied and pasted from the [docs](https://gohugo.io/functions/highlight/#options).


Discussion / hints:
@jmooring is there additional context to this reproduction, like the site config's values for:

```toml
[markup]
  [markup.highlight]
    lineNos = "???" # anything here?
```
> is there additional context

No. Simple example:


```text
git clone --single-branch -b hugo-github-issue-10682 https://github.com/jmooring/hugo-testing hugo-github-issue-10682
cd hugo-github-issue-10682
hugo
```

Fix patch:
diff --git a/markup/highlight/config.go b/markup/highlight/config.go
index 9013dd07298..b1f6d460304 100644
--- a/markup/highlight/config.go
+++ b/markup/highlight/config.go
@@ -198,7 +198,7 @@ func parseHightlightOptions(in string) (map[string]any, error) {
 
 	for _, v := range strings.Split(in, ",") {
 		keyVal := strings.Split(v, "=")
-		key := strings.ToLower(strings.Trim(keyVal[0], " "))
+		key := strings.Trim(keyVal[0], " ")
 		if len(keyVal) != 2 {
 			return opts, fmt.Errorf("invalid Highlight option: %s", key)
 		}
@@ -216,6 +216,12 @@ func normalizeHighlightOptions(m map[string]any) {
 		return
 	}
 
+	// lowercase all keys
+	for k, v := range m {
+		delete(m, k)
+		m[strings.ToLower(k)] = v
+	}
+
 	baseLineNumber := 1
 	if v, ok := m[linosStartKey]; ok {
 		baseLineNumber = cast.ToInt(v)
@@ -232,7 +238,6 @@ func normalizeHighlightOptions(m map[string]any) {
 			if vs, ok := v.(string); ok {
 				m[k] = vs != "false"
 			}
-
 		case hlLinesKey:
 			if hlRanges, ok := v.([][2]int); ok {
 				for i := range hlRanges {


Test patch:
diff --git a/markup/highlight/config_test.go b/markup/highlight/config_test.go
index ab92ecf36fa..23da29ab616 100644
--- a/markup/highlight/config_test.go
+++ b/markup/highlight/config_test.go
@@ -53,4 +53,21 @@ func TestConfig(t *testing.T) {
 		c.Assert(cfg.LineNoStart, qt.Equals, 32)
 		c.Assert(cfg.Hl_Lines, qt.Equals, "3-8 10-20")
 	})
+
+	c.Run("applyOptionsFromMap", func(c *qt.C) {
+		cfg := DefaultConfig
+		err := applyOptionsFromMap(map[string]any{
+			"noclasses":   true,
+			"lineNos":     "inline", // mixed case key, should work after normalization
+			"linenostart": 32,
+			"hl_lines":    "3-8 10-20",
+		}, &cfg)
+
+		c.Assert(err, qt.IsNil)
+		c.Assert(cfg.NoClasses, qt.Equals, true)
+		c.Assert(cfg.LineNos, qt.Equals, true)
+		c.Assert(cfg.LineNumbersInTable, qt.Equals, false)
+		c.Assert(cfg.LineNoStart, qt.Equals, 32)
+		c.Assert(cfg.Hl_Lines, qt.Equals, "3-8 10-20")
+	})
 }