123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- package web
- import (
- "fmt"
- h "github.com/theplant/htmlgo"
- )
- type headKey int
- const (
- titleKey headKey = iota
- )
- type MetaKey string
- type keyComp struct {
- key interface{}
- comp h.HTMLComponent
- }
- type PageInjector struct {
- comps map[injectPosition][]*keyComp
- }
- type injectPosition int
- const (
- head injectPosition = iota
- tail
- extra
- )
- func (b *PageInjector) putComp(key interface{}, comp h.HTMLComponent, pos injectPosition, replace bool) {
- if b.comps == nil {
- b.comps = make(map[injectPosition][]*keyComp)
- }
- for _, h := range b.comps[pos] {
- if h.key == key {
- if !replace {
- return
- }
- h.comp = comp
- return
- }
- }
- b.comps[pos] = append(b.comps[pos], &keyComp{key: key, comp: comp})
- }
- func (b *PageInjector) getComp(key interface{}, pos injectPosition) *keyComp {
- for _, h := range b.comps[pos] {
- if h.key == key {
- return h
- }
- }
- return nil
- }
- func (b *PageInjector) Title(title string) {
- b.addNode(h.Title(""), titleKey, true, title)
- return
- }
- func (b *PageInjector) HasTitle() (r bool) {
- return b.getComp(titleKey, head) != nil
- }
- func (b *PageInjector) MetaNameContent(name, content string) {
- b.Meta(MetaKey(name), "name", name, "content", content)
- return
- }
- func (b *PageInjector) Meta(key interface{}, attrs ...string) {
- b.addNode(h.Meta(), key, true, "", attrs...)
- return
- }
- func (b *PageInjector) TailHTML(v string) {
- b.TailHTMLComponent(v, h.RawHTML(v), true)
- return
- }
- func (b *PageInjector) TailHTMLComponent(key interface{}, comp h.HTMLComponent, replace bool) {
- b.putComp(key, comp, tail, replace)
- return
- }
- func (b *PageInjector) Clear() (r *PageInjector) {
- b.comps = make(map[injectPosition][]*keyComp)
- return b
- }
- func (b *PageInjector) HeadHTML(v string) {
- b.HeadHTMLComponent(v, h.RawHTML(v), true)
- return
- }
- func (b *PageInjector) HeadHTMLComponent(key interface{}, comp h.HTMLComponent, replace bool) {
- b.putComp(key, comp, head, replace)
- return
- }
- func toHTMLComponent(list []*keyComp) h.HTMLComponent {
- var r []h.HTMLComponent
- for _, h := range list {
- r = append(r, h.comp)
- }
- return h.Components(r...)
- }
- func (b *PageInjector) GetHeadHTMLComponent() h.HTMLComponent {
- b.addCharsetViewPortIfMissing()
- return toHTMLComponent(b.comps[head])
- }
- func (b *PageInjector) GetTailHTMLComponent() h.HTMLComponent {
- return toHTMLComponent(b.comps[tail])
- }
- func (b *PageInjector) GetExtraHTMLComponent() h.HTMLComponent {
- return toHTMLComponent(b.comps[extra])
- }
- func (b *PageInjector) addCharsetViewPortIfMissing() {
- if b.getComp(MetaKey("charset"), head) == nil {
- b.Meta(MetaKey("charset"), "charset", "utf8")
- }
- if b.getComp(MetaKey("viewport"), head) == nil {
- b.MetaNameContent("viewport", "width=device-width, initial-scale=1, shrink-to-fit=no")
- }
- }
- func (b *PageInjector) addNode(tag *h.HTMLTagBuilder, key interface{}, replace bool, body string, attrs ...string) {
- l := len(attrs)
- if l%2 != 0 {
- panic(fmt.Sprintf("attrs should be pairs: %+v, length: %d", attrs, l))
- }
- for i := 0; i < l; i = i + 2 {
- tag.Attr(attrs[i], attrs[i+1])
- }
- if len(body) > 0 {
- tag.Text(body)
- }
- b.putComp(key, tag, head, replace)
- }
|