Documentation ¶
Overview ¶
Package goh4 constructs html element trees (something like DOM), html templates and integrates them with css rules. All of them are done by using types, not strings. This makes reuse and shortcuts easy.
It is inspired by http://godoc.org/github.com/daaku/go.h
It is easy to extend goh4 and build upon it and you may bring in some html and css strings as well.
Elements ¶
There are some helper functions to generate elements for you. For instance
element := A()
gives you an anchor element. Here is how A() is defined and how you may define your own shortcuts.
func A(objects ...Stringer) (t *Element) { t = NewElement(Tag("a"), Inline) t.Set(objects...) return }
A() calls NewElement() with a typed Tag (created from a string) and a flag that indicates that it's an inline element. All flags are defined as constants and may be combined with the bitwise or | or given as seperate parameters.
Then A() sets up the element by passing the optional Stringer to the Set() method. This allows you do some neat things, for instance
a := A( Class("button"), Id("start"), Text("begin")) a.String() // <a class="button" id="start">begin</a> a = A( Attr("href","#","_target","_blank"), Text("something")) a.String() // <a href="#" target="_blank">something</a> a = A( Style("color","red"), Strong( Html("not <escaped>!"))) a.String() // <a style="color:red;"><strong>not <escaped></strong></a>
Then you may get all the nice methods of element
children := a.Children() // only the Elements inner := a.InnerHtml() // everything inside buttons := a.All(Class("button")) start := a.Any(Id("start")) ...
You may define your own Matcher and pass it to All() and Any().
Templates and Css ¶
Template is an element that can Assign() anything that can be inside an element to any element within the tree, that has the given Id().
content := Div(Id("content")) body := NewTemplate(Body(content)) body.Assign(Id("content"), P(Text("here I am"))) body.String() // <body><div id="content"><p>here I am</p></div></body>
Template may also add css to your head element. In this case you need to use the Doc() pseudo element, that holds the root of the document. And you need a head obviously.
doc := NewTemplate(Doc(Head())) doc.AddCss("body{ color: red; }") doc.String() // <head><style>body { color: red; }</style></head>
Element and Template are structs you can inherit from them, e.g.
type Layout struct { *Template } func (xyyy *Layout) String() string { // do your thing here }
If you want type safe reusable css, you can use Css.
fontsize := NewCss(Class("default-font-size"),Style("font-size","20")) css := NewCss( Class("yellow-button"), Tags("a","button"), Style("background-color","yellow"), fontsize)
and then you might apply it to your elements.
a := A() a.ApplyCss(css) a.String() // <a class="yellow-button"></a>
don't forget to put your css into the template (we don't put fontsize into it, since it is only a building block)
doc := NewTemplate(Doc(Head(),Body(a))) doc.AddCss(css) doc.String()
this results in the following (no auto indentation at the moment, sorry):
<head> <style> a.yellow-button, button.yellow-button { background-color: yellow; font-size: 20; \/* inherited from ».default-font-size« *\/ } </style> </head> <body><a class="yellow-button"></a></body>
Index ¶
- Constants
- Variables
- func And(m ...Matcher) and
- func Child(selectors ...Selecter) combinator
- func Classes(c ...string) classes
- func Descendant(selectors ...Selecter) combinator
- func DirectFollows(selectors ...Selecter) combinator
- func Each(selectors ...Selecter) combinator
- func Follows(selectors ...Selecter) combinator
- func Not(m Matcher) *not
- func Or(m ...Matcher) or
- func Str(in interface{}) string
- func Tags(tag string, xyyy ...string) (a tags)
- func View(stru interface{}, tag string) *view
- type Attrs
- type Class
- type Comment
- type CompiledTemplate
- type Csser
- type Element
- func (xyyy *Element) Add(objects ...interface{}) (err error)
- func (xyyy *Element) AddAfter(v *Element, nu Elementer) (err error)
- func (xyyy *Element) AddAtPosition(pos int, v Elementer) (err error)
- func (xyyy *Element) AddBefore(v *Element, nu Elementer) (err error)
- func (xyyy *Element) AddClass(classes ...Class) (err error)
- func (xyyy *Element) All(m Matcher) (r []*Element)
- func (xyyy *Element) Any(m Matcher) (r *Element)
- func (xyyy *Element) AsTemplate() *Template
- func (xyyy *Element) Attribute(k string) string
- func (xyyy *Element) Attributes() map[string]string
- func (xyyy *Element) AttrsString() (res string)
- func (xyyy *Element) Children() (c []*Element)
- func (xyyy *Element) Classes() (c []Class)
- func (xyyy *Element) Clear()
- func (xyyy *Element) Compile(name string) *CompiledTemplate
- func (xyyy *Element) Fields() (fields []*Element)
- func (xyyy *Element) HasClass(class Class) bool
- func (xyyy *Element) Id() Id
- func (xyyy *Element) InnerHtml() (res string)
- func (xyyy *Element) Is(f flag) bool
- func (xyyy *Element) IsParentAllowed(parent Tager) (allowed bool)
- func (xyyy *Element) NotEscape() *Element
- func (xyyy *Element) Parent() Pather
- func (xyyy *Element) Path() string
- func (xyyy *Element) Placeholder(name string) *CompiledTemplate
- func (xyyy *Element) PositionOf(v *Element) (pos int, found bool)
- func (xyyy *Element) RemoveAttribute(k string)
- func (xyyy *Element) RemoveClass(class Class)
- func (xyyy *Element) Selecter(other ...Selecter) Selecter
- func (xyyy *Element) Selector() string
- func (xyyy *Element) ServeHTTP(w http.ResponseWriter, r *http.Request)
- func (xyyy *Element) SetAtPosition(pos int, v Elementer) (err error)
- func (xyyy *Element) SetAttribute(k, v string)
- func (xyyy *Element) SetAttributes(a ...string)
- func (xyyy *Element) SetBottom(v Elementer) (err error)
- func (xyyy *Element) SetClass(classes ...Class)
- func (xyyy *Element) SetContent(objects ...interface{}) (err error)
- func (xyyy *Element) SetId(id Id) (err error)
- func (xyyy *Element) SetParent(parent Pather)
- func (xyyy *Element) String() (res string)
- func (xyyy *Element) Tag() string
- func (xyyy *Element) WrapChildren(wrapper *Element)
- func (xyyy *Element) WriteTo(w io.Writer)
- type Elementer
- type FieldMatcher
- type Html
- type Id
- type Matcher
- type Pather
- type Placeholder
- type PositionMatcher
- type Scss
- type Selecter
- type SelecterAdder
- type SelectorString
- type SingleAttr
- type Stringer
- type Style
- type Tag
- type Tager
- type Templatable
- type Template
- func (xyyy *Template) Add(objects ...interface{}) (err error)
- func (xyyy *Template) AddCss(css ...Stringer) (err error)
- func (xyyy *Template) Assign(id Id, html interface{}) (err error)
- func (xyyy *Template) Compile(name string) (c *CompiledTemplate, ſ error)
- func (xyyy *Template) MustCompile(name string) *CompiledTemplate
- func (xyyy *Template) String() string
- type Text
Examples ¶
Constants ¶
const ( IdForbidden flag // element should not have an id attribute ClassForbidden // element should not have a class attribute SelfClosing // element is selfclosing and contains no content Inline // element is an inline element (only for visible elements) FormField // element is a field of a form Invisible // element doesn't render anything visible WithoutEscaping // element does not escape inner Text WithoutDecoration // element just prints the InnerHtml )
Variables ¶
var Escaper = templ.Escaper{ "text": handleStrings(html.EscapeString, true), "": handleStrings(html.EscapeString, true), "html": handleStrings(idem, true), "px": units("%vpx"), "%": units("%v%%"), "em": units("%vem"), "pt": units("%vpt"), "urlparam": handleStrings(url.QueryEscape, false), }
Functions ¶
func Descendant ¶
func Descendant(selectors ...Selecter) combinator
F element descendant of an E element
func DirectFollows ¶
func DirectFollows(selectors ...Selecter) combinator
F element immediately preceded by an E element
Types ¶
type Attrs ¶
type Attrs []SingleAttr
type Class ¶
type Class string
func (Class) Placeholder ¶
func (xyyy Class) Placeholder() Placeholder
type Comment ¶
type Comment string
func (Comment) Placeholder ¶
func (xyyy Comment) Placeholder() Placeholder
type CompiledTemplate ¶
type Element ¶
type Element struct { Comment Comment ParentTags tags // contains filtered or unexported fields }
the base of what becomes a tag when printed
func NewElement ¶
contruct a new element with some flags.
the tag constructors A(), Body(),... use these method, see tags.go file for examples
use it for your own tags
the following flags are supported
IdForbidden // element should not have an id attribute ClassForbidden // element should not have a class attribute SelfClosing // element is selfclosing and contains no content Inline // element is an inline element (only for visible elements) Field // element is a field of a form Invisible // element doesn't render anything visible WithoutEscaping // element does not escape inner Text WithoutDecoration // element just prints the InnerHtml
see Add() and Set() methods for how to modify the Element
Example ¶
create an element with a simple self defined tag
t := NewElement(Tag("special")) fmt.Println(t)
Output: <special></special>
Example (MultipleFlags) ¶
multiple flags may be passed with bitwise or | and as several parameters
t := NewElement(Tag("input"), SelfClosing|Inline, FormField) fmt.Println(t)
Output: <input />
Example (Selfclosing) ¶
a selfclosing tag can't have content
t := NewElement(Tag("special"), SelfClosing) fmt.Println(t) if err := t.Add("will fail"); err != nil { fmt.Println("can't add to selfclosing element") }
Output: <special /> can't add to selfclosing element
Example (WithoutDecoration) ¶
create an element that does not output it tags when printed
doc := NewElement(Tag("doc"), WithoutDecoration) layout := NewTemplate(doc) body := NewElement(Tag("body")) body.Add(Id("content")) doc.Add( Html("<!DOCTYPE html>"), body, Html("</html>")) layout.Assign("content", "in the body") fmt.Println(layout)
Output: <!DOCTYPE html><body id="content">in the body</body></html>
func (*Element) Add ¶
adds new inner content or properties based on Stringer objects and returns an error if changes could not be applied
the following types are handled in a special way:
- Comment: sets the comment
- Style: set a single style
- Styles: sets multiple styles
- Attr: set a single attribute // do not set id or class via Attr(s) directly, use Id() and Class() instead
- Attrs: sets multiple attribute
- Class: adds a class
- Id: sets the id
- *Css: applies the css, see ApplyCss()
the following types are added to the inner content:
- Text: ís escaped if the WithoutEscaping flag isn't set
- Html: is never escaped
If the Stringer can be casted to an Elementer (as Element can), it is added to the inner content as well otherwise it is handled like Text(), that means any type implementing Stringer can be added as (escaped) text
Example ¶
html, text and elementer are added as inner content
div := NewElement(Tag("div")) span := NewElement(Tag("span")) span.Add("hiho") div.Add( Html("<b>hello</b>"), // is not escaped Text("c > d"), // is escaped span) // objects to tag constructors like Div(), Span(),... gets passed to Add() fmt.Println(div)
Output: <div><b>hello</b>c > d<span>hiho</span></div>
Example (Properties) ¶
add / set properties
// css := NewCss(Class("yellow"), Style("background-color", "yellow")) d := NewElement(Tag("div")) d.Add(Class("first")) d.Add( Id("main"), Class("second"), // css, // adds the class of the css to the element, multiple *Css can be given Comment("main row"), Attr("height", "200")) // multiple attributes at once with Attrs{"height", "200", "width", "300"} //Style("width", "500px")) // multiple styles at once with Styles{"height", "200", "width", "300"} //fmt.Printf("---CSS---%s---HTML---%s\n", css, d)
Output:
func (*Element) AddAfter ¶
adds Elementer at the position before the Element in the inner content the following elements are moved down
func (*Element) AddAtPosition ¶
adds Elementer to the inner content at position pos
func (*Element) AddBefore ¶
adds Elementer at the position before the Element in the inner content the following elements are moved down
func (*Element) AddClass ¶
use this func to add the classes of the tag, do not set it via Attr directly
func (*Element) All ¶
filter by anything that fullfills the matcher interface, e.g. Class, Id, Attr, Attrs, Css, Tag, Style, Styles recursive finds all tags from the children
func (*Element) Any ¶
filter by anything that fullfills the matcher interface, e.g. Class, Id, Attr, Attrs, Css, Tag, Style, Styles returns the first tag in the children and the subchildren that matches
func (*Element) AsTemplate ¶
func (*Element) Attributes ¶
func (*Element) AttrsString ¶
prepare the id attribute for output
func (*Element) Compile ¶
func (xyyy *Element) Compile(name string) *CompiledTemplate
func (*Element) IsParentAllowed ¶
return false if the given Parent tag is not allowed for Elements tag
func (*Element) Placeholder ¶
func (xyyy *Element) Placeholder(name string) *CompiledTemplate
func (*Element) PositionOf ¶
returns the position of the Element in the inner content. if it could not be found, the last parameter is false
func (*Element) RemoveAttribute ¶
removes an attribute
func (*Element) RemoveClass ¶
func (*Element) SetAtPosition ¶
set the Elementer to the inner content at position pos and overwrite the current content at that position
func (*Element) SetAttribute ¶
sets the attribute k to v as long as k is not "id" or "class" use SetId() to set the id and AddClass() to add a class
func (*Element) SetAttributes ¶
func (*Element) SetBottom ¶
sets the Elementer to the last position of the inner content and overwrites the current content at that position
If you want to append to the inner content, use Add() instead
func (*Element) SetClass ¶
use this func to set the classes of the Element do not set them via Attr directly
func (*Element) SetContent ¶
clears the inner object array and then calles Add() method to add content
see Add() method for more details
func (*Element) SetId ¶
use this func to set the id of the Element, do not set it via Attr directly returns error if IdForbidden flag is set
func (*Element) String ¶
returns the html with inner content (and the own tags if WithoutDecoration is not set)
func (*Element) WrapChildren ¶
wraps the children with the given element
type Elementer ¶
an Elementer might be parent of an Element by implementing a type that fulfills this interface you might peek into the execution. when String() method is called, the html of the tree is built and when SetParent() it is embedded in another Elementer it could be combined with the Pather interface that allows you to modify specific css selectors for any children Elements
type FieldMatcher ¶
type FieldMatcher int
func (FieldMatcher) Matches ¶
func (xyyy FieldMatcher) Matches(t *Element) (m bool)
type Html ¶
type Html string
func (Html) Placeholder ¶
func (xyyy Html) Placeholder() Placeholder
type Placeholder ¶
type PositionMatcher ¶
func (*PositionMatcher) Matches ¶
func (xyyy *PositionMatcher) Matches(e *Element) (f bool)
type SelecterAdder ¶
type SelecterAdder interface { Selector() string Add(Selecter) SelecterAdder }
type SelectorString ¶
type SelectorString string
func (SelectorString) Selector ¶
func (xyyy SelectorString) Selector() string
type SingleAttr ¶
func (SingleAttr) Matches ¶
func (xyyy SingleAttr) Matches(t *Element) bool
func (SingleAttr) Placeholder ¶
func (xyyy SingleAttr) Placeholder() Placeholder
func (SingleAttr) String ¶
func (xyyy SingleAttr) String() string
type Style ¶
type Style struct{ Property, Value string }
func (Style) Placeholder ¶
func (xyyy Style) Placeholder() Placeholder
type Templatable ¶
type Template ¶
type Template struct { Element Templatable //*Element // contains filtered or unexported fields }
func NewTemplate ¶
func NewTemplate(t Templatable) *Template
creates a new template with the given element as root
func (*Template) AddCss ¶
add css to the head of the template returns an error if Element is no doc or has no head child
func (*Template) Assign ¶
replaces the content of an child Element with the given id with Stringer e.g.
t := NewTemplate(Body(Div(Id("content")))) t.Assign("content", P(Text("here we go")))
results in <body><div id="content"><p>here we go</p></div></body>
func (*Template) Compile ¶
func (xyyy *Template) Compile(name string) (c *CompiledTemplate, ſ error)
returns a *CompiledTemplate that is a template.Template (see github.com/metakeule/template) the template can then be initialized with New and merged with placeholders with Replace and Merge if you need to change the original template again, you can get it via CompiledTemplate.ElementTemplate then call Compile() again to get a new CompiledTemplate
func (*Template) MustCompile ¶
func (xyyy *Template) MustCompile(name string) *CompiledTemplate
panics on error