diff --git a/examples/gno.land/p/demo/ui/ui.gno b/examples/gno.land/p/demo/ui/ui.gno new file mode 100644 index 00000000000..57c172d8b6a --- /dev/null +++ b/examples/gno.land/p/demo/ui/ui.gno @@ -0,0 +1,125 @@ +package ui + +type DOM struct { + // metadata + Prefix string + Title string + + // elements + Header Element + Body Element + Footer Element +} + +func (dom DOM) String() string { + output := "" + + if dom.Title != "" { + output += H1(dom.Title).String() + "\n" + } + + if !dom.Header.Empty() { + output += dom.Header.Content + "\n" + } + + if !dom.Body.Empty() { + output += dom.Body.Content + "\n" + } + + if !dom.Footer.Empty() { + output += dom.Footer.Content + "\n" + } + + // TODO: cleanup double new-lines. + + return output +} + +type Element struct { + Content string +} + +func (e Element) Empty() bool { + return e.Content == "" +} + +func (e *Element) Append(elems ...stringer) { + for _, elem := range elems { + e.Content += elem.String() + "\n" + } +} + +func Breadcrumb(entries ...stringer) stringer { + output := "" + for idx, entry := range entries { + if idx > 0 { + output += " / " + } + output += entry.String() + } + return Raw{Content: output} +} + +type Link struct { + Text string + Path string + URL string +} + +// TODO: image + +// TODO: pager + +func (l Link) String() string { + // TODO: additional arguments. + if l.Path != "" && l.URL != "" { + panic("a link should have a path OR a URL.") + } + + if l.Path != "" { + // TODO: prefix + l.URL = "prefix" + l.Path + } + return "[" + l.Text + "](" + l.URL + ")" +} + +func Paragraph(s string) stringer { + return Raw{Content: "\n" + s + "\n"} +} + +func BulletList(entries ...stringer) stringer { + output := "" + + for _, entry := range entries { + output += "- " + entry.String() + "\n" + } + + return Raw{Content: output} +} + +func Text(s string) stringer { + return Raw{Content: s} +} + +type stringer interface { + String() string +} + +type Raw struct { + Content string +} + +func (r Raw) String() string { + return r.Content +} + +func H1(text string) stringer { return Raw{Content: "# " + text + "\n"} } +func H2(text string) stringer { return Raw{Content: "## " + text + "\n"} } +func H3(text string) stringer { return Raw{Content: "### " + text + "\n"} } +func H4(text string) stringer { return Raw{Content: "#### " + text + "\n"} } +func H5(text string) stringer { return Raw{Content: "##### " + text + "\n"} } +func H6(text string) stringer { return Raw{Content: "###### " + text + "\n"} } +func Bold(text string) stringer { return Raw{Content: "**" + text + "**"} } +func Italic(text string) stringer { return Raw{Content: "_" + text + "_"} } +func Code(text string) stringer { return Raw{Content: "`" + text + "`"} } +func HR() stringer { return Raw{Content: "\n---\n"} } diff --git a/examples/gno.land/p/demo/ui/ui_test.gno b/examples/gno.land/p/demo/ui/ui_test.gno new file mode 100644 index 00000000000..5b1faa2932c --- /dev/null +++ b/examples/gno.land/p/demo/ui/ui_test.gno @@ -0,0 +1 @@ +package ui diff --git a/examples/gno.land/r/demo/ui/ui.gno b/examples/gno.land/r/demo/ui/ui.gno new file mode 100644 index 00000000000..34c387c5083 --- /dev/null +++ b/examples/gno.land/r/demo/ui/ui.gno @@ -0,0 +1,46 @@ +package ui + +import "gno.land/p/demo/ui" + +func Render(path string) string { + // TODO: build this realm as a demo one with one page per feature. + + // TODO: pagination + // TODO: non-standard markdown + // TODO: error, warn + // TODO: header + // TODO: HTML + // TODO: toc + // TODO: forms + // TODO: comments + + var dom ui.DOM + + dom.Title = "UI Demo" + + dom.Header.Append(ui.Breadcrumb( + ui.Link{Text: "foo", Path: "foo"}, + ui.Link{Text: "bar", Path: "foo/bar"}, + )) + + dom.Body.Append( + ui.Paragraph("Simple UI demonstration."), + ui.BulletList( + ui.Text("a text"), + ui.Link{Text: "a relative link", Path: "foobar"}, + ui.Text("another text"), + // ui.H1("a H1 text"), + ui.Bold("a bold text"), + ui.Italic("italic text"), + ui.Text("raw markdown with **bold** text in the middle."), + ui.Code("some inline code"), + ui.Link{Text: "a remote link", URL: "https://gno.land"}, + ), + ) + + dom.Footer.Append(ui.Text("I'm the footer.")) + dom.Body.Append(ui.Text("another string.")) + dom.Body.Append(ui.Paragraph("a paragraph."), ui.HR()) + + return dom.String() +} diff --git a/examples/gno.land/r/demo/ui/ui_test.gno b/examples/gno.land/r/demo/ui/ui_test.gno new file mode 100644 index 00000000000..e4c5474522a --- /dev/null +++ b/examples/gno.land/r/demo/ui/ui_test.gno @@ -0,0 +1,12 @@ +package ui + +import "testing" + +func TestRender(t *testing.T) { + got := Render("") + expected := "# UI Demo\n\n[foo](prefixfoo) / [bar](prefixfoo/bar)\n\n\nSimple UI demonstration.\n\n- a text\n- [a relative link](prefixfoobar)\n- another text\n- **a bold text**\n- _italic text_\n- raw markdown with **bold** text in the middle.\n- `some inline code`\n- [a remote link](https://gno.land)\n\nanother string.\n\na paragraph.\n\n\n---\n\n\nI'm the footer.\n\n" + + if got != expected { + t.Errorf("expected %q, got %q.", expected, got) + } +}