about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--go.mod2
-rw-r--r--gomponents.go28
-rw-r--r--gomponents_test.go18
3 files changed, 47 insertions, 1 deletions
diff --git a/go.mod b/go.mod
index 8a7823b..0b6bf60 100644
--- a/go.mod
+++ b/go.mod
@@ -1,3 +1,3 @@
 module go.alanpearce.eu/gomponents
 
-go 1.18
+go 1.23
diff --git a/gomponents.go b/gomponents.go
index 4867152..1848291 100644
--- a/gomponents.go
+++ b/gomponents.go
@@ -22,6 +22,7 @@ import (
 	"fmt"
 	"html/template"
 	"io"
+	"iter"
 	"strings"
 )
 
@@ -277,6 +278,33 @@ func MapMap[K comparable, T any](ts map[K]T, cb func(K, T) Node) Group {
 	return nodes
 }
 
+// Map an iterator of anything to an IterNode (which is just an [iter.Seq] of [Node]-s)
+func MapIter[T any](ts iter.Seq[T], cb func(T) Node) IterNode {
+	return IterNode{
+		func(yield func(Node) bool) {
+			for t := range ts {
+				if !yield(cb(t)) {
+					return
+				}
+			}
+		},
+	}
+}
+
+type IterNode struct {
+	iter.Seq[Node]
+}
+
+func (it IterNode) Render(w io.Writer) error {
+	for node := range it.Seq {
+		if err := node.Render(w); err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
 // Group a slice of [Node]-s into one Node, while still being usable like a regular slice of [Node]-s.
 // A [Group] can render directly, but if any of the direct children are [AttributeType], they will be ignored,
 // to not produce invalid HTML.
diff --git a/gomponents_test.go b/gomponents_test.go
index 0d1c478..39b5fe6 100644
--- a/gomponents_test.go
+++ b/gomponents_test.go
@@ -5,6 +5,7 @@ import (
 	"fmt"
 	"io"
 	"os"
+	"slices"
 	"strings"
 	"testing"
 
@@ -302,6 +303,23 @@ func ExampleMapMap() {
 	// Output: <ul><li>party: hat</li><li>super: hat</li></ul>
 }
 
+func TestMapIter(t *testing.T) {
+	items := slices.Values([]string{"party hat", "super hat"})
+	e := g.El("ul", g.MapIter(items, func(value string) g.Node {
+		return g.El("li", g.Text(value))
+	}))
+	assert.Equal(t, `<ul><li>party hat</li><li>super hat</li></ul>`, e)
+}
+
+func ExampleMapIter() {
+	items := slices.Values([]string{"party hat", "super hat"})
+	e := g.El("ul", g.MapIter(items, func(value string) g.Node {
+		return g.El("li", g.Text(value))
+	}))
+	_ = e.Render(os.Stdout)
+	// Output: <ul><li>party hat</li><li>super hat</li></ul>
+}
+
 func TestGroup(t *testing.T) {
 	t.Run("groups multiple nodes into one", func(t *testing.T) {
 		children := []g.Node{g.El("br", g.Attr("id", "hat")), g.El("hr")}