|
@@ -1,161 +1,25 @@
|
|
package pgenr
|
|
package pgenr
|
|
|
|
|
|
import (
|
|
import (
|
|
- "bytes"
|
|
|
|
|
|
+ "git.nspix.com/golang/pgenr/element"
|
|
"golang.org/x/net/html/atom"
|
|
"golang.org/x/net/html/atom"
|
|
"html"
|
|
"html"
|
|
- "sync"
|
|
|
|
)
|
|
)
|
|
|
|
|
|
-const (
|
|
|
|
- TextThemeSuccess = "success"
|
|
|
|
- TextThemeDanger = "danger"
|
|
|
|
-)
|
|
|
|
-
|
|
|
|
-var (
|
|
|
|
- bufferPool sync.Pool
|
|
|
|
-)
|
|
|
|
-
|
|
|
|
-func getBuffer() *bytes.Buffer {
|
|
|
|
- if v := bufferPool.Get(); v == nil {
|
|
|
|
- return new(bytes.Buffer)
|
|
|
|
- } else {
|
|
|
|
- return v.(*bytes.Buffer)
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func releaseBuffer(sb *bytes.Buffer) {
|
|
|
|
- sb.Reset()
|
|
|
|
- bufferPool.Put(sb)
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
type (
|
|
type (
|
|
- Element interface {
|
|
|
|
- Html() string
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- Style map[string]string
|
|
|
|
-
|
|
|
|
- TextOption func(t *Text)
|
|
|
|
-
|
|
|
|
- ButtonOption func(btn *Button)
|
|
|
|
-
|
|
|
|
- Text struct {
|
|
|
|
- Tag atom.Atom
|
|
|
|
- Content string
|
|
|
|
- Theme string
|
|
|
|
- Color string
|
|
|
|
- Style Style
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- Button struct {
|
|
|
|
- Url string
|
|
|
|
- Text string
|
|
|
|
- Color string
|
|
|
|
- Style Style
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- Entry struct {
|
|
|
|
- Title Element
|
|
|
|
- Items map[string]Element
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- Action struct {
|
|
|
|
- Instructions Element
|
|
|
|
- Button *Button
|
|
|
|
- InviteCode string
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- Table struct {
|
|
|
|
- Title Element
|
|
|
|
- Header []Element
|
|
|
|
- Body [][]Element
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
Page struct {
|
|
Page struct {
|
|
Title string
|
|
Title string
|
|
Head string
|
|
Head string
|
|
- Intros []Element
|
|
|
|
- Entries []*Entry
|
|
|
|
- Actions []*Action
|
|
|
|
- Tables []*Table
|
|
|
|
- Outros []Element
|
|
|
|
|
|
+ Intros []element.Element
|
|
|
|
+ Entries []*element.Entry
|
|
|
|
+ Actions []*element.Action
|
|
|
|
+ Timelines []*element.Timeline
|
|
|
|
+ Tables []*element.Table
|
|
|
|
+ Outros []element.Element
|
|
Copyright string
|
|
Copyright string
|
|
}
|
|
}
|
|
)
|
|
)
|
|
|
|
|
|
-func (s Style) Css(name string, value string) {
|
|
|
|
- s[name] = value
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func (s Style) String() string {
|
|
|
|
- br := getBuffer()
|
|
|
|
- defer releaseBuffer(br)
|
|
|
|
- for k, v := range s {
|
|
|
|
- br.WriteString(k)
|
|
|
|
- br.WriteString(":")
|
|
|
|
- br.WriteString(v)
|
|
|
|
- br.WriteString(";")
|
|
|
|
- }
|
|
|
|
- return br.String()
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func (a *Action) Html() string {
|
|
|
|
- return a.String()
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func (a *Action) String() string {
|
|
|
|
- br := getBuffer()
|
|
|
|
- defer releaseBuffer(br)
|
|
|
|
- if a.Instructions != nil {
|
|
|
|
- br.WriteString(a.Instructions.Html())
|
|
|
|
- }
|
|
|
|
- br.WriteString("<div class='action-block'>")
|
|
|
|
- if a.InviteCode != "" {
|
|
|
|
- br.WriteString("<span class='invite-code'>")
|
|
|
|
- br.WriteString(html.EscapeString(a.InviteCode))
|
|
|
|
- br.WriteString("</span>")
|
|
|
|
- }
|
|
|
|
- if a.Button != nil {
|
|
|
|
- br.WriteString(a.Button.String())
|
|
|
|
- }
|
|
|
|
- br.WriteString("</div>")
|
|
|
|
- return br.String()
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func (e *Entry) Html() string {
|
|
|
|
- return e.String()
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func (e *Entry) String() string {
|
|
|
|
- br := getBuffer()
|
|
|
|
- defer releaseBuffer(br)
|
|
|
|
- br.WriteString("<div class='grid'>")
|
|
|
|
- if e.Title != nil {
|
|
|
|
- br.WriteString(e.Title.Html())
|
|
|
|
- }
|
|
|
|
- for k, v := range e.Items {
|
|
|
|
- br.WriteString("<div class='row'>")
|
|
|
|
- br.WriteString("<div class='preview-label'>")
|
|
|
|
- br.WriteString(k)
|
|
|
|
- br.WriteString("</div>")
|
|
|
|
- br.WriteString("<div class='preview-value'>")
|
|
|
|
- br.WriteString(v.Html())
|
|
|
|
- br.WriteString("</div>")
|
|
|
|
- br.WriteString("</div>")
|
|
|
|
- }
|
|
|
|
- br.WriteString("</div>")
|
|
|
|
- return br.String()
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func (e *Entry) AddItem(label string, txt *Text) *Entry {
|
|
|
|
- if e.Items == nil {
|
|
|
|
- e.Items = make(map[string]Element)
|
|
|
|
- }
|
|
|
|
- e.Items[label] = txt
|
|
|
|
- return e
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
func (page *Page) SetHead(s string) *Page {
|
|
func (page *Page) SetHead(s string) *Page {
|
|
page.Head = s
|
|
page.Head = s
|
|
return page
|
|
return page
|
|
@@ -167,42 +31,47 @@ func (page *Page) SetCopyright(s string) *Page {
|
|
}
|
|
}
|
|
|
|
|
|
func (page *Page) AddPlainIntro(s string) *Page {
|
|
func (page *Page) AddPlainIntro(s string) *Page {
|
|
- page.Intros = append(page.Intros, NewText(s, WithTextTag(atom.P)))
|
|
|
|
|
|
+ page.Intros = append(page.Intros, element.NewText(s, element.WithTextTag(atom.P)))
|
|
return page
|
|
return page
|
|
}
|
|
}
|
|
|
|
|
|
-func (page *Page) AddIntro(t *Text) *Page {
|
|
|
|
- page.Intros = append(page.Intros, t)
|
|
|
|
|
|
+func (page *Page) AddIntro(ele element.Element) *Page {
|
|
|
|
+ page.Intros = append(page.Intros, ele)
|
|
return page
|
|
return page
|
|
}
|
|
}
|
|
|
|
|
|
-func (page *Page) AddEntry(e *Entry) *Page {
|
|
|
|
|
|
+func (page *Page) AddEntry(e *element.Entry) *Page {
|
|
page.Entries = append(page.Entries, e)
|
|
page.Entries = append(page.Entries, e)
|
|
return page
|
|
return page
|
|
}
|
|
}
|
|
|
|
|
|
-func (page *Page) AddTable(t *Table) *Page {
|
|
|
|
|
|
+func (page *Page) AddTable(t *element.Table) *Page {
|
|
page.Tables = append(page.Tables, t)
|
|
page.Tables = append(page.Tables, t)
|
|
return page
|
|
return page
|
|
}
|
|
}
|
|
|
|
|
|
-func (page *Page) AddButtonAction(s string, btn *Button) *Page {
|
|
|
|
- page.Actions = append(page.Actions, &Action{Instructions: NewText(s, WithTextTag(atom.P)), Button: btn})
|
|
|
|
|
|
+func (page *Page) AddTimeline(t *element.Timeline) *Page {
|
|
|
|
+ page.Timelines = append(page.Timelines, t)
|
|
|
|
+ return page
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (page *Page) AddButtonAction(s string, btn *element.Button) *Page {
|
|
|
|
+ page.Actions = append(page.Actions, &element.Action{Instructions: element.NewText(s, element.WithTextTag(atom.P)), Button: btn})
|
|
return page
|
|
return page
|
|
}
|
|
}
|
|
|
|
|
|
func (page *Page) AddInviteCodeAction(s string, code string) *Page {
|
|
func (page *Page) AddInviteCodeAction(s string, code string) *Page {
|
|
- page.Actions = append(page.Actions, &Action{Instructions: NewText(s, WithTextTag(atom.P)), InviteCode: code})
|
|
|
|
|
|
+ page.Actions = append(page.Actions, &element.Action{Instructions: element.NewText(s, element.WithTextTag(atom.P)), InviteCode: code})
|
|
return page
|
|
return page
|
|
}
|
|
}
|
|
|
|
|
|
-func (page *Page) AddOutro(t *Text) *Page {
|
|
|
|
- page.Outros = append(page.Outros, t)
|
|
|
|
|
|
+func (page *Page) AddOutro(ele element.Element) *Page {
|
|
|
|
+ page.Outros = append(page.Outros, ele)
|
|
return page
|
|
return page
|
|
}
|
|
}
|
|
|
|
|
|
func (page *Page) AddPlainOutro(s string) *Page {
|
|
func (page *Page) AddPlainOutro(s string) *Page {
|
|
- page.Outros = append(page.Outros, NewText(s, WithTextTag(atom.P)))
|
|
|
|
|
|
+ page.Outros = append(page.Outros, element.NewText(s, element.WithTextTag(atom.P)))
|
|
return page
|
|
return page
|
|
}
|
|
}
|
|
|
|
|
|
@@ -213,182 +82,12 @@ func (page *Page) Escape() {
|
|
|
|
|
|
func NewPage(title string) *Page {
|
|
func NewPage(title string) *Page {
|
|
return &Page{
|
|
return &Page{
|
|
- Title: title,
|
|
|
|
- Intros: make([]Element, 0),
|
|
|
|
- Entries: make([]*Entry, 0),
|
|
|
|
- Actions: make([]*Action, 0),
|
|
|
|
- Outros: make([]Element, 0),
|
|
|
|
- Tables: make([]*Table, 0),
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func NewEntry(title string) *Entry {
|
|
|
|
- return &Entry{
|
|
|
|
- Title: NewText(title, WithTextTag(atom.P)),
|
|
|
|
- Items: make(map[string]Element),
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func WithTextTheme(s string) TextOption {
|
|
|
|
- return func(t *Text) {
|
|
|
|
- t.Theme = s
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func WithTextStyle(ms map[string]string) TextOption {
|
|
|
|
- return func(t *Text) {
|
|
|
|
- t.Style = ms
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func WithTextTag(tag atom.Atom) TextOption {
|
|
|
|
- return func(t *Text) {
|
|
|
|
- t.Tag = tag
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func WithTextColor(color string) TextOption {
|
|
|
|
- return func(t *Text) {
|
|
|
|
- t.Color = color
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func (button *Button) Html() string {
|
|
|
|
- return button.String()
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func (button *Button) String() string {
|
|
|
|
- br := getBuffer()
|
|
|
|
- defer releaseBuffer(br)
|
|
|
|
- if button.Style == nil {
|
|
|
|
- button.Style = make(map[string]string)
|
|
|
|
- }
|
|
|
|
- if button.Color != "" {
|
|
|
|
- button.Style["color"] = button.Color
|
|
|
|
- }
|
|
|
|
- br.WriteString("<a class='button'")
|
|
|
|
- if button.Url != "" {
|
|
|
|
- br.WriteString(" href='" + button.Url + "'")
|
|
|
|
- }
|
|
|
|
- if len(button.Style) > 0 {
|
|
|
|
- br.WriteString(" style='")
|
|
|
|
- br.WriteString(button.Style.String())
|
|
|
|
- br.WriteString("'")
|
|
|
|
- }
|
|
|
|
- br.WriteString(">")
|
|
|
|
- br.WriteString(html.EscapeString(button.Text))
|
|
|
|
- br.WriteString("</a>")
|
|
|
|
- return br.String()
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func (table *Table) SetHead(elements ...Element) {
|
|
|
|
- table.Header = elements
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func (table *Table) AddCell(elements ...Element) {
|
|
|
|
- if table.Body == nil {
|
|
|
|
- table.Body = make([][]Element, 0)
|
|
|
|
- }
|
|
|
|
- table.Body = append(table.Body, elements)
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func (table *Table) String() string {
|
|
|
|
- br := getBuffer()
|
|
|
|
- defer releaseBuffer(br)
|
|
|
|
- br.WriteString("<div class='table-wrapper'>")
|
|
|
|
- if table.Title != nil {
|
|
|
|
- br.WriteString("<div class='table-title'>")
|
|
|
|
- br.WriteString(table.Title.Html())
|
|
|
|
- br.WriteString("</div>")
|
|
|
|
- }
|
|
|
|
- br.WriteString("<table class='table'>")
|
|
|
|
-
|
|
|
|
- if len(table.Header) > 0 {
|
|
|
|
- br.WriteString("<thead>")
|
|
|
|
- br.WriteString("<tr>")
|
|
|
|
- for _, text := range table.Header {
|
|
|
|
- br.WriteString("<th>")
|
|
|
|
- br.WriteString(text.Html())
|
|
|
|
- br.WriteString("</th>")
|
|
|
|
- }
|
|
|
|
- br.WriteString("</tr>")
|
|
|
|
- br.WriteString("</thead>")
|
|
|
|
- }
|
|
|
|
- if len(table.Body) > 0 {
|
|
|
|
- br.WriteString("<tbody>")
|
|
|
|
- for _, cell := range table.Body {
|
|
|
|
- br.WriteString("<tr>")
|
|
|
|
- for _, text := range cell {
|
|
|
|
- br.WriteString("<td>")
|
|
|
|
- br.WriteString(text.Html())
|
|
|
|
- br.WriteString("</td>")
|
|
|
|
- }
|
|
|
|
- br.WriteString("</tr>")
|
|
|
|
- }
|
|
|
|
- br.WriteString("</tbody>")
|
|
|
|
- }
|
|
|
|
- br.WriteString("</table>")
|
|
|
|
- br.WriteString("</div>")
|
|
|
|
- return br.String()
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func (text *Text) Html() string {
|
|
|
|
- return text.String()
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func (text *Text) String() string {
|
|
|
|
- br := getBuffer()
|
|
|
|
- defer releaseBuffer(br)
|
|
|
|
- if text.Style == nil {
|
|
|
|
- text.Style = make(map[string]string)
|
|
|
|
- }
|
|
|
|
- if text.Color != "" {
|
|
|
|
- text.Style["color"] = text.Color
|
|
|
|
- }
|
|
|
|
- if text.Tag == 0 {
|
|
|
|
- text.Tag = atom.Span
|
|
|
|
- }
|
|
|
|
- br.WriteString("<")
|
|
|
|
- br.WriteString(text.Tag.String())
|
|
|
|
- if text.Theme != "" {
|
|
|
|
- br.WriteString(" class='text-")
|
|
|
|
- br.WriteString(text.Theme)
|
|
|
|
- br.WriteString("'")
|
|
|
|
- }
|
|
|
|
- if len(text.Style) > 0 {
|
|
|
|
- br.WriteString(" style='")
|
|
|
|
- br.WriteString(text.Style.String())
|
|
|
|
- br.WriteString("'")
|
|
|
|
- }
|
|
|
|
- br.WriteString(">")
|
|
|
|
- br.WriteString(html.EscapeString(text.Content))
|
|
|
|
- br.WriteString("</")
|
|
|
|
- br.WriteString(text.Tag.String())
|
|
|
|
- br.WriteString(">")
|
|
|
|
- return br.String()
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func NewButton(label, link string, opts ...ButtonOption) *Button {
|
|
|
|
- btn := &Button{Text: label, Url: link}
|
|
|
|
- for _, cb := range opts {
|
|
|
|
- cb(btn)
|
|
|
|
- }
|
|
|
|
- return btn
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func NewText(s string, opts ...TextOption) *Text {
|
|
|
|
- txt := &Text{Content: s, Tag: atom.Span}
|
|
|
|
- for _, cb := range opts {
|
|
|
|
- cb(txt)
|
|
|
|
- }
|
|
|
|
- return txt
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-func NewTable(title *Text) *Table {
|
|
|
|
- table := &Table{
|
|
|
|
- Title: title,
|
|
|
|
- Header: make([]Element, 0),
|
|
|
|
- Body: make([][]Element, 0),
|
|
|
|
|
|
+ Title: title,
|
|
|
|
+ Intros: make([]element.Element, 0),
|
|
|
|
+ Entries: make([]*element.Entry, 0),
|
|
|
|
+ Actions: make([]*element.Action, 0),
|
|
|
|
+ Timelines: make([]*element.Timeline, 0),
|
|
|
|
+ Outros: make([]element.Element, 0),
|
|
|
|
+ Tables: make([]*element.Table, 0),
|
|
}
|
|
}
|
|
- return table
|
|
|
|
}
|
|
}
|