1
0
html/validate.go

78 lines
1.3 KiB
Go
Raw Permalink Normal View History

2025-09-11 20:50:00 +02:00
package html
import (
"errors"
"fmt"
"regexp"
"strings"
2025-09-11 20:50:00 +02:00
)
2025-10-06 23:49:11 +02:00
var symbolExp = regexp.MustCompile(`^[a-zA-Z][a-zA-Z0-9-_.]*$`)
2025-09-11 20:50:00 +02:00
func validateSymbol(s string) error {
if !symbolExp.MatchString(s) {
return errors.New("invalid symbol")
}
return nil
}
func validateTagName(name string) error {
2025-10-06 00:37:10 +02:00
if strings.HasPrefix(name, "!") {
return nil
}
2025-09-11 20:50:00 +02:00
return validateSymbol(name)
}
func validateAttributeName(name string) error {
return validateSymbol(name)
}
func validate(name string, children []any) error {
if err := validateTagName(name); err != nil {
return err
}
2025-10-06 23:49:11 +02:00
isDeclaration := strings.HasPrefix(name, "!")
2025-09-11 20:50:00 +02:00
a, c, rgs := groupChildren(children)
rg := mergeRenderingGuides(rgs)
if rg.void && len(c) > 0 {
return fmt.Errorf("tag %s is void but it has children", name)
}
2025-10-06 23:49:11 +02:00
if isDeclaration && len(c) > 0 {
return fmt.Errorf("declarations cannot have children (%s)", name)
}
2025-09-11 20:50:00 +02:00
for _, ai := range a {
2025-10-06 00:37:10 +02:00
for _, name := range ai.names {
if isDeclaration {
continue
}
2025-09-11 20:50:00 +02:00
if err := validateAttributeName(name); err != nil {
return fmt.Errorf("tag %s: %w", name, err)
}
}
}
for _, ci := range c {
if tag, ok := ci.(Tag); ok {
if rg.script {
2025-09-11 20:50:00 +02:00
return fmt.Errorf("tag %s does not allow child elements", name)
}
var v validator
tag(&v)
if v.err != nil {
return v.err
}
continue
}
}
return nil
}