-
Notifications
You must be signed in to change notification settings - Fork 0
/
smetana.go
113 lines (99 loc) · 3.27 KB
/
smetana.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// Smetana is a library for programatically generating HTML and CSS.
// This can be pre-compiled for a static site, on-demand for dynamic
// pages, or somewhere in the middle with caching.
//
// The basic idea is that pages are constructed from a tree of structs
// that implement [Node]. These can be simple structures such as
// [DomNode] that correspond 1-to-1 with HTML tags (Smetana defines all
// standard HTML5 tag nodes for you) or [TextNode], or you can use
// these basic primitives to build more complex, reusable, React-style
// components.
//
// Typical usage looks something like this:
//
// smetana := s.NewSmetanaWithPalettes(s.Palettes{
// "light": {"color": s.Hex("#222")},
// "dark": {"color": s.Hex("#ddd")},
// })
// myClass := smetana.Styles.AddAnonClass(s.CssProps{
// "color": s.PaletteValue("color"),
// })
// page := Html(
// Head(
// Title("My HTML Document"),
// ),
// Body(
// myClass,
// Div(
// H(1, "Hello world"),
// P("Foo bar"),
// ),
// ),
// )
// htmlToServe := s.RenderHtml(page)
// cssToServe := smetana.RenderStyles()
package smetana
import "log"
// All structural elements of an HTML document are implementers of
// the [Node] interface for converting to HTML. This is primarily
// different types of HTML tags and text.
type Node interface {
ToHtml(b *Builder)
}
// Type alias for an HTML tag name (ie; "div", "span", etc.)
type Tag = string
// A single HTML attribute. For example,
//
// {Key: "href", Value: "https://duckduckgo.com"}
type Attr struct {
Key string
Value string
}
// A map of multiple HTML attributes.
type Attrs map[string]string
// Many types of [Node] have children to create a tree.
type Children []Node
// A map from a palette name to a [Palette]
type Palettes map[string]Palette
// The [Smetana] struct is an overarching compilation context for tying
// together different parts of the application.
type Smetana struct {
Palettes Palettes
Styles StyleSheet
}
// Create a new [Smetana] instance with default values.
func NewSmetana() Smetana {
return Smetana{
Palettes: Palettes{},
Styles: NewStyleSheet(),
}
}
// Create a new [Smetana] instance with specific [Palettes].
func NewSmetanaWithPalettes(palettes Palettes) Smetana {
return Smetana{
Palettes: palettes,
Styles: NewStyleSheet(),
}
}
// Add a new [Palette] to a [Smetana] context with the given name.
func (s *Smetana) AddPalette(name string, palette Palette) {
s.Palettes[name] = palette
}
// Render the styles from the [Smetana] context into CSS strings. One CSS
// stylesheet will be created for each palette added with [AddPalette]. The
// return value is a map from palette names to rendered CSS strings.
// See [RenderStylesOpts] for more fine-grained control.
func (s Smetana) RenderStyles() map[string]string {
return s.RenderStylesOpts(nil)
}
// Render the styles from the [Smetana] context into CSS strings. One CSS
// stylesheet will be created for each palette added with [AddPalette]. The
// return value is a map from palette names to rendered CSS strings.
// See [RenderStyles] for a simple interface with default values.
func (s Smetana) RenderStylesOpts(logger *log.Logger) map[string]string {
result := map[string]string{}
for name, palette := range s.Palettes {
result[name] = RenderCssOpts(s.Styles, palette, logger)
}
return result
}