Gostar HTML Builder for Go

repository·main·Indexed 41 days ago

https://github.com/delaneyj/gostar

A fluent, type-safe HTML builder for Go that provides a programmatic way to construct HTML using a DSL based on the HTML Living Standard. It replaces string concatenation and standard templates with a fluent API and ElementRenderer types for creating reusable components.

Tokens
1.4K
Snippets
3
Records
4
Agent score
50%

What's inside Gostar

  1. What is Gostar?

    main
    Gostar is a fluent HTML builder for Go. It is designed to replace string concatenation or standard Go templates with a fluent API that allows for programmatic and natural HTML construction. The library is built directly from the HTML Living Standard, automatically providing conversions for all HTML elements and attributes.
  2. Create reusable HTML components with ElementRenderer

    main

    Gostar uses a fluent API where functions return ElementRenderer types. Because these are just functions, you can compose them into complex structures or define your own reusable components by creating functions that return an ElementRenderer.

    Common patterns include:

    • Composition: Nesting element functions (e.g., DIV(P().Text("..."))).
    • Custom Components: Defining variables or functions that encapsulate specific HTML structures.
    • Iteration: Using helper functions like Range to iterate over slices and generate elements for each item.
    // Example of a custom component
    var header = func(title string) ElementRenderer {
    	return HEADER(
    		TITLE().TextF("%s's Home Page", title),
    		DIV().CLASS("header").Text("Page Header"),
    	)
    }
  3. Install and import Gostar

    main

    To use Gostar, import the elements package. The author recommends using a dot import to avoid repetitive package prefixes, as all HTML tags and attributes are provided as uppercase functions to distinguish the DSL from Go keywords.

    import . "github.com/delaneyj/gostar/elements"
    import . "github.com/delaneyj/gostar/elements"
  4. Example: Building a complete HTML page

    main

    The following example demonstrates how to use Gostar to build a full HTML document, including a doctype, body, navigation, and content sections using custom components and iteration.

    import (
    	"net/http"
    	. "github.com/delaneyj/gostar/elements"
    )
    
    type Navigation struct {
    	Link string
    	Item string
    }
    
    type User struct {
    	FirstName      string
    	RawContent     string
    	EscapedContent string
    }
    
    var (
    	header = func(title string) ElementRenderer {
    		return HEADER(
    			TITLE().TextF("%s's Home Page", title),
    			DIV().CLASS("header").Text("Page Header"),
    		)
    	}
    
    	navigation = func(nav []*Navigation) ElementRenderer {
    		return NAV(
    			UL(
    				Range(nav, func(n *Navigation) ElementRenderer {
    					return LI(
    						A().HREF(n.Link).Text(n.Item),
    					)
    				}),
    			).CLASS("navigation"),
    		)
    	}
    
    	footer = func() ElementRenderer {
    		return FOOTER(DIV().CLASS("footer").Text("copyright 2016"))
    	}
    
    	index = func(u *User, nav []*Navigation, title string) ElementRenderer {
    		return Group(
    			Text("<!DOCTYPE html>"),
    			HTML(
    				BODY(
    					header(title),
    					navigation(nav),
    					SECTION(
    						DIV(
    							DIV(
    								H4().TextF("Hello %s", u.FirstName),
    									DIV().CLASS("raw").Text(u.RawContent),
    									DIV().CLASS("enc").Escaped(u.EscapedContent),
    								).CLASS("welcome"),
    								Range(lo.Range(5), func(i int) ElementRenderer {
    									count := i + 1
    									return Tern(
    n										count == 1,
    											P().TextF("%s has %d message", u.FirstName, count),
    											P().TextF("%s has %d messages", u.FirstName, count),
    									),
    								}),
    							).CLASS("content"),
    						),
    						),
    						footer(),
    					),
    				),
    			),
    		)
    	}
    )
    
    func indexHandler(w http.ResponseWriter, r *http.Request) {
    	user := &User{
    		FirstName:      "John",
    		RawContent:     `<a href="http://john.com">This is some raw content</a>`,
    		EscapedContent: `&lt;a href=&#34;http://john.com&#34;&gt;This is some encoded content&lt;/a&gt;`,
    	}
    
    	nav := []*Navigation{
    		{Link: "/home", Item: "Home"},
    		{Link: "/about", Item: "About"},
    	}
    
    	index(user, nav, "John").Render(w)
    }