tiny_css 0.0.2
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/README +62 -0
- data/lib/tiny_css.rb +10 -0
- data/lib/tiny_css/base.rb +75 -0
- data/lib/tiny_css/ordered_hash.rb +48 -0
- data/spec/base_spec.rb +220 -0
- data/spec/ordered_hash_spec.rb +187 -0
- data/spec/spec.opts +4 -0
- data/spec/style.css +19 -0
- data/tiny_css.gemspec +12 -0
- metadata +75 -0
data/README
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
TinyCss
|
2
|
+
=======
|
3
|
+
|
4
|
+
a ruby module to read and write .css stylesheets
|
5
|
+
|
6
|
+
|
7
|
+
Usage
|
8
|
+
=====
|
9
|
+
|
10
|
+
# In your .css file
|
11
|
+
H1 { color: blue }
|
12
|
+
H2 { color: red; font-family: Arial }
|
13
|
+
.this, .that { color: yellow }
|
14
|
+
|
15
|
+
# In your program
|
16
|
+
require 'tiny_css'
|
17
|
+
|
18
|
+
# Create a CSS stylesheet
|
19
|
+
css = TinyCss.new
|
20
|
+
|
21
|
+
# Open a CSS stylesheet
|
22
|
+
css = css.read('style.css')
|
23
|
+
|
24
|
+
# Reading properties
|
25
|
+
# (key is coverted to string, so you can access same value by symbol)
|
26
|
+
header_color = css.style['h1']['color']
|
27
|
+
css.style['h2'].each { |property, value| p "#{ property }: #{ value }" }
|
28
|
+
this_color = css.style[:this][:color]
|
29
|
+
that_color = css.style[:that][:color]
|
30
|
+
|
31
|
+
# Changing styles and properties
|
32
|
+
css.style['.newstyle']['color'] = '#FFFFFF' # Add a style
|
33
|
+
css.style['h1']['color'] = 'black' # Change a property
|
34
|
+
css.style['h2'].delete # Delete a style
|
35
|
+
|
36
|
+
# Save a CSS stylesheet
|
37
|
+
css.write 'style.css' # Sort selectors and properties
|
38
|
+
css.write 'style.css', false # Don't sort
|
39
|
+
|
40
|
+
|
41
|
+
Install
|
42
|
+
=======
|
43
|
+
|
44
|
+
git clone git://github.com/milk1000cc/tiny_css.git
|
45
|
+
|
46
|
+
or
|
47
|
+
|
48
|
+
sudo gem install tiny_css
|
49
|
+
|
50
|
+
|
51
|
+
Caution
|
52
|
+
=======
|
53
|
+
|
54
|
+
TinyCss#style doesn't return Hash object but TinyCss::OrderedHash, and TinyCss::OrderedHash class doesn't inherit Hash object.
|
55
|
+
|
56
|
+
I'm Japanese, and I'm not goot at English and Ruby, so please see the source code and edit them.
|
57
|
+
|
58
|
+
|
59
|
+
Author
|
60
|
+
======
|
61
|
+
|
62
|
+
milk1000cc <info@milk1000.cc>
|
data/lib/tiny_css.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
module TinyCss
|
2
|
+
class Base
|
3
|
+
attr_accessor :style
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@style = OrderedHash.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def read(file)
|
10
|
+
read_string open(file).read
|
11
|
+
end
|
12
|
+
|
13
|
+
def read_string(string)
|
14
|
+
string = string.tr("\n\t", ' ').gsub(%r!/\*.*?\*/!, '')
|
15
|
+
|
16
|
+
split_by_closing_brace(string).reject { |v| v !~ /\S/ }.each do |v|
|
17
|
+
unless match = v.match(/^\s*([^{]+?)\s*\{(.*)\}\s*$/)
|
18
|
+
raise Error, "Invalid or unexpected style data '#{ v }'"
|
19
|
+
end
|
20
|
+
|
21
|
+
style = match.captures.first
|
22
|
+
styles = style.gsub(/\s+/, ' ').split(/\s*,\s*/).
|
23
|
+
reject { |v| v !~ /\S/ }
|
24
|
+
|
25
|
+
match.captures.last.split(/\;/).reject { |v| v !~ /\S/ }.each do |v|
|
26
|
+
unless match = v.match(/^\s*([\w._-]+)\s*:\s*(.*?)\s*$/)
|
27
|
+
raise Error, "unexpected property '#{ v }' in style '#{ style }'"
|
28
|
+
end
|
29
|
+
styles.each do |v|
|
30
|
+
@style[v][match.captures.first.downcase] = match.captures.last
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
self
|
36
|
+
end
|
37
|
+
|
38
|
+
def write(file, sort = true)
|
39
|
+
open(file, 'w').write write_string(sort)
|
40
|
+
end
|
41
|
+
|
42
|
+
def write_string(sort = true)
|
43
|
+
style = @style.dup
|
44
|
+
contents = ''
|
45
|
+
selectors = style.keys
|
46
|
+
selectors.sort!.reverse! if sort
|
47
|
+
selectors.each do |selector|
|
48
|
+
contents += "#{ selector } {\n"
|
49
|
+
keys = style[selector].keys
|
50
|
+
keys.sort! if sort
|
51
|
+
keys.each { |k| contents += "\t#{ k }: #{ @style[selector][k] };\n" }
|
52
|
+
contents += "}\n"
|
53
|
+
end
|
54
|
+
|
55
|
+
contents
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
def split_by_closing_brace(string)
|
60
|
+
pattern = /(.+?\})/
|
61
|
+
ary = []
|
62
|
+
|
63
|
+
if string =~ pattern
|
64
|
+
string.gsub(pattern) { |matched| ary << matched }
|
65
|
+
if match = string.match(/.+\}(.+)$/)
|
66
|
+
ary << match.captures.first
|
67
|
+
end
|
68
|
+
else
|
69
|
+
ary << string
|
70
|
+
end
|
71
|
+
|
72
|
+
ary
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module TinyCss
|
2
|
+
class OrderedHash
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
attr_accessor :keys
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
self.keys = []
|
9
|
+
@hash = Hash.new { |h, k|
|
10
|
+
self.keys << k.to_s
|
11
|
+
h[k] = OrderedHash.new
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
def [](key)
|
16
|
+
@hash[key.to_s]
|
17
|
+
end
|
18
|
+
|
19
|
+
def []=(key, value)
|
20
|
+
key = key.to_s
|
21
|
+
@hash[key] = value
|
22
|
+
self.keys << key unless self.keys.include?(key)
|
23
|
+
end
|
24
|
+
|
25
|
+
def delete(key, &block)
|
26
|
+
key = key.to_s
|
27
|
+
self.keys.delete key
|
28
|
+
@hash.delete key, &block
|
29
|
+
end
|
30
|
+
|
31
|
+
def dup
|
32
|
+
dup = super
|
33
|
+
dup.keys = self.keys.dup
|
34
|
+
dup
|
35
|
+
end
|
36
|
+
|
37
|
+
def each(&block)
|
38
|
+
self.keys.each { |k| yield [k, self[k]] }
|
39
|
+
self
|
40
|
+
end
|
41
|
+
|
42
|
+
def inspect
|
43
|
+
ary = []
|
44
|
+
each { |k, v| ary << "#{ k.inspect }=>#{ v.inspect }" }
|
45
|
+
"{#{ ary.join(', ') }}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/spec/base_spec.rb
ADDED
@@ -0,0 +1,220 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../lib/tiny_css'
|
2
|
+
include TinyCss
|
3
|
+
|
4
|
+
describe Base, '削除に関して' do
|
5
|
+
before do
|
6
|
+
@css = TinyCss.new.read_string('h1, p { color: red; background: blue; }')
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'セレクタを削除したら、style.keys にそのセレクタが含まれていないこと' do
|
10
|
+
@css.style.keys.should include('h1')
|
11
|
+
@css.style.delete 'h1'
|
12
|
+
@css.style.keys.should_not include('h1')
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'セレクタを削除したら、write_string の結果にもそのセレクタが含まれていないこと' do
|
16
|
+
@css.style.delete 'h1'
|
17
|
+
@css.write_string.should == "p {\n\tbackground: blue;\n\tcolor: red;\n}\n"
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'プロパティを削除したら、style[セレクタ].keys にそのプロパティが' +
|
21
|
+
'含まれていないこと' do
|
22
|
+
@css.style['h1'].keys.should include('color')
|
23
|
+
@css.style['h1'].delete 'color'
|
24
|
+
@css.style['h1'].keys.should_not include('color')
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'プロパティを削除したら、write_string の結果にも反映されていること' do
|
28
|
+
@css.style['h1'].delete 'color'
|
29
|
+
@css.write_string.should == "p {\n\tbackground: blue;\n\tcolor: red;\n}\n" +
|
30
|
+
"h1 {\n\tbackground: blue;\n}\n"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe Base, 'CSS 文字列を指定してパースするとき' do
|
35
|
+
before do
|
36
|
+
@css1 = TinyCss.new.read_string('h3 { color: red; }')
|
37
|
+
@css2 = TinyCss.new.read_string('h1, p { color: red }')
|
38
|
+
@css3 = TinyCss.new.read_string("h3 { color: red; \n /*z-index: 4;*/\n" +
|
39
|
+
"background: blue }")
|
40
|
+
@css4 = TinyCss.new.read_string('h3, div .foo { color: red; ' +
|
41
|
+
'background: blue },div{color:red;}')
|
42
|
+
@selectors2 = ['h1', 'p']
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'は、self を返すこと' do
|
46
|
+
@css1.should be_instance_of(Base)
|
47
|
+
@css2.should be_instance_of(Base)
|
48
|
+
@css3.should be_instance_of(Base)
|
49
|
+
@css4.should be_instance_of(Base)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'は、style[セレクタ][プロパティ] で値が取り出せること' do
|
53
|
+
@css1.style['h3']['color'].should == 'red'
|
54
|
+
@css2.style['h1']['color'].should == 'red'
|
55
|
+
@css2.style['p']['color'].should == 'red'
|
56
|
+
@css3.style['h3']['color'].should == 'red'
|
57
|
+
@css3.style['h3']['background'].should == 'blue'
|
58
|
+
@css4.style['h3']['color'].should == 'red'
|
59
|
+
@css4.style['h3']['background'].should == 'blue'
|
60
|
+
@css4.style['div']['color'].should == 'red'
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'は、セレクタ文字列中のホワイトスペースが半角 1 スペースに変換されていること' do
|
64
|
+
@css4.style['div .foo']['color'].should == 'red'
|
65
|
+
@css4.style['div .foo']['background'].should == 'blue'
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'は、コメント内のスタイルが反映されていないこと' do
|
69
|
+
@css3.style['h3']['z-index'].should_not == '4'
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'は、style.keys で順番にセレクタが得られること' do
|
73
|
+
@css2.style.keys.should == @selectors2
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'は、style[セレクタ].keys で順番にプロパティが得られること' do
|
77
|
+
@css4.style['div .foo'].keys.should == ['color', 'background']
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe Base, '} で終わらない CSS 文字列を指定してパースするとき' do
|
82
|
+
before do
|
83
|
+
@proc1 = Proc.new { TinyCss.new.read_string('h3 { color: red;') }
|
84
|
+
@proc2 = Proc.new {
|
85
|
+
TinyCss.new.read_string('h1, p { color: red }, f')
|
86
|
+
}
|
87
|
+
@proc3 = Proc.new {
|
88
|
+
TinyCss.new.read_string('h1, p { color: red }, div { margin: 0')
|
89
|
+
}
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'は、例外 TinyCss::Error が発生すること' do
|
93
|
+
msg = "Invalid or unexpected style data 'h3 { color: red;'"
|
94
|
+
@proc1.should raise_error(Error, msg)
|
95
|
+
msg = "Invalid or unexpected style data ', f'"
|
96
|
+
@proc2.should raise_error(Error, msg)
|
97
|
+
msg = "Invalid or unexpected style data ', div { margin: 0'"
|
98
|
+
@proc3.should raise_error(Error, msg)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe Base, 'セレクタの後 { で始まらない CSS 文字列を指定してパースするとき' do
|
103
|
+
before do
|
104
|
+
@proc1 = Proc.new { TinyCss.new.read_string('h3 color: red; }') }
|
105
|
+
@proc2 = Proc.new {
|
106
|
+
TinyCss.new.read_string('h1, p { color: red }, div }')
|
107
|
+
}
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'は、例外 TinyCss::Error が発生すること' do
|
111
|
+
msg = "Invalid or unexpected style data 'h3 color: red; }'"
|
112
|
+
@proc1.should raise_error(Error, msg)
|
113
|
+
|
114
|
+
msg = "Invalid or unexpected style data ', div }'"
|
115
|
+
@proc2.should raise_error(Error, msg)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe Base, 'プロパティと値が : で区切られていないとき' do
|
120
|
+
before do
|
121
|
+
@proc = Proc.new { TinyCss.new.read_string('h3 { color }') }
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'は、例外 TinyCss::Error が発生すること' do
|
125
|
+
msg = "unexpected property ' color ' in style 'h3'"
|
126
|
+
@proc.should raise_error(Error, msg)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
describe Base do
|
131
|
+
before do
|
132
|
+
@css = TinyCss.new.read(File.join(File.dirname(__FILE__), 'style.css'))
|
133
|
+
@selectors = ['div', 'h1', 'h2', 'div#test', 'div.foo ul', 'p#hoge',
|
134
|
+
'.bar div']
|
135
|
+
end
|
136
|
+
|
137
|
+
describe Base, 'CSS ファイルを指定してパースするとき' do
|
138
|
+
it 'は、self を返すこと' do
|
139
|
+
@css.should be_instance_of(Base)
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'は、style[セレクタ][プロパティ] で値が取り出せること' do
|
143
|
+
@css.style['div']['padding'].should == '0'
|
144
|
+
@css.style['div']['margin'].should == '0'
|
145
|
+
@css.style['h1']['padding'].should == '0'
|
146
|
+
@css.style['h1']['margin'].should == '0'
|
147
|
+
@css.style['h2']['padding'].should == '0'
|
148
|
+
@css.style['h2']['margin'].should == '0'
|
149
|
+
@css.style['div#test']['border'].should == '1px solid black'
|
150
|
+
@css.style['div#test']['padding'].should == '1px'
|
151
|
+
@css.style['div#test']['padding-left'].should == '3px'
|
152
|
+
@css.style['p#hoge']['color'].should == 'red'
|
153
|
+
@css.style['p#hoge']['background'].should == '#ff0000'
|
154
|
+
end
|
155
|
+
|
156
|
+
it 'は、セレクタ文字列中のホワイトスペースが半角 1 スペースに変換されていること' do
|
157
|
+
@css.style['div.foo ul']['list-style-type'].should == 'circle'
|
158
|
+
@css.style['div.foo ul']['text-decoration'].should == 'underline'
|
159
|
+
end
|
160
|
+
|
161
|
+
it 'は、コメント内のスタイルが反映されていないこと' do
|
162
|
+
@css.style['p#hoge']['font-size'].should_not == 'big'
|
163
|
+
end
|
164
|
+
|
165
|
+
it 'は、style.keys で順番にセレクタが得られること' do
|
166
|
+
@css.style.keys.should == @selectors
|
167
|
+
end
|
168
|
+
|
169
|
+
it 'は、style[セレクタ].keys で順番にプロパティが得られること' do
|
170
|
+
@css.style['.bar div'].keys.should == ['color', 'z-index', 'background']
|
171
|
+
end
|
172
|
+
|
173
|
+
it 'は、style.each で順番にセレクタとスタイルが得られること' do
|
174
|
+
selectors, styles = [], []
|
175
|
+
@css.style.each do |selector, style|
|
176
|
+
selectors << selector
|
177
|
+
styles << style
|
178
|
+
end
|
179
|
+
selectors.should == @selectors
|
180
|
+
|
181
|
+
properties, values = [], []
|
182
|
+
styles[3].each do |property, value|
|
183
|
+
properties << property
|
184
|
+
values << value
|
185
|
+
end
|
186
|
+
properties.should == ['border', 'padding', 'padding-left']
|
187
|
+
values.should == ['1px solid black', '1px', '3px']
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
describe Base, 'CSS 文字列を取得するとき' do
|
192
|
+
before do
|
193
|
+
@css.style['p#added']['background'] = 'yellow'
|
194
|
+
@result = @css.write_string
|
195
|
+
end
|
196
|
+
|
197
|
+
it 'は、ソート(セレクタは逆ソート)されて整形されていること' do
|
198
|
+
@result.should == "p#hoge {\n\tbackground: #ff0000;\n\tcolor: red;\n" +
|
199
|
+
"\tz-index: 3;\n}\np#added {\n\tbackground: yellow;\n}\nh2 {\n\t" +
|
200
|
+
"margin: 0;\n\tpadding: 0;\n}\nh1 {\n\tmargin: 0;\n\tpadding: 0;\n" +
|
201
|
+
"}\ndiv.foo ul {\n\tlist-style-type: circle;\n\ttext-decoration: " +
|
202
|
+
"underline;\n}\ndiv#test {\n\tborder: 1px solid black;\n\tpadding: " +
|
203
|
+
"1px;\n\tpadding-left: 3px;\n}\ndiv {\n\tmargin: 0;\n\tpadding: 0;\n" +
|
204
|
+
"}\n.bar div {\n\tbackground: #ff0000;\n\tcolor: red;\n\tz-index: " +
|
205
|
+
"3;\n}\n"
|
206
|
+
end
|
207
|
+
|
208
|
+
it 'は、write_string で 第 1 引数に false を指定するとソートされないこと' do
|
209
|
+
result = @css.write_string(false)
|
210
|
+
result.should == "div {\n\tmargin: 0;\n\tpadding: 0;\n}\nh1 {\n\t" +
|
211
|
+
"margin: 0;\n\tpadding: 0;\n}\nh2 {\n\tmargin: 0;\n\tpadding: 0;\n}" +
|
212
|
+
"\ndiv#test {\n\tborder: 1px solid black;\n\tpadding: 1px;\n\t" +
|
213
|
+
"padding-left: 3px;\n}\ndiv.foo ul {\n\tlist-style-type: circle;\n" +
|
214
|
+
"\ttext-decoration: underline;\n}\np#hoge {\n\tbackground: #ff0000;\n" +
|
215
|
+
"\tcolor: red;\n\tz-index: 3;\n}\n.bar div {\n\tbackground: #ff0000;" +
|
216
|
+
"\n\tcolor: red;\n\tz-index: 3;\n}\np#added {\n\tbackground: yellow;" +
|
217
|
+
"\n}\n"
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
@@ -0,0 +1,187 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../lib/tiny_css'
|
2
|
+
include TinyCss
|
3
|
+
|
4
|
+
describe OrderedHash, '未定義のキーが指定されたとき' do
|
5
|
+
before do
|
6
|
+
@oh = OrderedHash.new
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'は、OrderedHash のインスタンスが得られること' do
|
10
|
+
@oh[:a].should be_instance_of(OrderedHash)
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'は、keys に そのキーが文字列で追加されること' do
|
15
|
+
@oh[:a][:b] = 3
|
16
|
+
@oh.keys.last.should == 'a'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe OrderedHash, '代入・参照操作について' do
|
21
|
+
before do
|
22
|
+
@oh1, @oh2 = OrderedHash.new, OrderedHash.new
|
23
|
+
@oh1[:a] = 3
|
24
|
+
@oh2['b'] = 4
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'は、キーから値が取り出せること' do
|
28
|
+
@oh1[:a].should == 3
|
29
|
+
@oh2['b'].should == 4
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'は、キーがシンボルでも文字列でも同じ値を指すこと' do
|
33
|
+
@oh1[:a.to_s].should == @oh1[:a]
|
34
|
+
@oh2['b'.to_sym].should == @oh2['b']
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'は、キーが文字列に変換されていること' do
|
38
|
+
@oh1.keys.should_not include(:a)
|
39
|
+
@oh1.keys.should include('a')
|
40
|
+
@oh2.keys.should_not include(:b)
|
41
|
+
@oh2.keys.should include('b')
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'は、きちんと上書き処理がされること' do
|
45
|
+
@oh1['a'] = 4
|
46
|
+
@oh1['a'].should == 4
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe OrderedHash, '#dup について' do
|
51
|
+
before do
|
52
|
+
@oh = OrderedHash.new
|
53
|
+
@dup = @oh.dup
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'は、self と 戻り値 の object_id が相違なること' do
|
57
|
+
@oh.object_id.should_not == @dup.object_id
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'は、self.keys と 戻り値.keys の object_id が相違なること' do
|
61
|
+
@oh.keys.object_id.should_not == @dup.keys.object_id
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe OrderedHash, '#delete について' do
|
66
|
+
before(:each) do
|
67
|
+
@oh = OrderedHash.new
|
68
|
+
@oh['foo'] = 3
|
69
|
+
end
|
70
|
+
|
71
|
+
it '存在するキーに対する関連を取り除いた場合は、取り除かれた値を返すこと' do
|
72
|
+
result = @oh.delete('foo')
|
73
|
+
result.should == 3
|
74
|
+
end
|
75
|
+
|
76
|
+
it '存在するキーに対する関連を取り除いた場合は、取り除かれた値を返すこと' +
|
77
|
+
'(シンボルでキーを指定した場合も)' do
|
78
|
+
result = @oh.delete(:foo)
|
79
|
+
result.should == 3
|
80
|
+
end
|
81
|
+
|
82
|
+
it '存在するキーに対する関連を取り除いた場合は、keys からそのキーがなくなっていること' do
|
83
|
+
@oh.keys.should include('foo')
|
84
|
+
@oh.delete 'foo'
|
85
|
+
@oh.keys.should_not include('foo')
|
86
|
+
end
|
87
|
+
|
88
|
+
it '存在するキーに対する関連を取り除いた場合は、keys からそのキーがなくなっていること' +
|
89
|
+
'(シンボルでキーを指定した場合も)' do
|
90
|
+
@oh.keys.should include('foo')
|
91
|
+
@oh.delete :foo
|
92
|
+
@oh.keys.should_not include('foo')
|
93
|
+
end
|
94
|
+
|
95
|
+
it '存在しないキーを指定された場合は、nil が返ること' do
|
96
|
+
result = @oh.delete('none')
|
97
|
+
result.should == nil
|
98
|
+
|
99
|
+
result = @oh.delete(:none)
|
100
|
+
result.should be_nil
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'ブロックが与えられたときは、key にマッチするものがなかった時に評価して、' +
|
104
|
+
'その結果を返すこと' do
|
105
|
+
result = @oh.delete('foo') { |key| key + 'no' }
|
106
|
+
result.should == 3
|
107
|
+
|
108
|
+
result = @oh.delete('none') { |key| key + 'no' }
|
109
|
+
result.should == 'noneno'
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'ブロックが与えられて、シンボルの key が与えられたときは' +
|
113
|
+
'key にマッチするものがなかった時にブロックを評価して、その結果を返すこと ' +
|
114
|
+
'(ブロックには文字列のキーが渡される)' do
|
115
|
+
result = @oh.delete(:foo) { |key| key + 'no' }
|
116
|
+
result.should == 3
|
117
|
+
|
118
|
+
result = @oh.delete(:none) { |key| key + 'no' }
|
119
|
+
result.should == 'noneno'
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
describe OrderedHash, '#each について' do
|
124
|
+
before do
|
125
|
+
@oh1, @oh2 = OrderedHash.new, OrderedHash.new
|
126
|
+
@keys1, @keys2 = [], []
|
127
|
+
@values1, @values2 = [], []
|
128
|
+
|
129
|
+
@oh1['1'] = 'one'
|
130
|
+
@oh1['2'] = 'two'
|
131
|
+
@oh1['3'] = 'three'
|
132
|
+
@oh2['2'] = 'two'
|
133
|
+
@oh2['1'] = 'one'
|
134
|
+
@oh2['3'] = 'three'
|
135
|
+
|
136
|
+
@result1 = @oh1.each { |k, v|
|
137
|
+
@keys1 << k
|
138
|
+
@values1 << v
|
139
|
+
}
|
140
|
+
|
141
|
+
@result2 = @oh2.each { |k, v|
|
142
|
+
@keys2 << k
|
143
|
+
@values2 << v
|
144
|
+
}
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'は、代入順に要素が処理されること' do
|
148
|
+
@keys1.should == ['1', '2', '3']
|
149
|
+
@keys2.should == ['2', '1', '3']
|
150
|
+
@values1.should == ['one', 'two', 'three']
|
151
|
+
@values2.should == ['two', 'one', 'three']
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'は、self を返すこと' do
|
155
|
+
@result1.should == @oh1
|
156
|
+
@result2.should == @oh2
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
describe OrderedHash, '#inspect について' do
|
161
|
+
before do
|
162
|
+
oh1, oh2 = OrderedHash.new, OrderedHash.new
|
163
|
+
oh1['1'] = 'one'
|
164
|
+
oh1['2'] = 'two'
|
165
|
+
oh1['3'] = 'three'
|
166
|
+
oh2['2'] = 'two'
|
167
|
+
oh2['1'] = 'one'
|
168
|
+
oh2['3'] = 'three'
|
169
|
+
@inspect1, @inspect2 = oh1.inspect, oh2.inspect
|
170
|
+
end
|
171
|
+
|
172
|
+
it 'は、{#{k.inspect}=>#{v.inspect}, ...} を返すこと' do
|
173
|
+
@inspect1.should ==
|
174
|
+
'{' +
|
175
|
+
"#{ '1'.inspect }=>#{ 'one'.inspect }, " +
|
176
|
+
"#{ '2'.inspect }=>#{ 'two'.inspect }, " +
|
177
|
+
"#{ '3'.inspect }=>#{ 'three'.inspect }" +
|
178
|
+
'}'
|
179
|
+
@inspect2.should ==
|
180
|
+
'{' +
|
181
|
+
"#{ '2'.inspect }=>#{ 'two'.inspect }, " +
|
182
|
+
"#{ '1'.inspect }=>#{ 'one'.inspect }, " +
|
183
|
+
"#{ '3'.inspect }=>#{ 'three'.inspect }" +
|
184
|
+
'}'
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
data/spec/spec.opts
ADDED
data/spec/style.css
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
div, h1, h2 {
|
2
|
+
padding: 0; margin: 0;
|
3
|
+
}
|
4
|
+
div#test {
|
5
|
+
border: 1px solid black;
|
6
|
+
padding: 1px;
|
7
|
+
padding-left: 3px;
|
8
|
+
}
|
9
|
+
div.foo ul {
|
10
|
+
list-style-type: circle;
|
11
|
+
text-decoration: underline;
|
12
|
+
}
|
13
|
+
p#hoge, .bar div
|
14
|
+
{
|
15
|
+
color: red;
|
16
|
+
/* font-size: big; */
|
17
|
+
z-index: 3 ;
|
18
|
+
background: #ff0000;
|
19
|
+
}
|
data/tiny_css.gemspec
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "tiny_css"
|
3
|
+
s.version = "0.0.2"
|
4
|
+
s.date = "2008-07-10"
|
5
|
+
s.summary = ""
|
6
|
+
s.email = "info@milk1000.cc"
|
7
|
+
s.homepage = "http://github.com/milk1000cc/tiny_css"
|
8
|
+
s.description = ""
|
9
|
+
s.has_rdoc = false
|
10
|
+
s.authors = ["milk1000cc"]
|
11
|
+
s.files = ["README", "lib/tiny_css.rb", "lib/tiny_css/base.rb", "lib/tiny_css/ordered_hash.rb", "spec/base_spec.rb", "spec/ordered_hash_spec.rb", "spec/spec.opts", "spec/style.css", "tiny_css.gemspec"]
|
12
|
+
end
|
metadata
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tiny_css
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 2
|
10
|
+
version: 0.0.2
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- milk1000cc
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2008-07-10 00:00:00 +09:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: ""
|
23
|
+
email: info@milk1000.cc
|
24
|
+
executables: []
|
25
|
+
|
26
|
+
extensions: []
|
27
|
+
|
28
|
+
extra_rdoc_files: []
|
29
|
+
|
30
|
+
files:
|
31
|
+
- README
|
32
|
+
- lib/tiny_css.rb
|
33
|
+
- lib/tiny_css/base.rb
|
34
|
+
- lib/tiny_css/ordered_hash.rb
|
35
|
+
- spec/base_spec.rb
|
36
|
+
- spec/ordered_hash_spec.rb
|
37
|
+
- spec/spec.opts
|
38
|
+
- spec/style.css
|
39
|
+
- tiny_css.gemspec
|
40
|
+
has_rdoc: true
|
41
|
+
homepage: http://github.com/milk1000cc/tiny_css
|
42
|
+
licenses: []
|
43
|
+
|
44
|
+
post_install_message:
|
45
|
+
rdoc_options: []
|
46
|
+
|
47
|
+
require_paths:
|
48
|
+
- lib
|
49
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
hash: 3
|
55
|
+
segments:
|
56
|
+
- 0
|
57
|
+
version: "0"
|
58
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
59
|
+
none: false
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
hash: 3
|
64
|
+
segments:
|
65
|
+
- 0
|
66
|
+
version: "0"
|
67
|
+
requirements: []
|
68
|
+
|
69
|
+
rubyforge_project:
|
70
|
+
rubygems_version: 1.3.7
|
71
|
+
signing_key:
|
72
|
+
specification_version: 3
|
73
|
+
summary: ""
|
74
|
+
test_files: []
|
75
|
+
|