-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcss.go
219 lines (187 loc) · 4.67 KB
/
css.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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
package html
type styleWriter func(tw *TagWriter)
// Style describes an individual CSS style, which contians a set of
// associations (element, class or id) and set of key/values which
// describe individual styles
type CSSData struct {
Attributes
css string
}
// NewStyle will create a Style object, identified by name.
// An optional list of StyleDef can be passed to add individual styles, or Add() can be called later
// The Style will need to be added to the Styles list to be rendered
func CSS(css string) *CSSData {
return &CSSData{
css: css,
}
}
func (css *CSSData) WriteContent(tw *TagWriter) {
tw.WriteString(css.css)
}
type CSSElement struct {
Container
css []*CSSData
}
// NewCSS will create a container to contain CSS objects
func NewCSS() *CSSElement {
css := &CSSElement{}
css.AddAttr("type", "text/css")
return css
}
// Write all styles
func (s *CSSElement) Write(tw *TagWriter) {
// nothing to do
if len(s.css) == 0 {
return
}
tw.WriteTag(TagStyle, s)
}
// Write each style
func (s *CSSElement) WriteContent(tw *TagWriter) {
for _, v := range s.css {
v.WriteContent(tw)
}
}
// Add CSS to the CSS container
func (s *CSSElement) Add(css *CSSData) {
s.css = append(s.css, css)
}
var (
styleSep = []byte(", ")
styleIndent = []byte(" ")
styleOpen = []byte(" {\n")
styleClose = []byte("}\n")
styleBreak = []byte(": ")
styleComplete = []byte(";\n")
)
// StyleDef describes an individual style key: value;
type StyleDef struct {
// Key is the key name
Key string
// Value is value for the key
Value string
}
// Style describes an individual CSS style, which contians a set of
// associations (element, class or id) and set of key/values which
// describe individual styles
type Style struct {
name string
// associations is an slice of associations which links a
// style to one or more HTML elements, classes or styles
// element: table
// class: .center or table.center
// id: #table1
associations []string
// styles key: value
styles map[string]string
}
// NewStyle will create a Style object, identified by name.
// An optional list of StyleDef can be passed to add individual styles, or Add() can be called later
// The Style will need to be added to the Styles list to be rendered
func NewStyle(name string, defs ...StyleDef) *Style {
style := &Style{
name: name,
styles: make(map[string]string),
}
style.Add(defs...)
return style
}
// Add will add individual styles
func (style *Style) Add(defs ...StyleDef) {
for _, def := range defs {
style.styles[def.Key] = def.Value
}
}
// Write renders the style to the io.Writer
func (s *Style) Write(tw *TagWriter) {
// If there are no associations, then can not write the style
if len(s.associations) == 0 {
return
}
// If there are no styles, then nothing to do
if len(s.styles) == 0 {
return
}
multiAssoc := false
for _, a := range s.associations {
if multiAssoc {
tw.Write(styleSep)
}
tw.WriteString(a)
multiAssoc = true
}
s.writeStyle(tw, func(tw *TagWriter) {
for k, v := range s.styles {
tw.Write(styleIndent)
tw.WriteString(k)
tw.Write(styleBreak) // :
tw.WriteString(v)
tw.Write(styleComplete) // ;\n
}
})
}
// Add Class to this style
func (s *Style) AddClass(c *Class) {
if c != nil {
s.associations = append(s.associations, "."+c.Name)
}
}
func (s *Style) writeStyle(tw *TagWriter, sw styleWriter) {
tw.Write(styleOpen)
sw(tw)
tw.Write(styleClose)
}
// StyleElement contains a map of styles
type StyleElement struct {
Attributes
styles map[string]*Style
}
// NewStyles will create a container to contain Style objects
func NewStyles() *StyleElement {
styles := &StyleElement{
styles: make(map[string]*Style),
}
styles.AddAttr("type", "text/css")
return styles
}
// Write all styles
func (s *StyleElement) Write(tw *TagWriter) {
// nothing to do
if len(s.styles) == 0 {
return
}
tw.WriteTag(TagStyle, s)
}
// Write each style
func (s *StyleElement) WriteContent(tw *TagWriter) {
for k, v := range s.styles {
tw.Comment("Style", k)
v.Write(tw)
}
}
// Add a Style to the Styles container
func (styles *StyleElement) Add(style *Style) {
styles.styles[style.name] = style
}
// Class is an association between Styles and elements
type Class struct {
// Name is the name of the Class
Name string
}
// NewClass creates a new CSS Class with name as the class name
func NewClass(name string) *Class {
return &Class{
Name: name,
}
}
// AddStyle is a convenience function for style.AddClass() which is awkward
func (c *Class) AddStyle(s *Style) {
s.AddClass(c)
}
// StyleBackgroundColor defines a background color
func StyleBackgroundColor(color string) StyleDef {
return StyleDef{
Key: "background",
Value: color,
}
}