|
@@ -1,5 +1,11 @@
|
|
package pgenr
|
|
package pgenr
|
|
|
|
|
|
|
|
+import (
|
|
|
|
+ "golang.org/x/net/html/atom"
|
|
|
|
+ "html"
|
|
|
|
+ "strings"
|
|
|
|
+)
|
|
|
|
+
|
|
const (
|
|
const (
|
|
TextThemeSuccess = "success"
|
|
TextThemeSuccess = "success"
|
|
TextThemeDanger = "danger"
|
|
TextThemeDanger = "danger"
|
|
@@ -11,35 +17,45 @@ type (
|
|
ButtonOption func(btn *Button)
|
|
ButtonOption func(btn *Button)
|
|
|
|
|
|
Text struct {
|
|
Text struct {
|
|
|
|
+ Tag atom.Atom
|
|
Content string
|
|
Content string
|
|
Theme string
|
|
Theme string
|
|
Color string
|
|
Color string
|
|
|
|
+ Style map[string]string
|
|
}
|
|
}
|
|
|
|
|
|
Button struct {
|
|
Button struct {
|
|
Url string
|
|
Url string
|
|
Text string
|
|
Text string
|
|
Color string
|
|
Color string
|
|
|
|
+ Style map[string]string
|
|
}
|
|
}
|
|
|
|
|
|
Entry struct {
|
|
Entry struct {
|
|
- Title string
|
|
|
|
|
|
+ Title *Text
|
|
Items map[string]*Text
|
|
Items map[string]*Text
|
|
}
|
|
}
|
|
|
|
|
|
Action struct {
|
|
Action struct {
|
|
- Instructions string
|
|
|
|
|
|
+ Instructions *Text
|
|
Button *Button
|
|
Button *Button
|
|
InviteCode string
|
|
InviteCode string
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ Table struct {
|
|
|
|
+ Title *Text
|
|
|
|
+ Header []*Text
|
|
|
|
+ Body [][]*Text
|
|
|
|
+ }
|
|
|
|
+
|
|
Page struct {
|
|
Page struct {
|
|
Title string
|
|
Title string
|
|
Head string
|
|
Head string
|
|
- Intros []string
|
|
|
|
|
|
+ Intros []*Text
|
|
Entries []*Entry
|
|
Entries []*Entry
|
|
- Actions []Action
|
|
|
|
- Outros []string
|
|
|
|
|
|
+ Actions []*Action
|
|
|
|
+ Tables []*Table
|
|
|
|
+ Outros []*Text
|
|
Copyright string
|
|
Copyright string
|
|
}
|
|
}
|
|
)
|
|
)
|
|
@@ -62,8 +78,13 @@ func (page *Page) SetCopyright(s string) *Page {
|
|
return page
|
|
return page
|
|
}
|
|
}
|
|
|
|
|
|
-func (page *Page) AddIntro(s string) *Page {
|
|
|
|
- page.Intros = append(page.Intros, s)
|
|
|
|
|
|
+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
|
|
return page
|
|
}
|
|
}
|
|
|
|
|
|
@@ -72,34 +93,50 @@ func (page *Page) AddEntry(e *Entry) *Page {
|
|
return page
|
|
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 {
|
|
func (page *Page) AddButtonAction(s string, btn *Button) *Page {
|
|
- page.Actions = append(page.Actions, Action{Instructions: s, Button: btn})
|
|
|
|
|
|
+ page.Actions = append(page.Actions, &Action{Instructions: NewText(s, 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: s, InviteCode: code})
|
|
|
|
|
|
+ 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
|
|
return page
|
|
}
|
|
}
|
|
|
|
|
|
-func (page *Page) AddOutro(s string) *Page {
|
|
|
|
- page.Outros = append(page.Outros, s)
|
|
|
|
|
|
+func (page *Page) AddPlainOutro(s string) *Page {
|
|
|
|
+ page.Outros = append(page.Outros, NewText(s, WithTextTag(atom.P)))
|
|
return page
|
|
return page
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+func (page *Page) Escape() {
|
|
|
|
+ page.Head = html.EscapeString(page.Head)
|
|
|
|
+ page.Copyright = html.EscapeString(page.Copyright)
|
|
|
|
+}
|
|
|
|
+
|
|
func NewPage(title string) *Page {
|
|
func NewPage(title string) *Page {
|
|
return &Page{
|
|
return &Page{
|
|
Title: title,
|
|
Title: title,
|
|
- Intros: make([]string, 0),
|
|
|
|
|
|
+ Intros: make([]*Text, 0),
|
|
Entries: make([]*Entry, 0),
|
|
Entries: make([]*Entry, 0),
|
|
- Actions: make([]Action, 0),
|
|
|
|
- Outros: make([]string, 0),
|
|
|
|
|
|
+ Actions: make([]*Action, 0),
|
|
|
|
+ Outros: make([]*Text, 0),
|
|
|
|
+ Tables: make([]*Table, 0),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
func NewEntry(title string) *Entry {
|
|
func NewEntry(title string) *Entry {
|
|
return &Entry{
|
|
return &Entry{
|
|
- Title: title,
|
|
|
|
|
|
+ Title: NewText(title, WithTextTag(atom.P)),
|
|
Items: make(map[string]*Text),
|
|
Items: make(map[string]*Text),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -110,12 +147,141 @@ func WithTextTheme(s string) TextOption {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+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 {
|
|
func WithTextColor(color string) TextOption {
|
|
return func(t *Text) {
|
|
return func(t *Text) {
|
|
t.Color = color
|
|
t.Color = color
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+func (button *Button) String() string {
|
|
|
|
+ var (
|
|
|
|
+ sb strings.Builder
|
|
|
|
+ )
|
|
|
|
+ if button.Style == nil {
|
|
|
|
+ button.Style = make(map[string]string)
|
|
|
|
+ }
|
|
|
|
+ if button.Color != "" {
|
|
|
|
+ button.Style["color"] = button.Color
|
|
|
|
+ }
|
|
|
|
+ sb.WriteString("<a class='button'")
|
|
|
|
+ if button.Url != "" {
|
|
|
|
+ sb.WriteString(" href='" + button.Url + "'")
|
|
|
|
+ }
|
|
|
|
+ if len(button.Style) > 0 {
|
|
|
|
+ sb.WriteString(" style='")
|
|
|
|
+ for k, v := range button.Style {
|
|
|
|
+ sb.WriteString(k)
|
|
|
|
+ sb.WriteString(":")
|
|
|
|
+ sb.WriteString(v)
|
|
|
|
+ sb.WriteString(";")
|
|
|
|
+ }
|
|
|
|
+ sb.WriteString("'")
|
|
|
|
+ }
|
|
|
|
+ sb.WriteString(">")
|
|
|
|
+ sb.WriteString(html.EscapeString(button.Text))
|
|
|
|
+ sb.WriteString("</a>")
|
|
|
|
+ return sb.String()
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (table *Table) SetHead(header ...*Text) {
|
|
|
|
+ table.Header = header
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (table *Table) AddCell(texts ...*Text) {
|
|
|
|
+ if table.Body == nil {
|
|
|
|
+ table.Body = make([][]*Text, 0)
|
|
|
|
+ }
|
|
|
|
+ table.Body = append(table.Body, texts)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (table *Table) String() string {
|
|
|
|
+ var (
|
|
|
|
+ sb strings.Builder
|
|
|
|
+ )
|
|
|
|
+ sb.WriteString("<div class='table-wrapper'>")
|
|
|
|
+ if table.Title != nil {
|
|
|
|
+ sb.WriteString("<div class='table-title'>")
|
|
|
|
+ sb.WriteString(table.Title.String())
|
|
|
|
+ sb.WriteString("</div>")
|
|
|
|
+ }
|
|
|
|
+ sb.WriteString("<table class='table'>")
|
|
|
|
+
|
|
|
|
+ if len(table.Header) > 0 {
|
|
|
|
+ sb.WriteString("<thead><tr>")
|
|
|
|
+ for _, text := range table.Header {
|
|
|
|
+ sb.WriteString("<th>")
|
|
|
|
+ sb.WriteString(text.String())
|
|
|
|
+ sb.WriteString("</th>")
|
|
|
|
+ }
|
|
|
|
+ sb.WriteString("</tr></thead>")
|
|
|
|
+ }
|
|
|
|
+ if len(table.Body) > 0 {
|
|
|
|
+ sb.WriteString("<tbody>")
|
|
|
|
+ for _, cell := range table.Body {
|
|
|
|
+ sb.WriteString("<tr>")
|
|
|
|
+ for _, text := range cell {
|
|
|
|
+ sb.WriteString("<td>")
|
|
|
|
+ sb.WriteString(text.String())
|
|
|
|
+ sb.WriteString("</td>")
|
|
|
|
+ }
|
|
|
|
+ sb.WriteString("</tr>")
|
|
|
|
+ }
|
|
|
|
+ sb.WriteString("</tbody>")
|
|
|
|
+ }
|
|
|
|
+ sb.WriteString("</table></div>")
|
|
|
|
+ return sb.String()
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (text *Text) String() string {
|
|
|
|
+ var (
|
|
|
|
+ sb strings.Builder
|
|
|
|
+ )
|
|
|
|
+ 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
|
|
|
|
+ }
|
|
|
|
+ sb.WriteString("<")
|
|
|
|
+ sb.WriteString(text.Tag.String())
|
|
|
|
+ if text.Theme != "" {
|
|
|
|
+ sb.WriteString(" class='text-")
|
|
|
|
+ sb.WriteString(text.Theme)
|
|
|
|
+ sb.WriteString("'")
|
|
|
|
+ }
|
|
|
|
+ if len(text.Style) > 0 {
|
|
|
|
+ sb.WriteString(" style='")
|
|
|
|
+ for k, v := range text.Style {
|
|
|
|
+ sb.WriteString(k)
|
|
|
|
+ sb.WriteString(":")
|
|
|
|
+ sb.WriteString(v)
|
|
|
|
+ sb.WriteString(";")
|
|
|
|
+ }
|
|
|
|
+ sb.WriteString("'")
|
|
|
|
+ }
|
|
|
|
+ sb.WriteString(">")
|
|
|
|
+ sb.WriteString(html.EscapeString(text.Content))
|
|
|
|
+ sb.WriteString("</")
|
|
|
|
+ sb.WriteString(text.Tag.String())
|
|
|
|
+ sb.WriteString(">")
|
|
|
|
+ return sb.String()
|
|
|
|
+}
|
|
|
|
+
|
|
func NewButton(label, link string, opts ...ButtonOption) *Button {
|
|
func NewButton(label, link string, opts ...ButtonOption) *Button {
|
|
btn := &Button{Text: label, Url: link}
|
|
btn := &Button{Text: label, Url: link}
|
|
for _, cb := range opts {
|
|
for _, cb := range opts {
|
|
@@ -125,9 +291,18 @@ func NewButton(label, link string, opts ...ButtonOption) *Button {
|
|
}
|
|
}
|
|
|
|
|
|
func NewText(s string, opts ...TextOption) *Text {
|
|
func NewText(s string, opts ...TextOption) *Text {
|
|
- txt := &Text{Content: s}
|
|
|
|
|
|
+ txt := &Text{Content: s, Tag: atom.Span}
|
|
for _, cb := range opts {
|
|
for _, cb := range opts {
|
|
cb(txt)
|
|
cb(txt)
|
|
}
|
|
}
|
|
return txt
|
|
return txt
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+func NewTable(title *Text) *Table {
|
|
|
|
+ table := &Table{
|
|
|
|
+ Title: title,
|
|
|
|
+ Header: make([]*Text, 0),
|
|
|
|
+ Body: make([][]*Text, 0),
|
|
|
|
+ }
|
|
|
|
+ return table
|
|
|
|
+}
|