Search Apps Documentation Source Content File Folder Download Copy

ui.gno

4.54 Kb ยท 229 lines
  1package ui
  2
  3import (
  4	"strconv"
  5	"strings"
  6)
  7
  8type DOM struct {
  9	// metadata
 10	Prefix       string
 11	Title        string
 12	WithComments bool
 13	Classes      []string
 14
 15	// elements
 16	Header Element
 17	Body   Element
 18	Footer Element
 19}
 20
 21func (dom DOM) String() string {
 22	classes := strings.Join(dom.Classes, " ")
 23
 24	output := ""
 25
 26	if classes != "" {
 27		output += "<main class='" + classes + "'>" + "\n\n"
 28	}
 29
 30	if dom.Title != "" {
 31		output += H1(dom.Title).String(dom) + "\n"
 32	}
 33
 34	if header := dom.Header.String(dom); header != "" {
 35		if dom.WithComments {
 36			output += "<!-- header -->"
 37		}
 38		output += header + "\n"
 39		if dom.WithComments {
 40			output += "<!-- /header -->"
 41		}
 42	}
 43
 44	if body := dom.Body.String(dom); body != "" {
 45		if dom.WithComments {
 46			output += "<!-- body -->"
 47		}
 48		output += body + "\n"
 49		if dom.WithComments {
 50			output += "<!-- /body -->"
 51		}
 52	}
 53
 54	if footer := dom.Footer.String(dom); footer != "" {
 55		if dom.WithComments {
 56			output += "<!-- footer -->"
 57		}
 58		output += footer + "\n"
 59		if dom.WithComments {
 60			output += "<!-- /footer -->"
 61		}
 62	}
 63
 64	if classes != "" {
 65		output += "</main>"
 66	}
 67
 68	// TODO: cleanup double new-lines.
 69
 70	return output
 71}
 72
 73type Jumbotron []DomStringer
 74
 75func (j Jumbotron) String(dom DOM) string {
 76	output := `<div class="jumbotron">` + "\n\n"
 77	for _, elem := range j {
 78		output += elem.String(dom) + "\n"
 79	}
 80	output += `</div><!-- /jumbotron -->` + "\n"
 81	return output
 82}
 83
 84// XXX: rename Element to Div?
 85type Element []DomStringer
 86
 87func (e *Element) Append(elems ...DomStringer) {
 88	*e = append(*e, elems...)
 89}
 90
 91func (e *Element) String(dom DOM) string {
 92	output := ""
 93	for _, elem := range *e {
 94		output += elem.String(dom) + "\n"
 95	}
 96	return output
 97}
 98
 99type Breadcrumb []DomStringer
100
101func (b *Breadcrumb) Append(elems ...DomStringer) {
102	*b = append(*b, elems...)
103}
104
105func (b Breadcrumb) String(dom DOM) string {
106	output := ""
107	for idx, entry := range b {
108		if idx > 0 {
109			output += " / "
110		}
111		output += entry.String(dom)
112	}
113	return output
114}
115
116type Columns struct {
117	MaxWidth int
118	Columns  []Element
119}
120
121func (c *Columns) Append(elems ...Element) {
122	c.Columns = append(c.Columns, elems...)
123}
124
125func (c Columns) String(dom DOM) string {
126	output := `<div class="columns-` + strconv.Itoa(c.MaxWidth) + `">` + "\n"
127	for _, entry := range c.Columns {
128		output += `<div class="column">` + "\n\n"
129		output += entry.String(dom)
130		output += "</div><!-- /column-->\n"
131	}
132	output += "</div><!-- /columns-" + strconv.Itoa(c.MaxWidth) + " -->\n"
133	return output
134}
135
136type Link struct {
137	Text string
138	Path string
139	URL  string
140}
141
142// TODO: image
143
144// TODO: pager
145
146func (l Link) String(dom DOM) string {
147	url := ""
148	switch {
149	case l.Path != "" && l.URL != "":
150		panic("a link should have a path or a URL, not both.")
151	case l.Path != "":
152		if l.Text == "" {
153			l.Text = l.Path
154		}
155		url = dom.Prefix + l.Path
156	case l.URL != "":
157		if l.Text == "" {
158			l.Text = l.URL
159		}
160		url = l.URL
161	}
162
163	return "[" + l.Text + "](" + url + ")"
164}
165
166type BulletList []DomStringer
167
168func (bl BulletList) String(dom DOM) string {
169	output := ""
170
171	for _, entry := range bl {
172		output += "- " + entry.String(dom) + "\n"
173	}
174
175	return output
176}
177
178func Text(s string) DomStringer {
179	return Raw{Content: s}
180}
181
182type DomStringer interface {
183	String(dom DOM) string
184}
185
186type Raw struct {
187	Content string
188}
189
190func (r Raw) String(_ DOM) string {
191	return r.Content
192}
193
194type (
195	H1        string
196	H2        string
197	H3        string
198	H4        string
199	H5        string
200	H6        string
201	Bold      string
202	Italic    string
203	Code      string
204	Paragraph string
205	Quote     string
206	HR        struct{}
207)
208
209func (text H1) String(_ DOM) string        { return "# " + string(text) + "\n" }
210func (text H2) String(_ DOM) string        { return "## " + string(text) + "\n" }
211func (text H3) String(_ DOM) string        { return "### " + string(text) + "\n" }
212func (text H4) String(_ DOM) string        { return "#### " + string(text) + "\n" }
213func (text H5) String(_ DOM) string        { return "##### " + string(text) + "\n" }
214func (text H6) String(_ DOM) string        { return "###### " + string(text) + "\n" }
215func (text Quote) String(_ DOM) string     { return "> " + string(text) + "\n" }
216func (text Bold) String(_ DOM) string      { return "**" + string(text) + "**" }
217func (text Italic) String(_ DOM) string    { return "_" + string(text) + "_" }
218func (text Paragraph) String(_ DOM) string { return "\n" + string(text) + "\n" }
219func (_ HR) String(_ DOM) string           { return "\n---\n" }
220
221func (text Code) String(_ DOM) string {
222	// multiline
223	if strings.Contains(string(text), "\n") {
224		return "\n```\n" + string(text) + "\n```\n"
225	}
226
227	// single line
228	return "`" + string(text) + "`"
229}