123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394 |
- package pgenr
- import (
- "bytes"
- "golang.org/x/net/html/atom"
- "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 (
- 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 {
- Title string
- Head string
- Intros []Element
- Entries []*Entry
- Actions []*Action
- Tables []*Table
- Outros []Element
- 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 {
- page.Head = s
- return page
- }
- func (page *Page) SetCopyright(s string) *Page {
- page.Copyright = s
- return page
- }
- func (page *Page) AddPlainIntro(s string) *Page {
- page.Intros = append(page.Intros, NewText(s, WithTextTag(atom.P)))
- return page
- }
- func (page *Page) AddIntro(t *Text) *Page {
- page.Intros = append(page.Intros, t)
- return page
- }
- func (page *Page) AddEntry(e *Entry) *Page {
- page.Entries = append(page.Entries, e)
- return page
- }
- func (page *Page) AddTable(t *Table) *Page {
- page.Tables = append(page.Tables, t)
- 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})
- return page
- }
- func (page *Page) AddInviteCodeAction(s string, code string) *Page {
- page.Actions = append(page.Actions, &Action{Instructions: NewText(s, WithTextTag(atom.P)), InviteCode: code})
- return page
- }
- func (page *Page) AddOutro(t *Text) *Page {
- page.Outros = append(page.Outros, t)
- return page
- }
- func (page *Page) AddPlainOutro(s string) *Page {
- page.Outros = append(page.Outros, NewText(s, WithTextTag(atom.P)))
- return page
- }
- func (page *Page) Escape() {
- page.Head = html.EscapeString(page.Head)
- page.Copyright = html.EscapeString(page.Copyright)
- }
- func NewPage(title string) *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),
- }
- return table
- }
|