mdlist.gno
3.33 Kb · 119 lines
1// Package mdlist is a proof-of-concept for composable UIs patterns.
2//
3// It allows specifying a data source and then dynamically rendering it as
4// a list or a grid.
5package mdlist
6
7import (
8 "strings"
9
10 "gno.land/p/moul/md/v0"
11)
12
13// XXX: configurable length UL
14// XXX: moul/pager.Pager-powered auto mdlist
15// XXX: func (l List) Render(path string) string {
16// XXX: add .Table()
17
18type Entries []Entry
19
20type Entry struct {
21 // Title is the title of the entry. Required.
22 Title string
23 // Body is the body of the entry. Required.
24 Body string
25 // Link is the URL of the entry. Optional.
26 Link string
27 // Links is a list of additional URLs of the entry. Optional.
28 Links []string
29}
30
31// BulletList returns entries as a markdown bullet list without truncation.
32func (l Entries) BulletList() string {
33 return l.BulletListTruncated(-1, -1)
34}
35
36// BulletListTruncated returns entries as a markdown bullet list with truncation.
37func (l Entries) BulletListTruncated(titleMaxLength, bodyMaxLength int) string {
38 items := make([]string, len(l))
39 for i, entry := range l {
40 title := truncateText(entry.Title, titleMaxLength, false)
41 if entry.Link != "" {
42 title = md.Link(title, entry.Link)
43 }
44 body := truncateText(entry.Body, bodyMaxLength, true)
45 links := strings.Join(entry.Links, " ")
46 item := md.Bold(title) + ": " + md.Italic(body) + " " + links
47 items[i] = strings.TrimSpace(item)
48 }
49 return md.BulletList(items)
50}
51
52// NumberedList returns entries as a markdown numbered list without truncation.
53func (l Entries) NumberedList() string {
54 return l.NumberedListTruncated(-1, -1)
55}
56
57// NumberedListTruncated returns entries as a markdown numbered list with truncation.
58func (l Entries) NumberedListTruncated(titleMaxLength, bodyMaxLength int) string {
59 items := make([]string, len(l))
60 for i, entry := range l {
61 title := truncateText(entry.Title, titleMaxLength, false)
62 if entry.Link != "" {
63 title = md.Link(title, entry.Link)
64 }
65 body := truncateText(entry.Body, bodyMaxLength, true)
66 links := strings.Join(entry.Links, " ")
67 item := md.Bold(title) + ": " + md.Italic(body) + " " + links
68 items[i] = strings.TrimSpace(item)
69 }
70 return md.OrderedList(items)
71}
72
73// Paragraphs returns entries as simple paragraphs with bold titles.
74func (l Entries) Paragraphs() string {
75 paragraphs := make([]string, len(l))
76 for i, entry := range l {
77 title := entry.Title
78 if entry.Link != "" {
79 title = md.Link(title, entry.Link)
80 }
81 paragraph := md.Bold(title) + ". " + entry.Body
82 if len(entry.Links) > 0 {
83 paragraph += " " + strings.Join(entry.Links, " ")
84 }
85 paragraphs[i] = paragraph
86 }
87 return strings.Join(paragraphs, "\n\n")
88}
89
90func (l Entries) Columns() string {
91 columns := make([]string, len(l))
92 for i, entry := range l {
93 title := entry.Title
94 if entry.Link != "" {
95 title = md.Link(title, entry.Link)
96 }
97 body := entry.Body
98 links := strings.Join(entry.Links, " ")
99 columns[i] = md.H2(title) + md.Paragraph(body) + md.Paragraph(links)
100 }
101 return md.Columns(columns, false)
102}
103
104func truncateText(content string, maxLength int, withNewLines bool) string {
105 // If maxLength is -1, don't truncate
106 if maxLength < 0 {
107 if !withNewLines {
108 content = strings.ReplaceAll(content, "\n", " ")
109 }
110 return content
111 }
112 if !withNewLines {
113 content = strings.ReplaceAll(content, "\n", " ")
114 }
115 if len(content) > maxLength {
116 return content[:maxLength-3] + "..."
117 }
118 return content
119}