css_toolkit 1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/css_toolkit.rb +21 -0
- data/lib/modules/css_base.rb +17 -0
- data/lib/modules/css_comment.rb +42 -0
- data/lib/modules/css_declaration.rb +149 -0
- data/lib/modules/css_import.rb +24 -0
- data/lib/modules/css_media_set.rb +88 -0
- data/lib/modules/css_misc.rb +149 -0
- data/lib/modules/css_parser.rb +463 -0
- data/lib/modules/css_properties.rb +195 -0
- data/lib/modules/css_rule_set.rb +197 -0
- data/lib/modules/css_stylesheet.rb +119 -0
- data/lib/modules/css_tidy.rb +78 -0
- data/lib/modules/yui_compressor.rb +224 -0
- metadata +78 -0
@@ -0,0 +1,195 @@
|
|
1
|
+
module CssTidy
|
2
|
+
|
3
|
+
# parser current context
|
4
|
+
NONE = 0
|
5
|
+
IN_SELECTOR = 1
|
6
|
+
IN_PROPERTY = 2
|
7
|
+
IN_VALUE = 3
|
8
|
+
IN_STRING = 4
|
9
|
+
IN_COMMENT = 5
|
10
|
+
IN_AT_BLOCK = 6
|
11
|
+
|
12
|
+
# All whitespace allowed in CSS
|
13
|
+
WHITESPACE = [' ',"\n","\t","\r","\x0B"]
|
14
|
+
|
15
|
+
# All CSS tokens used by tidy
|
16
|
+
TOKENS = %w[/ @ } { ; : = ' " ( , \\ ! $ % & ) * + . < > ? [ ] ^ ` | ~]
|
17
|
+
# All CSS units (CSS 3 units included)
|
18
|
+
units = ['in','cm','mm','pt','pc','px','rem','em','%','ex','gd','vw','vh','vm','deg','grad','rad','ms','s','khz','hz']
|
19
|
+
|
20
|
+
# Available at-rules
|
21
|
+
AT_RULES = {
|
22
|
+
'page' => IN_SELECTOR,
|
23
|
+
'font-face' => IN_SELECTOR,
|
24
|
+
'charset' => IN_VALUE,
|
25
|
+
'import' => IN_VALUE,
|
26
|
+
'namespace' => IN_VALUE,
|
27
|
+
'media' => IN_AT_BLOCK
|
28
|
+
}
|
29
|
+
|
30
|
+
# Properties that need a value with unit
|
31
|
+
unit_values = [
|
32
|
+
'background', 'background-position',
|
33
|
+
'border', 'border-top', 'border-right', 'border-bottom', 'border-left', 'border-width',
|
34
|
+
'border-top-width', 'border-right-width', 'border-left-width', 'border-bottom-width',
|
35
|
+
'bottom', 'border-spacing', 'font-size', 'height', 'left',
|
36
|
+
'margin', 'margin-top', 'margin-right', 'margin-bottom', 'margin-left',
|
37
|
+
'max-height', 'max-width', 'min-height', 'min-width', 'outline-width',
|
38
|
+
'padding', 'padding-top', 'padding-right', 'padding-bottom', 'padding-left',
|
39
|
+
'position', 'right', 'top', 'text-indent', 'letter-spacing', 'word-spacing', 'width'
|
40
|
+
]
|
41
|
+
|
42
|
+
# Properties that allow <color> as value
|
43
|
+
color_values = [
|
44
|
+
'background-color', 'border-color', 'border-top-color', 'border-right-color',
|
45
|
+
'border-bottom-color', 'border-left-color', 'color', 'outline-color'
|
46
|
+
]
|
47
|
+
|
48
|
+
# Default values for the background properties
|
49
|
+
background_prop_default = {
|
50
|
+
'background-image' => 'none',
|
51
|
+
'background-size' => 'auto',
|
52
|
+
'background-repeat' => 'repeat',
|
53
|
+
'background-position' => '0 0',
|
54
|
+
'background-attachment' => 'scroll',
|
55
|
+
'background-clip' => 'border',
|
56
|
+
'background-origin' => 'padding',
|
57
|
+
'background-color' => 'transparent',
|
58
|
+
}
|
59
|
+
|
60
|
+
# A list of all shorthand properties that are devided into four properties and/or have four subvalues
|
61
|
+
SHORTHANDS = {
|
62
|
+
'border-color' => ['border-top-color','border-right-color','border-bottom-color','border-left-color'],
|
63
|
+
'border-style' => ['border-top-style','border-right-style','border-bottom-style','border-left-style'],
|
64
|
+
'border-width' => ['border-top-width','border-right-width','border-bottom-width','border-left-width'],
|
65
|
+
'margin' => ['margin-top','margin-right','margin-bottom','margin-left'],
|
66
|
+
'padding' => ['padding-top','padding-right','padding-bottom','padding-left'],
|
67
|
+
}
|
68
|
+
|
69
|
+
# All CSS Properties
|
70
|
+
PROPERTIES = {
|
71
|
+
'background' => '1.0,2.0,2.1',
|
72
|
+
'background-color' => '1.0,2.0,2.1',
|
73
|
+
'background-image' => '1.0,2.0,2.1',
|
74
|
+
'background-repeat' => '1.0,2.0,2.1',
|
75
|
+
'background-attachment' => '1.0,2.0,2.1',
|
76
|
+
'background-position' => '1.0,2.0,2.1',
|
77
|
+
'border' => '1.0,2.0,2.1',
|
78
|
+
'border-top' => '1.0,2.0,2.1',
|
79
|
+
'border-right' => '1.0,2.0,2.1',
|
80
|
+
'border-bottom' => '1.0,2.0,2.1',
|
81
|
+
'border-left' => '1.0,2.0,2.1',
|
82
|
+
'border-color' => '1.0,2.0,2.1',
|
83
|
+
'border-top-color' => '2.0,2.1',
|
84
|
+
'border-bottom-color' => '2.0,2.1',
|
85
|
+
'border-left-color' => '2.0,2.1',
|
86
|
+
'border-right-color' => '2.0,2.1',
|
87
|
+
'border-style' => '1.0,2.0,2.1',
|
88
|
+
'border-top-style' => '2.0,2.1',
|
89
|
+
'border-right-style' => '2.0,2.1',
|
90
|
+
'border-left-style' => '2.0,2.1',
|
91
|
+
'border-bottom-style' => '2.0,2.1',
|
92
|
+
'border-width' => '1.0,2.0,2.1',
|
93
|
+
'border-top-width' => '1.0,2.0,2.1',
|
94
|
+
'border-right-width' => '1.0,2.0,2.1',
|
95
|
+
'border-left-width' => '1.0,2.0,2.1',
|
96
|
+
'border-bottom-width' => '1.0,2.0,2.1',
|
97
|
+
'border-collapse' => '2.0,2.1',
|
98
|
+
'border-spacing' => '2.0,2.1',
|
99
|
+
'bottom' => '2.0,2.1',
|
100
|
+
'caption-side' => '2.0,2.1',
|
101
|
+
'content' => '2.0,2.1',
|
102
|
+
'clear' => '1.0,2.0,2.1',
|
103
|
+
'clip' => '1.0,2.0,2.1',
|
104
|
+
'color' => '1.0,2.0,2.1',
|
105
|
+
'counter-reset' => '2.0,2.1',
|
106
|
+
'counter-increment' => '2.0,2.1',
|
107
|
+
'cursor' => '2.0,2.1',
|
108
|
+
'empty-cells' => '2.0,2.1',
|
109
|
+
'display' => '1.0,2.0,2.1',
|
110
|
+
'direction' => '2.0,2.1',
|
111
|
+
'float' => '1.0,2.0,2.1',
|
112
|
+
'font' => '1.0,2.0,2.1',
|
113
|
+
'font-family' => '1.0,2.0,2.1',
|
114
|
+
'font-style' => '1.0,2.0,2.1',
|
115
|
+
'font-variant' => '1.0,2.0,2.1',
|
116
|
+
'font-weight' => '1.0,2.0,2.1',
|
117
|
+
'font-stretch' => '2.0',
|
118
|
+
'font-size-adjust' => '2.0',
|
119
|
+
'font-size' => '1.0,2.0,2.1',
|
120
|
+
'height' => '1.0,2.0,2.1',
|
121
|
+
'left' => '1.0,2.0,2.1',
|
122
|
+
'line-height' => '1.0,2.0,2.1',
|
123
|
+
'list-style' => '1.0,2.0,2.1',
|
124
|
+
'list-style-type' => '1.0,2.0,2.1',
|
125
|
+
'list-style-image' => '1.0,2.0,2.1',
|
126
|
+
'list-style-position' => '1.0,2.0,2.1',
|
127
|
+
'margin' => '1.0,2.0,2.1',
|
128
|
+
'margin-top' => '1.0,2.0,2.1',
|
129
|
+
'margin-right' => '1.0,2.0,2.1',
|
130
|
+
'margin-bottom' => '1.0,2.0,2.1',
|
131
|
+
'margin-left' => '1.0,2.0,2.1',
|
132
|
+
'marks' => '1.0,2.0',
|
133
|
+
'marker-offset' => '2.0',
|
134
|
+
'max-height' => '2.0,2.1',
|
135
|
+
'max-width' => '2.0,2.1',
|
136
|
+
'min-height' => '2.0,2.1',
|
137
|
+
'min-width' => '2.0,2.1',
|
138
|
+
'overflow' => '1.0,2.0,2.1',
|
139
|
+
'orphans' => '2.0,2.1',
|
140
|
+
'outline' => '2.0,2.1',
|
141
|
+
'outline-width' => '2.0,2.1',
|
142
|
+
'outline-style' => '2.0,2.1',
|
143
|
+
'outline-color' => '2.0,2.1',
|
144
|
+
'padding' => '1.0,2.0,2.1',
|
145
|
+
'padding-top' => '1.0,2.0,2.1',
|
146
|
+
'padding-right' => '1.0,2.0,2.1',
|
147
|
+
'padding-bottom' => '1.0,2.0,2.1',
|
148
|
+
'padding-left' => '1.0,2.0,2.1',
|
149
|
+
'page-break-before' => '1.0,2.0,2.1',
|
150
|
+
'page-break-after' => '1.0,2.0,2.1',
|
151
|
+
'page-break-inside' => '2.0,2.1',
|
152
|
+
'page' => '2.0',
|
153
|
+
'position' => '1.0,2.0,2.1',
|
154
|
+
'quotes' => '2.0,2.1',
|
155
|
+
'right' => '2.0,2.1',
|
156
|
+
'size' => '1.0,2.0',
|
157
|
+
'speak-header' => '2.0,2.1',
|
158
|
+
'table-layout' => '2.0,2.1',
|
159
|
+
'top' => '1.0,2.0,2.1',
|
160
|
+
'text-indent' => '1.0,2.0,2.1',
|
161
|
+
'text-align' => '1.0,2.0,2.1',
|
162
|
+
'text-decoration' => '1.0,2.0,2.1',
|
163
|
+
'text-shadow' => '2.0',
|
164
|
+
'letter-spacing' => '1.0,2.0,2.1',
|
165
|
+
'word-spacing' => '1.0,2.0,2.1',
|
166
|
+
'text-transform' => '1.0,2.0,2.1',
|
167
|
+
'white-space' => '1.0,2.0,2.1',
|
168
|
+
'unicode-bidi' => '2.0,2.1',
|
169
|
+
'vertical-align' => '1.0,2.0,2.1',
|
170
|
+
'visibility' => '1.0,2.0,2.1',
|
171
|
+
'width' => '1.0,2.0,2.1',
|
172
|
+
'widows' => '2.0,2.1',
|
173
|
+
'z-index' => '1.0,2.0,2.1',
|
174
|
+
# Speech
|
175
|
+
'volume' => '2.0,2.1',
|
176
|
+
'speak' => '2.0,2.1',
|
177
|
+
'pause' => '2.0,2.1',
|
178
|
+
'pause-before' => '2.0,2.1',
|
179
|
+
'pause-after' => '2.0,2.1',
|
180
|
+
'cue' => '2.0,2.1',
|
181
|
+
'cue-before' => '2.0,2.1',
|
182
|
+
'cue-after' => '2.0,2.1',
|
183
|
+
'play-during' => '2.0,2.1',
|
184
|
+
'azimuth' => '2.0,2.1',
|
185
|
+
'elevation' => '2.0,2.1',
|
186
|
+
'speech-rate' => '2.0,2.1',
|
187
|
+
'voice-family' => '2.0,2.1',
|
188
|
+
'pitch' => '2.0,2.1',
|
189
|
+
'pitch-range' => '2.0,2.1',
|
190
|
+
'stress' => '2.0,2.1',
|
191
|
+
'richness' => '2.0,2.1',
|
192
|
+
'speak-punctuation' => '2.0,2.1',
|
193
|
+
'speak-numeral' => '2.0,2.1',
|
194
|
+
}
|
195
|
+
end
|
@@ -0,0 +1,197 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__)
|
2
|
+
require 'css_properties'
|
3
|
+
|
4
|
+
module CssTidy
|
5
|
+
|
6
|
+
# The RuleSet class takes ONE selector and a set of declarations
|
7
|
+
# Declarations are stored in order to allow for hacks such as the box model hacks
|
8
|
+
class RuleSet < CssBase
|
9
|
+
attr_accessor :declarations, :selectors
|
10
|
+
|
11
|
+
def initialize(opts={})
|
12
|
+
@selectors = []
|
13
|
+
|
14
|
+
# declarations are made up of: property S* ':' S* value;
|
15
|
+
@declarations = []
|
16
|
+
add_rule(opts)
|
17
|
+
end
|
18
|
+
|
19
|
+
def add_rule(opts={})
|
20
|
+
if opts[:selector] && opts[:declarations]
|
21
|
+
# we assume the declarations are valid, but top and tail whitespace
|
22
|
+
# and avoid duplicate selectors
|
23
|
+
@selectors << opts[:selector].strip unless @selectors.member?( opts[:selector])
|
24
|
+
opts[:declarations].strip.split(/[\;$]+/m).each do |declaration|
|
25
|
+
if matches = declaration.match(/(.[^:]*)\:(.[^;]*)(;|\Z)/i)
|
26
|
+
property, value, end_of_declaration = matches.captures
|
27
|
+
@declarations << CssTidy::Declaration.new(property.strip, value.strip)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
opts[:declarations].strip.split(';').each do |declaration|
|
31
|
+
property, value = declaration.strip.split(/:/)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
self
|
35
|
+
end
|
36
|
+
|
37
|
+
def << (declaration)
|
38
|
+
property, value = declaration.strip.split(':')
|
39
|
+
@declarations << CssTidy::Declaration.new(property.strip, value.strip)
|
40
|
+
end
|
41
|
+
|
42
|
+
def to_hash
|
43
|
+
declarations = []
|
44
|
+
@declarations.each do |declaration|
|
45
|
+
declarations << declaration.to_s
|
46
|
+
end
|
47
|
+
{@selectors, declarations}
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_s(format=:one_line)
|
51
|
+
return '' if @selectors.empty? || @declarations.empty?
|
52
|
+
|
53
|
+
declarations = []
|
54
|
+
@declarations.each do |declaration|
|
55
|
+
declarations << declaration.to_s
|
56
|
+
end
|
57
|
+
|
58
|
+
case format
|
59
|
+
when :one_line
|
60
|
+
@selectors.join(',') + '{' + declarations.join(';') + '}'
|
61
|
+
when :multi_line
|
62
|
+
@selectors.join(',') + "{\n " + declarations.join(";\n ") + "\n}"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Rule Sets know how to optimise themselves
|
67
|
+
|
68
|
+
def optimize(options)
|
69
|
+
merge_4_part_longhands
|
70
|
+
@declarations.each do |declaration|
|
71
|
+
declaration.optimize_colors if options[:optimize_colors]
|
72
|
+
declaration.fix_invalid_colors if options[:fix_invalid_colors]
|
73
|
+
declaration.downcase_property if options[:downcase_properties]
|
74
|
+
declaration.optimize_zeros if options[:optimize_zeros]
|
75
|
+
declaration.optimize_mp_shorthands if options[:optimize_margin_padding]
|
76
|
+
declaration.optimize_filters if options[:optimize_filters]
|
77
|
+
declaration.optimize_urls if options[:optimize_urls]
|
78
|
+
declaration.optimize_font_weight if options[:optimize_font_weight]
|
79
|
+
declaration.optimize_punctuation # no option
|
80
|
+
end
|
81
|
+
optimize_selectors(options)
|
82
|
+
end
|
83
|
+
|
84
|
+
def merge_4_part_longhands
|
85
|
+
SHORTHANDS.each do |shorthand, longhands|
|
86
|
+
values = []
|
87
|
+
important_count = 0
|
88
|
+
@declarations.each_with_index do |declaration, idx|
|
89
|
+
# if one is important, the new merged rule will be important.
|
90
|
+
# this will probably break CSS in some rare cases
|
91
|
+
important_count = declaration.important? ? important_count + 1 : important_count + 0
|
92
|
+
case declaration.property
|
93
|
+
when longhands[0]
|
94
|
+
values[0] = declaration.value
|
95
|
+
when longhands[1]
|
96
|
+
values[1] = declaration.value
|
97
|
+
when longhands[2]
|
98
|
+
values[2] = declaration.value
|
99
|
+
when longhands[3]
|
100
|
+
values[3] = declaration.value
|
101
|
+
end
|
102
|
+
end
|
103
|
+
# remove nil values
|
104
|
+
values.compact!
|
105
|
+
if values.size == 4
|
106
|
+
# remove the old ones
|
107
|
+
@declarations.delete_if do |decl|
|
108
|
+
longhands.include?(decl.property)
|
109
|
+
end
|
110
|
+
values.map!{|v| v.gsub(/!important/, '').strip}
|
111
|
+
important = important_count > 0 ? '!important' : ''
|
112
|
+
# add the new rule
|
113
|
+
@declarations << CssTidy::Declaration.new(shorthand, values.join(' ') + important)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def optimize_selectors(options)
|
119
|
+
@selectors.map do |selector|
|
120
|
+
# squish up IE comment in selector hack
|
121
|
+
selector.gsub!(/\s*>\s*\/\*\s*\*\/\s*/, '>/**/' )
|
122
|
+
# special case for IE
|
123
|
+
selector.gsub!(/:first-(line|letter)(,|\Z)/, ':first-\1 \2')
|
124
|
+
# remove any kind of comment string
|
125
|
+
if options[:keep_ie7_selector_comments]
|
126
|
+
selector.gsub!(/\/\*\*\//, '_IE7_') # protect from next options
|
127
|
+
end
|
128
|
+
if ! options[:keep_selector_comments]
|
129
|
+
selector.gsub!(/(\s+)?\/\*(.|[\r\n])*?\*\/(\s+)?/, '')
|
130
|
+
end
|
131
|
+
selector.gsub!(/_IE7_/, '/**/') # restore hack comments
|
132
|
+
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
# starting with colors
|
137
|
+
def optimize_colors
|
138
|
+
@declarations.each do |declaration|
|
139
|
+
declaration.optimize_colors
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
# starting with colors
|
144
|
+
def downcase_selectors
|
145
|
+
@selectors.map {|selector| selector.downcase }
|
146
|
+
end
|
147
|
+
|
148
|
+
def empty?
|
149
|
+
@declarations.empty?
|
150
|
+
end
|
151
|
+
|
152
|
+
def == (other_set)
|
153
|
+
# must at least have the same number of declarations and be same type of object
|
154
|
+
if other_set.respond_to?(:declaration_count) && declaration_count == other_set.declaration_count
|
155
|
+
number_of_identical_declations = 0
|
156
|
+
other_set.declarations.each do |other_dec|
|
157
|
+
@declarations.each do |this_dec|
|
158
|
+
if this_dec == other_dec
|
159
|
+
number_of_identical_declations += 1
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
true if declaration_count == number_of_identical_declations
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def + (other_set)
|
168
|
+
@selectors += other_set.selectors
|
169
|
+
self
|
170
|
+
end
|
171
|
+
|
172
|
+
def declaration_count
|
173
|
+
@declarations.length
|
174
|
+
end
|
175
|
+
|
176
|
+
def inspect(indent='')
|
177
|
+
puts indent + " + " + @selectors.join(',')
|
178
|
+
@declarations.each do |decl|
|
179
|
+
puts indent * 2 + "| " + decl.to_s
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def clear
|
184
|
+
@selectors = []
|
185
|
+
@declarations = []
|
186
|
+
end
|
187
|
+
|
188
|
+
private
|
189
|
+
|
190
|
+
|
191
|
+
def each_declaration
|
192
|
+
@values.each_index do |index|
|
193
|
+
yield @properties[index], @values[index]
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
module CssTidy
|
2
|
+
|
3
|
+
class StyleSheet
|
4
|
+
attr_accessor :in_media
|
5
|
+
alias :end_at_block :in_media
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
# nodes can contain any kind of object:
|
9
|
+
# * charset
|
10
|
+
# * media (which can contain media or rulesets)
|
11
|
+
# * rulesets
|
12
|
+
@nodes = []
|
13
|
+
@charset = ''
|
14
|
+
@in_media = false
|
15
|
+
end
|
16
|
+
|
17
|
+
def << (object)
|
18
|
+
# if we are in media block, then add object to the last node
|
19
|
+
if @in_media
|
20
|
+
if object.class == CssTidy::MediaSet
|
21
|
+
@nodes << object
|
22
|
+
else
|
23
|
+
@nodes.last << object
|
24
|
+
end
|
25
|
+
else
|
26
|
+
@nodes << object
|
27
|
+
if object.class == CssTidy::MediaSet
|
28
|
+
@in_media = true
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_s(format=:one_line)
|
34
|
+
css = ''
|
35
|
+
if ! @charset.empty?
|
36
|
+
css << "@charset #{@charset};" + ((format == :multi_line) ? "\n" : '')
|
37
|
+
end
|
38
|
+
|
39
|
+
@nodes.each do |node|
|
40
|
+
css << node.to_s(format) + ((format == :multi_line) ? "\n" : '')
|
41
|
+
end
|
42
|
+
css
|
43
|
+
end
|
44
|
+
|
45
|
+
def charset=(charset)
|
46
|
+
if @charset.empty?
|
47
|
+
@charset = charset.strip
|
48
|
+
return true
|
49
|
+
else
|
50
|
+
return false
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def charset
|
55
|
+
@charset
|
56
|
+
end
|
57
|
+
|
58
|
+
def optimize(options={})
|
59
|
+
keep_next_comment = false
|
60
|
+
|
61
|
+
@nodes.each_with_index do |node, idx|
|
62
|
+
if node.class == CssTidy::Comment
|
63
|
+
if node.is_special? && options[:keep_special_comments]
|
64
|
+
next # do nothing
|
65
|
+
elsif node.is_ie5_hack? && options[:keep_ie5_comment_hack] && ! options[:optimize_selectors]
|
66
|
+
node.text = '\\' # replace it
|
67
|
+
keep_next_comment = true
|
68
|
+
elsif keep_next_comment
|
69
|
+
node.text = '' # replace it
|
70
|
+
keep_next_comment = false
|
71
|
+
elsif ! options[:keep_comments]
|
72
|
+
node.printable = false # don't print this one
|
73
|
+
end
|
74
|
+
end
|
75
|
+
node.optimize(options)
|
76
|
+
end
|
77
|
+
|
78
|
+
if options[:optimize_selectors]
|
79
|
+
nodes_to_remove = []
|
80
|
+
length = @nodes.length
|
81
|
+
@nodes.each_with_index do |node, index|
|
82
|
+
if node.class == CssTidy::RuleSet
|
83
|
+
idx = index
|
84
|
+
# Check if properties also exist in another RuleSet
|
85
|
+
while idx < length -1
|
86
|
+
idx += 1 # start at the next one
|
87
|
+
# just Rulsets
|
88
|
+
if @nodes[idx].class == CssTidy::RuleSet
|
89
|
+
if ! node.empty? && node == @nodes[idx]
|
90
|
+
node += @nodes[idx]
|
91
|
+
nodes_to_remove << idx
|
92
|
+
@nodes[idx].clear
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
def inspect
|
103
|
+
indent = ' '
|
104
|
+
puts "Stylesheet"
|
105
|
+
@nodes.each_with_index do |node, idx|
|
106
|
+
case node.class.to_s
|
107
|
+
when 'CssTidy::RuleSet'
|
108
|
+
puts " + RuleSet"
|
109
|
+
when 'CssTidy::Comment'
|
110
|
+
puts " + Comment"
|
111
|
+
end
|
112
|
+
node.inspect(indent)
|
113
|
+
# puts node.class
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|