shithub: hugo

Download patch

ref: c03ea2b66010d2996d652903cb8fa41e983e787f
parent: fe60b7d9e4c12dbc428f992c05969bc14c7fe7a2
author: Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
date: Mon Apr 27 13:49:51 EDT 2020

Fix some missing JS class collector cases

Fixes #7216

--- a/publisher/htmlElementsCollector.go
+++ b/publisher/htmlElementsCollector.go
@@ -14,9 +14,10 @@
 package publisher
 
 import (
+	"regexp"
+
 	"github.com/gohugoio/hugo/helpers"
 	"golang.org/x/net/html"
-	yaml "gopkg.in/yaml.v2"
 
 	"bytes"
 	"sort"
@@ -196,7 +197,10 @@
 	return b == '"' || b == '\''
 }
 
-var htmlJsonFixer = strings.NewReplacer(", ", "\n")
+var (
+	htmlJsonFixer = strings.NewReplacer(", ", "\n")
+	jsonAttrRe    = regexp.MustCompile(`'?(.*?)'?:.*`)
+)
 
 func parseHTMLElement(elStr string) (el htmlElement) {
 	elStr = strings.TrimSpace(elStr)
@@ -225,27 +229,15 @@
 						val := strings.TrimSpace(a.Val)
 						if strings.Contains(key, "class") && strings.HasPrefix(val, "{") {
 							// This looks like a Vue or AlpineJS class binding.
-							// Try to unmarshal it as YAML and pull the keys.
-							// This may look odd, as the source is (probably) JS (JSON), but the YAML
-							// parser is much more lenient with simple JS input, it seems.
-							m := make(map[string]interface{})
 							val = htmlJsonFixer.Replace(strings.Trim(val, "{}"))
-							// Remove leading space to make it look like YAML.
 							lines := strings.Split(val, "\n")
 							for i, l := range lines {
 								lines[i] = strings.TrimSpace(l)
 							}
 							val = strings.Join(lines, "\n")
-							err := yaml.Unmarshal([]byte(val), &m)
-							if err == nil {
-								for k := range m {
-									el.Classes = append(el.Classes, strings.Fields(k)...)
-								}
-							} else {
-								// Just insert the raw values. This is used for CSS class pruning
-								// so, it's important not to leave out values that may be a CSS class.
-								el.Classes = append(el.Classes, strings.Fields(val)...)
-							}
+							val = jsonAttrRe.ReplaceAllString(val, "$1")
+							el.Classes = append(el.Classes, strings.Fields(val)...)
+
 						}
 					}
 				}
--- a/publisher/htmlElementsCollector_test.go
+++ b/publisher/htmlElementsCollector_test.go
@@ -70,6 +70,15 @@
 		{"Alpine bind 4", `<div x-bind:class="{ 'text-gray-800':  !checked, 
 					 'text-white': checked }"></div>`, f("div", "text-gray-800 text-white", "")},
 
+		{"Alpine bind 5", `<a x-bind:class="{
+                'text-a': a && b,
+                'text-b': !a && b || c,
+                'pl-3': a === 1,
+                 pl-2: b == 3,
+                'text-gray-600': (a > 1)
+      
+                }" class="block w-36 cursor-pointer pr-3 no-underline capitalize"></a>`, f("a", "block capitalize cursor-pointer no-underline pl-2 pl-3 pr-3 text-a text-b text-gray-600 w-36", "")},
+
 		{"Vue bind", `<div v-bind:class="{ active: isActive }"></div>`, f("div", "active", "")},
 	} {
 		c.Run(test.name, func(c *qt.C) {