package html import ( "errors" "fmt" "regexp" "strings" ) var symbolExp = regexp.MustCompile(`^[a-zA-Z][a-zA-Z0-9-_.]*$`) func validateSymbol(s string) error { if !symbolExp.MatchString(s) { return errors.New("invalid symbol") } return nil } func validateTagName(name string) error { if strings.HasPrefix(name, "!") { return nil } 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 } isDeclaration := strings.HasPrefix(name, "!") 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) } if isDeclaration && len(c) > 0 { return fmt.Errorf("declarations cannot have children (%s)", name) } for _, ai := range a { for _, name := range ai.names { if isDeclaration { continue } 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 { 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 }