Consolidate DOM manipulation utilities to eliminate code duplication

- Move addClass and setAttribute from ContentEngine/Injector to utils.go
- Remove duplicate hasInsertrClass implementation
- Add RemoveClass and HasClass utilities for completeness
- Eliminates 74+ lines of exact duplication across files
This commit is contained in:
2025-10-26 18:07:12 +01:00
parent c34a1a033e
commit a52d9bb600
3 changed files with 116 additions and 130 deletions

View File

@@ -32,6 +32,112 @@ func GetAttribute(node *html.Node, key string) string {
return ""
}
// SetAttribute sets an attribute on an HTML node
func SetAttribute(node *html.Node, key, value string) {
// Check for existing attribute and update in place
for i, attr := range node.Attr {
if attr.Key == key {
node.Attr[i].Val = value
return
}
}
// Add new attribute if not found
node.Attr = append(node.Attr, html.Attribute{
Key: key,
Val: value,
})
}
// AddClass safely adds a class to an HTML node
func AddClass(node *html.Node, className string) {
var classAttr *html.Attribute
var classIndex int = -1
// Find existing class attribute
for idx, attr := range node.Attr {
if attr.Key == "class" {
classAttr = &attr
classIndex = idx
break
}
}
var classes []string
if classAttr != nil {
classes = strings.Fields(classAttr.Val)
}
// Check if class already exists
if slices.Contains(classes, className) {
return
}
// Add new class
classes = append(classes, className)
newClassValue := strings.Join(classes, " ")
if classIndex >= 0 {
// Update existing class attribute
node.Attr[classIndex].Val = newClassValue
} else {
// Add new class attribute
node.Attr = append(node.Attr, html.Attribute{
Key: "class",
Val: newClassValue,
})
}
}
// RemoveClass safely removes a class from an HTML node
func RemoveClass(node *html.Node, className string) {
var classIndex int = -1
// Find existing class attribute
for idx, attr := range node.Attr {
if attr.Key == "class" {
classIndex = idx
break
}
}
if classIndex == -1 {
return // No class attribute found
}
// Parse existing classes
classes := strings.Fields(node.Attr[classIndex].Val)
// Filter out the target class
var newClasses []string
for _, class := range classes {
if class != className {
newClasses = append(newClasses, class)
}
}
// Update or remove class attribute
if len(newClasses) == 0 {
// Remove class attribute entirely if no classes remain
node.Attr = slices.Delete(node.Attr, classIndex, classIndex+1)
} else {
// Update class attribute with remaining classes
node.Attr[classIndex].Val = strings.Join(newClasses, " ")
}
}
// HasClass checks if a node has a specific class
func HasClass(node *html.Node, className string) bool {
for _, attr := range node.Attr {
if attr.Key == "class" {
classes := strings.Fields(attr.Val)
if slices.Contains(classes, className) {
return true
}
}
}
return false
}
// Inline formatting elements that are safe for editing
var inlineFormattingTags = map[string]bool{
"strong": true,