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  }