summaryrefslogtreecommitdiff
path: root/vendor/github.com/aymerick/douceur/css
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/aymerick/douceur/css')
-rw-r--r--vendor/github.com/aymerick/douceur/css/declaration.go60
-rw-r--r--vendor/github.com/aymerick/douceur/css/rule.go230
-rw-r--r--vendor/github.com/aymerick/douceur/css/stylesheet.go25
3 files changed, 315 insertions, 0 deletions
diff --git a/vendor/github.com/aymerick/douceur/css/declaration.go b/vendor/github.com/aymerick/douceur/css/declaration.go
new file mode 100644
index 0000000..61d29d3
--- /dev/null
+++ b/vendor/github.com/aymerick/douceur/css/declaration.go
@@ -0,0 +1,60 @@
1package css
2
3import "fmt"
4
5// Declaration represents a parsed style property
6type Declaration struct {
7 Property string
8 Value string
9 Important bool
10}
11
12// NewDeclaration instanciates a new Declaration
13func NewDeclaration() *Declaration {
14 return &Declaration{}
15}
16
17// Returns string representation of the Declaration
18func (decl *Declaration) String() string {
19 return decl.StringWithImportant(true)
20}
21
22// StringWithImportant returns string representation with optional !important part
23func (decl *Declaration) StringWithImportant(option bool) string {
24 result := fmt.Sprintf("%s: %s", decl.Property, decl.Value)
25
26 if option && decl.Important {
27 result += " !important"
28 }
29
30 result += ";"
31
32 return result
33}
34
35// Equal returns true if both Declarations are equals
36func (decl *Declaration) Equal(other *Declaration) bool {
37 return (decl.Property == other.Property) && (decl.Value == other.Value) && (decl.Important == other.Important)
38}
39
40//
41// DeclarationsByProperty
42//
43
44// DeclarationsByProperty represents sortable style declarations
45type DeclarationsByProperty []*Declaration
46
47// Implements sort.Interface
48func (declarations DeclarationsByProperty) Len() int {
49 return len(declarations)
50}
51
52// Implements sort.Interface
53func (declarations DeclarationsByProperty) Swap(i, j int) {
54 declarations[i], declarations[j] = declarations[j], declarations[i]
55}
56
57// Implements sort.Interface
58func (declarations DeclarationsByProperty) Less(i, j int) bool {
59 return declarations[i].Property < declarations[j].Property
60}
diff --git a/vendor/github.com/aymerick/douceur/css/rule.go b/vendor/github.com/aymerick/douceur/css/rule.go
new file mode 100644
index 0000000..b5a44b5
--- /dev/null
+++ b/vendor/github.com/aymerick/douceur/css/rule.go
@@ -0,0 +1,230 @@
1package css
2
3import (
4 "fmt"
5 "strings"
6)
7
8const (
9 indentSpace = 2
10)
11
12// RuleKind represents a Rule kind
13type RuleKind int
14
15// Rule kinds
16const (
17 QualifiedRule RuleKind = iota
18 AtRule
19)
20
21// At Rules than have Rules inside their block instead of Declarations
22var atRulesWithRulesBlock = []string{
23 "@document", "@font-feature-values", "@keyframes", "@media", "@supports",
24}
25
26// Rule represents a parsed CSS rule
27type Rule struct {
28 Kind RuleKind
29
30 // At Rule name (eg: "@media")
31 Name string
32
33 // Raw prelude
34 Prelude string
35
36 // Qualified Rule selectors parsed from prelude
37 Selectors []string
38
39 // Style properties
40 Declarations []*Declaration
41
42 // At Rule embedded rules
43 Rules []*Rule
44
45 // Current rule embedding level
46 EmbedLevel int
47}
48
49// NewRule instanciates a new Rule
50func NewRule(kind RuleKind) *Rule {
51 return &Rule{
52 Kind: kind,
53 }
54}
55
56// Returns string representation of rule kind
57func (kind RuleKind) String() string {
58 switch kind {
59 case QualifiedRule:
60 return "Qualified Rule"
61 case AtRule:
62 return "At Rule"
63 default:
64 return "WAT"
65 }
66}
67
68// EmbedsRules returns true if this rule embeds another rules
69func (rule *Rule) EmbedsRules() bool {
70 if rule.Kind == AtRule {
71 for _, atRuleName := range atRulesWithRulesBlock {
72 if rule.Name == atRuleName {
73 return true
74 }
75 }
76 }
77
78 return false
79}
80
81// Equal returns true if both rules are equals
82func (rule *Rule) Equal(other *Rule) bool {
83 if (rule.Kind != other.Kind) ||
84 (rule.Prelude != other.Prelude) ||
85 (rule.Name != other.Name) {
86 return false
87 }
88
89 if (len(rule.Selectors) != len(other.Selectors)) ||
90 (len(rule.Declarations) != len(other.Declarations)) ||
91 (len(rule.Rules) != len(other.Rules)) {
92 return false
93 }
94
95 for i, sel := range rule.Selectors {
96 if sel != other.Selectors[i] {
97 return false
98 }
99 }
100
101 for i, decl := range rule.Declarations {
102 if !decl.Equal(other.Declarations[i]) {
103 return false
104 }
105 }
106
107 for i, rule := range rule.Rules {
108 if !rule.Equal(other.Rules[i]) {
109 return false
110 }
111 }
112
113 return true
114}
115
116// Diff returns a string representation of rules differences
117func (rule *Rule) Diff(other *Rule) []string {
118 result := []string{}
119
120 if rule.Kind != other.Kind {
121 result = append(result, fmt.Sprintf("Kind: %s | %s", rule.Kind.String(), other.Kind.String()))
122 }
123
124 if rule.Prelude != other.Prelude {
125 result = append(result, fmt.Sprintf("Prelude: \"%s\" | \"%s\"", rule.Prelude, other.Prelude))
126 }
127
128 if rule.Name != other.Name {
129 result = append(result, fmt.Sprintf("Name: \"%s\" | \"%s\"", rule.Name, other.Name))
130 }
131
132 if len(rule.Selectors) != len(other.Selectors) {
133 result = append(result, fmt.Sprintf("Selectors: %v | %v", strings.Join(rule.Selectors, ", "), strings.Join(other.Selectors, ", ")))
134 } else {
135 for i, sel := range rule.Selectors {
136 if sel != other.Selectors[i] {
137 result = append(result, fmt.Sprintf("Selector: \"%s\" | \"%s\"", sel, other.Selectors[i]))
138 }
139 }
140 }
141
142 if len(rule.Declarations) != len(other.Declarations) {
143 result = append(result, fmt.Sprintf("Declarations Nb: %d | %d", len(rule.Declarations), len(other.Declarations)))
144 } else {
145 for i, decl := range rule.Declarations {
146 if !decl.Equal(other.Declarations[i]) {
147 result = append(result, fmt.Sprintf("Declaration: \"%s\" | \"%s\"", decl.String(), other.Declarations[i].String()))
148 }
149 }
150 }
151
152 if len(rule.Rules) != len(other.Rules) {
153 result = append(result, fmt.Sprintf("Rules Nb: %d | %d", len(rule.Rules), len(other.Rules)))
154 } else {
155
156 for i, rule := range rule.Rules {
157 if !rule.Equal(other.Rules[i]) {
158 result = append(result, fmt.Sprintf("Rule: \"%s\" | \"%s\"", rule.String(), other.Rules[i].String()))
159 }
160 }
161 }
162
163 return result
164}
165
166// Returns the string representation of a rule
167func (rule *Rule) String() string {
168 result := ""
169
170 if rule.Kind == QualifiedRule {
171 for i, sel := range rule.Selectors {
172 if i != 0 {
173 result += ", "
174 }
175 result += sel
176 }
177 } else {
178 // AtRule
179 result += fmt.Sprintf("%s", rule.Name)
180
181 if rule.Prelude != "" {
182 if result != "" {
183 result += " "
184 }
185 result += fmt.Sprintf("%s", rule.Prelude)
186 }
187 }
188
189 if (len(rule.Declarations) == 0) && (len(rule.Rules) == 0) {
190 result += ";"
191 } else {
192 result += " {\n"
193
194 if rule.EmbedsRules() {
195 for _, subRule := range rule.Rules {
196 result += fmt.Sprintf("%s%s\n", rule.indent(), subRule.String())
197 }
198 } else {
199 for _, decl := range rule.Declarations {
200 result += fmt.Sprintf("%s%s\n", rule.indent(), decl.String())
201 }
202 }
203
204 result += fmt.Sprintf("%s}", rule.indentEndBlock())
205 }
206
207 return result
208}
209
210// Returns identation spaces for declarations and rules
211func (rule *Rule) indent() string {
212 result := ""
213
214 for i := 0; i < ((rule.EmbedLevel + 1) * indentSpace); i++ {
215 result += " "
216 }
217
218 return result
219}
220
221// Returns identation spaces for end of block character
222func (rule *Rule) indentEndBlock() string {
223 result := ""
224
225 for i := 0; i < (rule.EmbedLevel * indentSpace); i++ {
226 result += " "
227 }
228
229 return result
230}
diff --git a/vendor/github.com/aymerick/douceur/css/stylesheet.go b/vendor/github.com/aymerick/douceur/css/stylesheet.go
new file mode 100644
index 0000000..6b32c2e
--- /dev/null
+++ b/vendor/github.com/aymerick/douceur/css/stylesheet.go
@@ -0,0 +1,25 @@
1package css
2
3// Stylesheet represents a parsed stylesheet
4type Stylesheet struct {
5 Rules []*Rule
6}
7
8// NewStylesheet instanciate a new Stylesheet
9func NewStylesheet() *Stylesheet {
10 return &Stylesheet{}
11}
12
13// Returns string representation of the Stylesheet
14func (sheet *Stylesheet) String() string {
15 result := ""
16
17 for _, rule := range sheet.Rules {
18 if result != "" {
19 result += "\n"
20 }
21 result += rule.String()
22 }
23
24 return result
25}