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