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 as4// a list or a grid.5package mdlist67import (8 "strings"910 "gno.land/p/moul/md/v0"11)1213// XXX: configurable length UL14// XXX: moul/pager.Pager-powered auto mdlist15// XXX: func (l List) Render(path string) string {16// XXX: add .Table()1718type Entries []Entry1920type Entry struct {21 // Title is the title of the entry. Required.22 Title string23 // Body is the body of the entry. Required.24 Body string25 // Link is the URL of the entry. Optional.26 Link string27 // Links is a list of additional URLs of the entry. Optional.28 Links []string29}3031// BulletList returns entries as a markdown bullet list without truncation.32func (l Entries) BulletList() string {33 return l.BulletListTruncated(-1, -1)34}3536// 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) + " " + links47 items[i] = strings.TrimSpace(item)48 }49 return md.BulletList(items)50}5152// NumberedList returns entries as a markdown numbered list without truncation.53func (l Entries) NumberedList() string {54 return l.NumberedListTruncated(-1, -1)55}5657// 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) + " " + links68 items[i] = strings.TrimSpace(item)69 }70 return md.OrderedList(items)71}7273// 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.Title78 if entry.Link != "" {79 title = md.Link(title, entry.Link)80 }81 paragraph := md.Bold(title) + ". " + entry.Body82 if len(entry.Links) > 0 {83 paragraph += " " + strings.Join(entry.Links, " ")84 }85 paragraphs[i] = paragraph86 }87 return strings.Join(paragraphs, "\n\n")88}8990func (l Entries) Columns() string {91 columns := make([]string, len(l))92 for i, entry := range l {93 title := entry.Title94 if entry.Link != "" {95 title = md.Link(title, entry.Link)96 }97 body := entry.Body98 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}103104func truncateText(content string, maxLength int, withNewLines bool) string {105 // If maxLength is -1, don't truncate106 if maxLength < 0 {107 if !withNewLines {108 content = strings.ReplaceAll(content, "\n", " ")109 }110 return content111 }112 if !withNewLines {113 content = strings.ReplaceAll(content, "\n", " ")114 }115 if len(content) > maxLength {116 return content[:maxLength-3] + "..."117 }118 return content119}120Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.