This repository has been archived by the owner on Jul 13, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
sheet.go
130 lines (117 loc) · 2.47 KB
/
sheet.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
package gs
type Sheet struct {
id int64
CLasses ClassMap
rules RuleList
list []string
idGen func() string
attached bool
registry Registry
}
// AddRule processes the rules are returns mapping of original classnames to the
// generated classnames.
//
// The resulting class map is merged with the existing classmap, so added
// classes can always be acced by s.Classes[className] field. The processed
// rules are stored in the stylesheet, note that this doesn't attach the sheet
// to the dom. You need to explicitly call Attach method to attach the styles to
// the dom.
func (s *Sheet) AddRule(rules CSSRule) ClassMap {
m := make(ClassMap)
v := Process(rules, classNamer(
namerFunc(m, s.idGen),
))
if ls, ok := v.(RuleList); ok {
s.rules = append(s.rules, ls...)
} else {
s.rules = append(s.rules, v)
}
for k, v := range m {
s.CLasses[k] = v
}
return m
}
// func (s *Sheet) Text() string {
// return s.rules.String()
// }
func NewSheet(idGen func() string) *Sheet {
return &Sheet{CLasses: make(ClassMap), idGen: idGen}
}
func namerFunc(c ClassMap, idGen func() string) func(string) string {
return func(s string) string {
if exist, ok := c[s]; ok {
return exist
}
gen := s + "-" + idGen()
c[s] = gen
return gen
}
}
type ClassMap map[string]string
// Classes to be compatible with vecty.ClassMap
func (c ClassMap) Classes() map[string]bool {
o := make(map[string]bool)
for _, v := range c {
o[toClassname(v)] = true
}
return o
}
func toClassname(c string) string {
if c == "" {
return c
}
if c[0] == '.' {
return c[1:]
}
return c
}
func isClass(s string) bool {
return s != "" && s[0] == '.'
}
func classNamer(namer func(string) string) Transformer {
return func(rules CSSRule) CSSRule {
switch e := rules.(type) {
case StyleRule:
if isClass(e.Selector) {
e.Selector = namer(e.Selector)
}
return e
case RuleList:
var o RuleList
for _, v := range e {
o = append(o, classNamer(namer)(v))
}
return o
default:
return e
}
}
}
func (s *Sheet) Attach() {
if !s.attached {
s.registry.Attach(s)
s.attached = true
}
}
func (s *Sheet) Detach() {
if s.attached {
s.registry.Detach(s)
s.attached = false
}
}
func (s *Sheet) ListRules() []string {
if s.list != nil {
return s.list
}
for _, v := range s.rules {
s.list = append(s.list, v.String())
}
return s.list
}
type Registry interface {
NewSheet() *Sheet
Attach(*Sheet)
Detach(*Sheet)
//again no user implementation
isRegistry()
}