package html import ( "errors" "fmt" "regexp" ) var ( symbolExp = regexp.MustCompile(`^[a-zA-Z][a-zA-Z0-9-_.]*$`) scriptTagExp = regexp.MustCompile(`<\s*/?\s*[sS][cC][rR][iI][pP][tT]([^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 { 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 } 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) } for _, ai := range a { for name := range ai { 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.verbatim || 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 }