135 lines
2.2 KiB
Go
135 lines
2.2 KiB
Go
package html
|
|
|
|
type nameQuery struct {
|
|
value string
|
|
}
|
|
|
|
type attributesQuery struct {
|
|
value Attributes
|
|
}
|
|
|
|
type attributeQuery struct {
|
|
name string
|
|
value any
|
|
found bool
|
|
}
|
|
|
|
type childrenQuery struct {
|
|
value []any
|
|
}
|
|
|
|
type validator struct {
|
|
err error
|
|
}
|
|
|
|
type renderGuidesQuery struct {
|
|
value []renderGuide
|
|
}
|
|
|
|
func groupChildren(c []any) ([]Attributes, []any, []renderGuide) {
|
|
var (
|
|
a []Attributes
|
|
cc []any
|
|
rg []renderGuide
|
|
)
|
|
|
|
for _, ci := range c {
|
|
if ai, ok := ci.(Attributes); ok {
|
|
a = append(a, ai)
|
|
continue
|
|
}
|
|
|
|
if rgi, ok := ci.(renderGuide); ok {
|
|
rg = append(rg, rgi)
|
|
continue
|
|
}
|
|
|
|
cc = append(cc, ci)
|
|
}
|
|
|
|
return a, cc, rg
|
|
}
|
|
|
|
func mergeAttributes(c []any) Attributes {
|
|
a, _, _ := groupChildren(c)
|
|
if len(a) == 0 {
|
|
return Attributes{}
|
|
}
|
|
|
|
to := Attributes{values: make(map[string]any)}
|
|
for i := len(a) - 1; i >= 0; i-- {
|
|
for _, name := range a[i].names {
|
|
if _, set := to.values[name]; set {
|
|
continue
|
|
}
|
|
|
|
to.names = append(to.names, name)
|
|
to.values[name] = a[i].values[name]
|
|
}
|
|
}
|
|
|
|
return to
|
|
}
|
|
|
|
func findAttribute(c []any, name string) (any, bool) {
|
|
a, _, _ := groupChildren(c)
|
|
for i := len(a) - 1; i >= 0; i-- {
|
|
value, ok := a[i].values[name]
|
|
if ok {
|
|
return value, true
|
|
}
|
|
}
|
|
|
|
return nil, false
|
|
}
|
|
|
|
func handleQuery(name string, children []any) bool {
|
|
if len(children) == 0 {
|
|
return false
|
|
}
|
|
|
|
last := len(children) - 1
|
|
lastChild := children[last]
|
|
if q, ok := lastChild.(*nameQuery); ok {
|
|
q.value = name
|
|
return true
|
|
}
|
|
|
|
if q, ok := lastChild.(*attributesQuery); ok {
|
|
q.value = mergeAttributes(children[:last])
|
|
return true
|
|
}
|
|
|
|
if q, ok := lastChild.(*attributeQuery); ok {
|
|
q.value, q.found = findAttribute(children[:last], q.name)
|
|
return true
|
|
}
|
|
|
|
if q, ok := lastChild.(*childrenQuery); ok {
|
|
_, q.value, _ = groupChildren(children[:last])
|
|
return true
|
|
}
|
|
|
|
if q, ok := lastChild.(*renderGuidesQuery); ok {
|
|
_, _, q.value = groupChildren(children[:last])
|
|
return true
|
|
}
|
|
|
|
if v, ok := lastChild.(*validator); ok {
|
|
v.err = validate(name, children[:last])
|
|
return true
|
|
}
|
|
|
|
if r, ok := lastChild.(*renderer); ok {
|
|
if err := validate(name, children[:last]); err != nil {
|
|
r.err = err
|
|
return true
|
|
}
|
|
|
|
r.render(name, children[:last])
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|