style_train 0.2.4 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/lib/style_train/sheet.rb +43 -42
- data/lib/style_train/style.rb +84 -0
- data/lib/style_train.rb +1 -0
- data/{utils → research}/alexch_color_gist/color.rb +0 -0
- data/{utils → research}/alexch_color_gist/color_test.rb +0 -0
- data/research/contexting.rb +34 -0
- data/{utils → research}/overview.txt +0 -0
- data/{utils → research}/stylesheet.txt +0 -0
- data/spec/integration.css +89 -0
- data/spec/integration_spec.rb +66 -0
- data/spec/sheet_spec.rb +162 -72
- data/spec/style_spec.rb +139 -0
- data/style_train.gemspec +14 -7
- metadata +16 -9
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
data/lib/style_train/sheet.rb
CHANGED
@@ -1,20 +1,29 @@
|
|
1
1
|
module StyleTrain
|
2
2
|
class Sheet
|
3
|
-
attr_accessor :output, :
|
3
|
+
attr_accessor :output, :level, :contexts
|
4
4
|
|
5
5
|
def initialize(opts={})
|
6
|
-
self.output =
|
7
|
-
self.
|
6
|
+
self.output = []
|
7
|
+
self.contexts = []
|
8
|
+
self.level = 0
|
8
9
|
end
|
9
10
|
|
10
|
-
def render render_method = :content
|
11
|
-
self.output = header
|
11
|
+
def render render_method = :content, opts={}
|
12
|
+
self.output = [header]
|
12
13
|
if render_method == :content
|
13
14
|
content
|
14
15
|
else
|
15
16
|
send render_method
|
16
17
|
end
|
17
|
-
|
18
|
+
if opts[:type]
|
19
|
+
render_type = opts[:type]
|
20
|
+
joiner = "\n"
|
21
|
+
else
|
22
|
+
render_type = :full
|
23
|
+
joiner = "\n\n"
|
24
|
+
end
|
25
|
+
|
26
|
+
output.map{|s| s.is_a?(String) ? s : s.render( render_type ) }.join(joiner)
|
18
27
|
end
|
19
28
|
|
20
29
|
def header
|
@@ -25,52 +34,44 @@ module StyleTrain
|
|
25
34
|
CSS
|
26
35
|
end
|
27
36
|
|
28
|
-
def style(
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
else
|
33
|
-
self.output << ".#{selector}"
|
34
|
-
end
|
35
|
-
self.output << " {"
|
37
|
+
def style(*selectors)
|
38
|
+
s = Style.new(:selectors => selectors, :level => level, :context => context)
|
39
|
+
self.output << s
|
40
|
+
self.contexts.unshift( s )
|
36
41
|
if block_given?
|
37
|
-
self.
|
38
|
-
yield
|
39
|
-
self.
|
42
|
+
self.level += 1
|
43
|
+
yield
|
44
|
+
self.level -= 1
|
40
45
|
end
|
41
|
-
self.
|
42
|
-
end
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
:map, :meta, :noframes, :noscript, :object, :ol, :optgroup,
|
52
|
-
:option, :p, :param, :pre, :q, :s, :samp, :script, :select,
|
53
|
-
:small, :span, :strike, :strong, :sub, :sup, :table,
|
54
|
-
:tbody, :td, :textarea, :tfoot, :th, :thead, :title,
|
55
|
-
:tr, :tt, :u, :ul, :var
|
56
|
-
]
|
46
|
+
self.contexts.shift
|
47
|
+
end
|
48
|
+
|
49
|
+
def context
|
50
|
+
contexts.first
|
51
|
+
end
|
52
|
+
|
53
|
+
alias :c :style
|
54
|
+
|
55
|
+
TAGS = StyleTrain::Style::TAGS
|
57
56
|
|
58
57
|
TAGS.each do |tag|
|
59
58
|
class_eval <<-RUBY
|
60
|
-
def #{tag} &block
|
61
|
-
|
59
|
+
def #{tag}(*selectors, &block)
|
60
|
+
if selectors.size > 0
|
61
|
+
selectors = selectors.map{ |e| '#{tag}' + '.' + e.to_s }
|
62
|
+
style( *selectors, &block )
|
63
|
+
else
|
64
|
+
style( '#{tag}', &block )
|
65
|
+
end
|
62
66
|
end
|
63
67
|
RUBY
|
64
68
|
end
|
65
69
|
|
66
|
-
def indent
|
67
|
-
" " * indent_level
|
68
|
-
end
|
69
70
|
|
70
71
|
def property( label, value )
|
71
72
|
value = value.join(' ') if value.is_a?(Array)
|
72
|
-
str = "
|
73
|
-
self.
|
73
|
+
str = "#{label}: #{value};"
|
74
|
+
self.context.properties << str
|
74
75
|
str
|
75
76
|
end
|
76
77
|
|
@@ -366,8 +367,8 @@ CSS
|
|
366
367
|
|
367
368
|
def export opts={}
|
368
369
|
name = file_name(opts[:file_name])
|
369
|
-
render opts[:render_method] || :content
|
370
|
-
File.open("#{StyleTrain.dir}/#{file_name}.css", 'w'){ |f| f.write(
|
370
|
+
str = render (opts[:render_method] || :content), opts
|
371
|
+
File.open("#{StyleTrain.dir}/#{file_name}.css", 'w'){ |f| f.write(str) }
|
371
372
|
end
|
372
373
|
|
373
374
|
def file_name name=nil
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module StyleTrain
|
2
|
+
class Style
|
3
|
+
attr_accessor :selectors, :level, :properties
|
4
|
+
|
5
|
+
def initialize(opts)
|
6
|
+
self.level = opts[:level].to_i
|
7
|
+
self.selectors = []
|
8
|
+
self.properties = []
|
9
|
+
set_selectors opts[:selectors], opts[:context] && opts[:context].selectors
|
10
|
+
end
|
11
|
+
|
12
|
+
def set_selectors values, contexts
|
13
|
+
if contexts
|
14
|
+
contexts.each do |context|
|
15
|
+
values.each do |value|
|
16
|
+
self.selectors << "#{context} #{make_selector(value)}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
else
|
20
|
+
values.each do |value|
|
21
|
+
self.selectors << make_selector(value)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
TAGS = [
|
27
|
+
:a, :abbr, :acronym, :address, :area, :b, :base, :bdo,
|
28
|
+
:big, :blockquote, :body, :br, :button, :caption, :center,
|
29
|
+
:cite, :code, :col, :colgroup, :dd, :del, :dfn, :div,
|
30
|
+
:dl, :dt, :em, :embed, :fieldset, :form, :frame, :frameset,
|
31
|
+
:h1, :h2, :h3, :h4, :h5, :h6, :head, :hr, :html, :i, :iframe,
|
32
|
+
:img, :input, :ins, :kbd, :label, :legend, :li, :link,
|
33
|
+
:map, :meta, :noframes, :noscript, :object, :ol, :optgroup,
|
34
|
+
:option, :p, :param, :pre, :q, :s, :samp, :script, :select,
|
35
|
+
:small, :span, :strike, :strong, :sub, :sup, :table,
|
36
|
+
:tbody, :td, :textarea, :tfoot, :th, :thead, :title,
|
37
|
+
:tr, :tt, :u, :ul, :var
|
38
|
+
]
|
39
|
+
|
40
|
+
def make_selector(value)
|
41
|
+
value.is_a?(String) || TAGS.include?(value) ? "#{value}" : ".#{value}"
|
42
|
+
end
|
43
|
+
|
44
|
+
INDENT = ' '
|
45
|
+
|
46
|
+
def render(type=:full)
|
47
|
+
type == :full ? render_full : render_linear
|
48
|
+
end
|
49
|
+
|
50
|
+
alias :to_s :render
|
51
|
+
|
52
|
+
def render_full
|
53
|
+
str = ""
|
54
|
+
|
55
|
+
# selectors
|
56
|
+
array = selectors.dup
|
57
|
+
last_selector = array.pop
|
58
|
+
array.each do |selector|
|
59
|
+
str << "#{indent}#{selector},\n"
|
60
|
+
end
|
61
|
+
str << "#{indent}#{last_selector} {"
|
62
|
+
|
63
|
+
# properties
|
64
|
+
properties.each do |property|
|
65
|
+
str << "\n#{indent(1)}#{property}"
|
66
|
+
end
|
67
|
+
str << "\n#{indent}}"
|
68
|
+
|
69
|
+
str
|
70
|
+
end
|
71
|
+
|
72
|
+
def render_linear
|
73
|
+
str = "#{indent}"
|
74
|
+
str << selectors.join(', ')
|
75
|
+
str << " { "
|
76
|
+
str << properties.join(' ')
|
77
|
+
str << " }"
|
78
|
+
end
|
79
|
+
|
80
|
+
def indent(plus=0)
|
81
|
+
INDENT * (level+plus)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
data/lib/style_train.rb
CHANGED
File without changes
|
File without changes
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class Contexting
|
2
|
+
attr_accessor :context, :last_context
|
3
|
+
|
4
|
+
def style(*selectors)
|
5
|
+
self.last_context = context
|
6
|
+
self.context = Style.new(selectors)
|
7
|
+
yield if block_given?
|
8
|
+
self.context = last_context
|
9
|
+
end
|
10
|
+
|
11
|
+
def render
|
12
|
+
style(:outer) {
|
13
|
+
puts context
|
14
|
+
style(:inner){
|
15
|
+
puts context
|
16
|
+
}
|
17
|
+
puts context
|
18
|
+
}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class Style
|
23
|
+
attr_accessor :selectors
|
24
|
+
|
25
|
+
def initialize(selectors)
|
26
|
+
self.selectors = selectors
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_s
|
30
|
+
"<Style selectors=#{selectors.inspect}>"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
Contexting.new.render
|
File without changes
|
File without changes
|
@@ -0,0 +1,89 @@
|
|
1
|
+
/*
|
2
|
+
Generated by StlyeTrain CSS generator via the class Cohuman
|
3
|
+
*/
|
4
|
+
body {
|
5
|
+
font-family: Verdana Sans;
|
6
|
+
font-size: 13px;
|
7
|
+
line-height: 1.5;
|
8
|
+
}
|
9
|
+
|
10
|
+
h1 {
|
11
|
+
font-size: 25px;
|
12
|
+
}
|
13
|
+
|
14
|
+
h2 {
|
15
|
+
font-size: 23px;
|
16
|
+
}
|
17
|
+
|
18
|
+
h3 {
|
19
|
+
font-size: 18px;
|
20
|
+
}
|
21
|
+
|
22
|
+
h3 {
|
23
|
+
margin-left: 0;
|
24
|
+
margin-top: 0;
|
25
|
+
margin-bottom: 0;
|
26
|
+
margin-right: 0;
|
27
|
+
}
|
28
|
+
|
29
|
+
h4 {
|
30
|
+
font-size: 16px;
|
31
|
+
}
|
32
|
+
|
33
|
+
h5 {
|
34
|
+
font-size: 11px;
|
35
|
+
}
|
36
|
+
|
37
|
+
h6 {
|
38
|
+
font-size: 10px;
|
39
|
+
}
|
40
|
+
|
41
|
+
hr {
|
42
|
+
border: none;
|
43
|
+
height: 1px;
|
44
|
+
color: gray;
|
45
|
+
background-color: gray;
|
46
|
+
}
|
47
|
+
|
48
|
+
.create_button {
|
49
|
+
font-weight: bold;
|
50
|
+
font-size: 8em;
|
51
|
+
border: 1px solid black;
|
52
|
+
color: gray;
|
53
|
+
cursor: pointer;
|
54
|
+
padding: 0 0.5em;
|
55
|
+
}
|
56
|
+
|
57
|
+
.activity_button {
|
58
|
+
display: inline-block;
|
59
|
+
position: relative;
|
60
|
+
overflow: visible;
|
61
|
+
padding-left: 0;
|
62
|
+
padding-top: 0;
|
63
|
+
padding-bottom: 0;
|
64
|
+
padding-right: 0;
|
65
|
+
font-weight: bold;
|
66
|
+
font-size: 0.8em;
|
67
|
+
cursor: pointer;
|
68
|
+
color: gray;
|
69
|
+
border: 1px solid black;
|
70
|
+
}
|
71
|
+
|
72
|
+
.user_info {
|
73
|
+
padding: 10px 10px 0px 10px;
|
74
|
+
width: 500px;
|
75
|
+
overflow-x: hidden;
|
76
|
+
}
|
77
|
+
|
78
|
+
.user_info h1 {
|
79
|
+
margin: -4px 0 -2px 0;
|
80
|
+
font-size: 1.5em;
|
81
|
+
}
|
82
|
+
|
83
|
+
.user_info .my_class {
|
84
|
+
padding: 2em;
|
85
|
+
}
|
86
|
+
|
87
|
+
.user_info < p {
|
88
|
+
padding: 1em;
|
89
|
+
}
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
class Cohuman < StyleTrain::Sheet
|
4
|
+
def content
|
5
|
+
body {
|
6
|
+
font :size => 13.px, :family => "Verdana Sans", :height => 1.5
|
7
|
+
}
|
8
|
+
|
9
|
+
h1 { font :size => 25.px}
|
10
|
+
h2 { font :size => 23.px}
|
11
|
+
h3 { font :size => 18.px}
|
12
|
+
h3 { margin 0 }
|
13
|
+
h4 { font :size => 16.px}
|
14
|
+
h5 { font :size => 11.px}
|
15
|
+
h6 { font :size => 10.px}
|
16
|
+
|
17
|
+
hr {
|
18
|
+
border :none
|
19
|
+
height 1.px
|
20
|
+
color :gray
|
21
|
+
background :color => :gray
|
22
|
+
}
|
23
|
+
|
24
|
+
c(:create_button) {
|
25
|
+
font :weight => :bold, :size => 8.em
|
26
|
+
border :color => :black
|
27
|
+
color :gray
|
28
|
+
cursor :pointer
|
29
|
+
padding 0, 0.5.em
|
30
|
+
}
|
31
|
+
|
32
|
+
c(:activity_button) {
|
33
|
+
display 'inline-block'
|
34
|
+
position :relative
|
35
|
+
overflow :visible
|
36
|
+
padding 0
|
37
|
+
font :weight => :bold, :size => 0.8.em
|
38
|
+
cursor :pointer
|
39
|
+
color :gray
|
40
|
+
border :color => :black
|
41
|
+
}
|
42
|
+
|
43
|
+
c(:user_info) {
|
44
|
+
padding 10.px, 10.px, 0.px, 10.px
|
45
|
+
width 500.px;
|
46
|
+
overflow :x => :hidden
|
47
|
+
|
48
|
+
h1 {
|
49
|
+
margin -4.px, 0, -2.px, 0
|
50
|
+
font :size => 1.5.em
|
51
|
+
}
|
52
|
+
|
53
|
+
c(:my_class){
|
54
|
+
padding 2.em
|
55
|
+
}
|
56
|
+
|
57
|
+
c('< p'){
|
58
|
+
padding 1.em
|
59
|
+
}
|
60
|
+
}
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
@dir = File.dirname(__FILE__) + "/generated_files"
|
65
|
+
StyleTrain.dir = @dir
|
66
|
+
Cohuman.export
|
data/spec/sheet_spec.rb
CHANGED
@@ -14,6 +14,10 @@ describe Sheet do
|
|
14
14
|
background :color => :white
|
15
15
|
margin [1.em, :auto]
|
16
16
|
}
|
17
|
+
|
18
|
+
style(:foo){
|
19
|
+
color :red
|
20
|
+
}
|
17
21
|
end
|
18
22
|
end
|
19
23
|
|
@@ -28,12 +32,16 @@ describe Sheet do
|
|
28
32
|
@sheet.output.should == 'foo'
|
29
33
|
end
|
30
34
|
|
31
|
-
it 'output gets set to an empty
|
32
|
-
Sheet.new.output.should ==
|
35
|
+
it 'output gets set to an empty array on initialize' do
|
36
|
+
Sheet.new.output.should == []
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should have contexts' do
|
40
|
+
Sheet.new.contexts.should == []
|
33
41
|
end
|
34
42
|
|
35
|
-
it 'should have an
|
36
|
-
Sheet.new.
|
43
|
+
it 'should have an indent level that is initialized to 0' do
|
44
|
+
Sheet.new.level.should == 0
|
37
45
|
end
|
38
46
|
end
|
39
47
|
|
@@ -52,7 +60,7 @@ CSS
|
|
52
60
|
|
53
61
|
it 'resets the output' do
|
54
62
|
@sheet.stub(:header).and_return('HEADER')
|
55
|
-
@sheet.should_receive(:output=).with('HEADER')
|
63
|
+
@sheet.should_receive(:output=).with(['HEADER'])
|
56
64
|
@sheet.render
|
57
65
|
end
|
58
66
|
|
@@ -67,11 +75,18 @@ CSS
|
|
67
75
|
@sheet.render :foo
|
68
76
|
end
|
69
77
|
|
70
|
-
it 'returns the output' do
|
71
|
-
@sheet.output = "bar"
|
78
|
+
it 'returns the output joined by 2 line ends' do
|
79
|
+
@sheet.output = ["bar", "baz"]
|
72
80
|
@sheet.stub(:output=)
|
73
|
-
@sheet.stub(:content)
|
74
|
-
@sheet.render.should == "bar"
|
81
|
+
@sheet.stub(:content)
|
82
|
+
@sheet.render.should == "bar\n\nbaz"
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'joins with one line break when a render type is specified' do
|
86
|
+
@sheet.output = ['bar', 'baz']
|
87
|
+
@sheet.stub!(:output=)
|
88
|
+
@sheet.stub!(:content)
|
89
|
+
@sheet.render(:content, :type => :linear).should == "bar\nbaz"
|
75
90
|
end
|
76
91
|
end
|
77
92
|
|
@@ -80,37 +95,31 @@ CSS
|
|
80
95
|
@sheet = Sheet.new
|
81
96
|
end
|
82
97
|
|
83
|
-
it 'adds an
|
84
|
-
@sheet.output.should ==
|
98
|
+
it 'adds an Style object to the output' do
|
99
|
+
@sheet.output.size.should == 0
|
85
100
|
@sheet.style(:foo)
|
86
|
-
@sheet.output.
|
87
|
-
|
88
|
-
|
89
|
-
it 'renders the right style when passed a string' do
|
90
|
-
@sheet.style('.foo')
|
91
|
-
@sheet.output.should include '.foo'
|
101
|
+
@sheet.output.size.should == 1
|
102
|
+
@sheet.output.first.class.should == StyleTrain::Style
|
92
103
|
end
|
93
104
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
@sheet.output.should_not include '.body'
|
103
|
-
end
|
104
|
-
|
105
|
-
it 'renders {} when not passed a block' do
|
106
|
-
@sheet.style(:body)
|
107
|
-
@sheet.output.should include "body {\n}"
|
108
|
-
end
|
105
|
+
describe 'Style object selector' do
|
106
|
+
it 'is correct when passed a string' do
|
107
|
+
@sheet.style('.foo')
|
108
|
+
style = @sheet.output.first
|
109
|
+
style.should_not be_nil
|
110
|
+
style.selectors.should == ['.foo']
|
111
|
+
style.render.should include '.foo'
|
112
|
+
end
|
109
113
|
|
110
|
-
|
111
|
-
|
114
|
+
it 'is correct when passed a non-tag symbol' do
|
115
|
+
@sheet.style(:bar)
|
116
|
+
@sheet.output.first.selectors.should == ['.bar']
|
117
|
+
end
|
112
118
|
|
113
|
-
|
119
|
+
it 'is correct when passed a tag symbol' do
|
120
|
+
@sheet.style(:body)
|
121
|
+
@sheet.output.first.selectors.should == ['body']
|
122
|
+
end
|
114
123
|
end
|
115
124
|
end
|
116
125
|
|
@@ -126,28 +135,21 @@ CSS
|
|
126
135
|
|
127
136
|
it "should add a style for '#{tag}'" do
|
128
137
|
@sheet.send(tag)
|
129
|
-
@sheet.output.should include "#{tag} {\n}"
|
138
|
+
@sheet.output.first.render.should include "#{tag} {\n}"
|
130
139
|
end
|
131
140
|
end
|
132
|
-
|
133
|
-
it 'should pass the block on to the style method' do
|
134
|
-
str = @sheet.instance_eval <<-RUBY
|
135
|
-
body do
|
136
|
-
margin [2.em, :auto]
|
137
|
-
end
|
138
|
-
RUBY
|
139
|
-
str.should include 'margin: 2em auto'
|
140
|
-
end
|
141
141
|
end
|
142
142
|
|
143
143
|
describe 'properties' do
|
144
144
|
before :all do
|
145
145
|
@sheet = Sheet.new
|
146
|
+
@style = StyleTrain::Style.new(:selectors => ['body'], :level => 2)
|
147
|
+
@sheet.contexts << @style
|
148
|
+
@sheet.output << @style
|
146
149
|
end
|
147
150
|
|
148
151
|
describe '#property' do
|
149
152
|
before :all do
|
150
|
-
@sheet.indent_level = 4
|
151
153
|
@property = @sheet.property('border', '1px solid #ccc' )
|
152
154
|
end
|
153
155
|
|
@@ -155,10 +157,6 @@ CSS
|
|
155
157
|
@property.is_a?(String).should be_true
|
156
158
|
end
|
157
159
|
|
158
|
-
it 'adds a line break and an indent to the front of the string' do
|
159
|
-
@property.match(/^\W{5}/).should_not be_nil
|
160
|
-
end
|
161
|
-
|
162
160
|
it 'includes the property name' do
|
163
161
|
@property.should include 'border'
|
164
162
|
end
|
@@ -172,11 +170,11 @@ CSS
|
|
172
170
|
end
|
173
171
|
|
174
172
|
it 'puts it all together correctly' do
|
175
|
-
@property.should == "
|
173
|
+
@property.should == "border: 1px solid #ccc;"
|
176
174
|
end
|
177
175
|
|
178
|
-
it 'adds the string
|
179
|
-
@sheet.output.should include @property
|
176
|
+
it 'adds the string the style object' do
|
177
|
+
@sheet.output.map{|e| e.render }.join(' ').should include @property
|
180
178
|
end
|
181
179
|
|
182
180
|
it 'converts an array to a space separated string' do
|
@@ -583,6 +581,9 @@ CSS
|
|
583
581
|
describe 'css 3 goodies' do
|
584
582
|
before :all do
|
585
583
|
@sheet = Sheet.new
|
584
|
+
@style = StyleTrain::Style.new(:selectors => ['body'], :level => 2)
|
585
|
+
@sheet.contexts << @style
|
586
|
+
@sheet.output << @style
|
586
587
|
end
|
587
588
|
|
588
589
|
describe '#corners' do
|
@@ -757,8 +758,7 @@ CSS
|
|
757
758
|
describe 'subclassing' do
|
758
759
|
it 'works' do
|
759
760
|
StyleSheet.render.should include(
|
760
|
-
|
761
|
-
body {
|
761
|
+
"body {
|
762
762
|
background-color: #666;
|
763
763
|
font-family: verdana;
|
764
764
|
}
|
@@ -767,7 +767,10 @@ body {
|
|
767
767
|
background-color: white;
|
768
768
|
margin: 1em auto;
|
769
769
|
}
|
770
|
-
|
770
|
+
|
771
|
+
.foo {
|
772
|
+
color: red;
|
773
|
+
}"
|
771
774
|
)
|
772
775
|
end
|
773
776
|
end
|
@@ -801,26 +804,113 @@ CSS
|
|
801
804
|
end
|
802
805
|
end
|
803
806
|
|
804
|
-
describe '
|
805
|
-
|
806
|
-
|
807
|
+
describe 'expanded syntax' do
|
808
|
+
class Expanded < Sheet
|
809
|
+
def content
|
810
|
+
c( :abridged_syntax )
|
811
|
+
|
812
|
+
c( :first, :second, :third ) {
|
813
|
+
background :color => :black
|
814
|
+
}
|
815
|
+
|
816
|
+
div( :next, :again ){
|
817
|
+
color :red
|
818
|
+
}
|
819
|
+
end
|
820
|
+
end
|
807
821
|
|
808
|
-
|
809
|
-
|
810
|
-
|
822
|
+
before :all do
|
823
|
+
@sheet = Expanded.new
|
824
|
+
end
|
811
825
|
|
826
|
+
it 'aliases #style to #s' do
|
827
|
+
@sheet.render.should match /^\.abridged_syntax/
|
828
|
+
end
|
812
829
|
|
813
|
-
|
830
|
+
it 'assigns multiple arguments to comma separated' do
|
831
|
+
@sheet.render.should include <<-CSS
|
832
|
+
.first,
|
833
|
+
.second,
|
834
|
+
.third {
|
835
|
+
background-color: black;
|
836
|
+
}
|
837
|
+
CSS
|
838
|
+
end
|
814
839
|
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
840
|
+
it 'tags take arguments too' do
|
841
|
+
@sheet.render.should include "
|
842
|
+
div.next,
|
843
|
+
div.again {
|
844
|
+
color: red;
|
845
|
+
}"
|
846
|
+
end
|
847
|
+
|
848
|
+
describe 'nesting' do
|
849
|
+
class Nested < Sheet
|
850
|
+
def content
|
851
|
+
style(:form){
|
852
|
+
border :color => '#666'
|
853
|
+
padding 1.em
|
854
|
+
|
855
|
+
# first level nesting
|
856
|
+
style(:label){
|
857
|
+
display :block
|
858
|
+
width 10.em
|
859
|
+
|
860
|
+
# second level nesting
|
861
|
+
style(:input){
|
862
|
+
color '#111'
|
863
|
+
}
|
864
|
+
}
|
865
|
+
|
866
|
+
# property after the nesting
|
867
|
+
color :blue
|
868
|
+
}
|
869
|
+
|
870
|
+
style(:a) {
|
871
|
+
text :decoration => :none
|
872
|
+
}
|
873
|
+
end
|
874
|
+
end
|
875
|
+
|
876
|
+
before :all do
|
877
|
+
@output = Nested.render
|
878
|
+
end
|
820
879
|
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
880
|
+
it 'makes a separate declaration for the first level nested style' do
|
881
|
+
@output.should match /^form \{$/
|
882
|
+
@output.should match /^\W*form label \{$/
|
883
|
+
end
|
884
|
+
|
885
|
+
it 'makes a separate declaration for deeply nested styles' do
|
886
|
+
@output.should match /^\W*form label input \{$/
|
887
|
+
end
|
888
|
+
|
889
|
+
it 'should indent the nested style to the right level' do
|
890
|
+
@output.should match /^\W{2}*form label \{$/
|
891
|
+
@output.should match /^\W{4}*form label \{$/
|
892
|
+
end
|
893
|
+
|
894
|
+
it 'puts property declarations after a nested style in the right place' do
|
895
|
+
@output.should include
|
896
|
+
"
|
897
|
+
form {
|
898
|
+
border: 1px solid #666;
|
899
|
+
padding: 1em;
|
900
|
+
color: blue;
|
901
|
+
}
|
902
|
+
"
|
903
|
+
end
|
904
|
+
|
905
|
+
it 'makes base level declarations correctly after nesting' do
|
906
|
+
@output.should match /^a \{$/
|
907
|
+
end
|
908
|
+
end
|
909
|
+
|
910
|
+
# input[:readonly]{ ... }
|
911
|
+
# input['type=text']{ ... }
|
912
|
+
# how to handle :hover and other psuedo selectors
|
913
|
+
# p.classy < a
|
914
|
+
# #css method on objects that allows instance eval of blocks globally
|
825
915
|
end
|
826
916
|
end
|
data/spec/style_spec.rb
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
Style = StyleTrain::Style unless defined?( Style )
|
4
|
+
|
5
|
+
describe Style do
|
6
|
+
before :all do
|
7
|
+
@selectors = [:p, :classy]
|
8
|
+
@context = Style.new( :selectors =>['a.special'] )
|
9
|
+
end
|
10
|
+
|
11
|
+
describe 'level' do
|
12
|
+
it 'is 0 by default' do
|
13
|
+
Style.new(:selectors => @selectors).level.should == 0
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'can be initialized to something else' do
|
17
|
+
Style.new(:level => 3, :selectors => @selectors).level.should == 3
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe 'selectors' do
|
22
|
+
it 'makes the correct selectors' do
|
23
|
+
Style.new(:selectors => @selectors).selectors.should == ['p', '.classy']
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'takes into account the context' do
|
27
|
+
Style.new(:selectors => @selectors, :context => @context).selectors.should == ['a.special p', 'a.special .classy']
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe 'properties' do
|
32
|
+
it 'is an empty array after initialization' do
|
33
|
+
Style.new(:selectors => @selectors, :properties => ["some: thing;"]).properties.should == []
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'adds property declarations' do
|
37
|
+
style = Style.new(:selectors => @selectors)
|
38
|
+
style.properties << "background-color: red"
|
39
|
+
style.properties.size.should == 1
|
40
|
+
style.properties.first.should == "background-color: red"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe 'rendering' do
|
45
|
+
describe 'types' do
|
46
|
+
before :all do
|
47
|
+
@style = Style.new(:selectors => @selectors)
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'renders full by default' do
|
51
|
+
@style.should_receive(:render_full)
|
52
|
+
@style.render
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'renders minimized if an argument is passed in' do
|
56
|
+
@style.should_receive(:render_linear)
|
57
|
+
@style.render(:something_else)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe 'full' do
|
62
|
+
before :all do
|
63
|
+
style = Style.new(:selectors => @selectors)
|
64
|
+
style.properties << 'background-color: yellow;' << 'color: maroon;'
|
65
|
+
@first_level = style.render
|
66
|
+
|
67
|
+
style = Style.new(:selectors => @selectors, :context => @context, :level => 3)
|
68
|
+
style.properties << 'background-color: yellow;' << 'color: maroon;'
|
69
|
+
@indented = style.render
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'puts the selectors at the correct indent level on a new line' do
|
73
|
+
@first_level.should match(/^p,/)
|
74
|
+
@first_level.should match(/^\.classy/)
|
75
|
+
|
76
|
+
@indented.should match(/^\W{6}a\.special p,/)
|
77
|
+
@indented.should match(/^\W{6}a\.special \.classy/)
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'brackets the properties' do
|
81
|
+
@first_level.should match(/\{$/)
|
82
|
+
@first_level.should match(/^\}/)
|
83
|
+
|
84
|
+
@indented.should match(/\{$/)
|
85
|
+
@indented.should match(/^\W{6}\}/)
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'puts each property on a new line' do
|
89
|
+
@first_level.should match(/^\W*background-color: yellow;$/)
|
90
|
+
@first_level.should match(/^\W*color: maroon;$/)
|
91
|
+
|
92
|
+
@indented.should match(/^\W*background-color: yellow;$/)
|
93
|
+
@indented.should match(/^\W*color: maroon;$/)
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'puts the properties at the correct level' do
|
97
|
+
@first_level.should match(/^\W{2}background/)
|
98
|
+
@first_level.should match(/^\W{2}color/)
|
99
|
+
|
100
|
+
@indented.should match(/^\W{8}background/)
|
101
|
+
@indented.should match(/^\W{8}color/)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe 'linear' do
|
106
|
+
before :all do
|
107
|
+
style = Style.new(:selectors => @selectors)
|
108
|
+
style.properties << 'background-color: yellow;' << 'color: maroon;'
|
109
|
+
@first_level = style.render(:linear)
|
110
|
+
|
111
|
+
style = Style.new(:selectors => @selectors, :context => @context, :level => 3)
|
112
|
+
style.properties << 'background-color: yellow;' << 'color: maroon;'
|
113
|
+
@indented = style.render(:linear)
|
114
|
+
|
115
|
+
@properties = 'background-color: yellow; color: maroon;'
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'puts the selectors at the correct indent level' do
|
119
|
+
@first_level.should match(/\Ap,/)
|
120
|
+
@indented.should match(/\A\W{6}a\.special p,/)
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'separates the selectors with a comma and a space' do
|
124
|
+
@first_level.should match /p, \.classy /
|
125
|
+
@indented.should match /a\.special p, a\.special \.classy /
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'separates the properties with a space' do
|
129
|
+
@first_level.should include @properties
|
130
|
+
@indented.should include @properties
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'puts the bracketed properties on the same line as the selectors' do
|
134
|
+
@first_level.should match /\Ap.*\}\z/
|
135
|
+
@indented.should match /\A\W*a\.special.*\}\z/
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
data/style_train.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{style_train}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.3.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Kane Baccigalupi"]
|
12
|
-
s.date = %q{2011-02-
|
12
|
+
s.date = %q{2011-02-28}
|
13
13
|
s.description = %q{style_train builds CSS using pure Ruby, not a DSL interpreted via Ruby. This allows inheritance, modules, instance level calculations and all the goodness Ruby can offer.}
|
14
14
|
s.email = %q{baccigalupi@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -28,28 +28,33 @@ Gem::Specification.new do |s|
|
|
28
28
|
"lib/style_train/color_types/keyword_color.rb",
|
29
29
|
"lib/style_train/color_types/rgb_color.rb",
|
30
30
|
"lib/style_train/sheet.rb",
|
31
|
+
"lib/style_train/style.rb",
|
31
32
|
"lib/style_train/support/gnash.rb",
|
32
33
|
"lib/style_train/support/numbers.rb",
|
33
34
|
"lib/style_train/theme.rb",
|
34
35
|
"lib/style_train/themed_sheet.rb",
|
36
|
+
"research/alexch_color_gist/color.rb",
|
37
|
+
"research/alexch_color_gist/color_test.rb",
|
38
|
+
"research/contexting.rb",
|
39
|
+
"research/overview.txt",
|
40
|
+
"research/stylesheet.txt",
|
35
41
|
"spec/color/color_spec.rb",
|
36
42
|
"spec/color/color_type_spec.rb",
|
37
43
|
"spec/color/hex_color_spec.rb",
|
38
44
|
"spec/color/keyword_color_spec.rb",
|
39
45
|
"spec/color/rgb_color_spec.rb",
|
40
46
|
"spec/generated_files/.gitkeep",
|
47
|
+
"spec/integration.css",
|
48
|
+
"spec/integration_spec.rb",
|
41
49
|
"spec/numbers_spec.rb",
|
42
50
|
"spec/sheet_spec.rb",
|
43
51
|
"spec/spec.opts",
|
44
52
|
"spec/spec_helper.rb",
|
53
|
+
"spec/style_spec.rb",
|
45
54
|
"spec/style_train_spec.rb",
|
46
55
|
"spec/theme_spec.rb",
|
47
56
|
"spec/themed_sheet_spec.rb",
|
48
|
-
"style_train.gemspec"
|
49
|
-
"utils/alexch_color_gist/color.rb",
|
50
|
-
"utils/alexch_color_gist/color_test.rb",
|
51
|
-
"utils/overview.txt",
|
52
|
-
"utils/stylesheet.txt"
|
57
|
+
"style_train.gemspec"
|
53
58
|
]
|
54
59
|
s.homepage = %q{http://github.com/baccigalupi/style_train}
|
55
60
|
s.require_paths = ["lib"]
|
@@ -61,9 +66,11 @@ Gem::Specification.new do |s|
|
|
61
66
|
"spec/color/hex_color_spec.rb",
|
62
67
|
"spec/color/keyword_color_spec.rb",
|
63
68
|
"spec/color/rgb_color_spec.rb",
|
69
|
+
"spec/integration_spec.rb",
|
64
70
|
"spec/numbers_spec.rb",
|
65
71
|
"spec/sheet_spec.rb",
|
66
72
|
"spec/spec_helper.rb",
|
73
|
+
"spec/style_spec.rb",
|
67
74
|
"spec/style_train_spec.rb",
|
68
75
|
"spec/theme_spec.rb",
|
69
76
|
"spec/themed_sheet_spec.rb"
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: style_train
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 19
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 3
|
9
|
+
- 0
|
10
|
+
version: 0.3.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Kane Baccigalupi
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-02-
|
18
|
+
date: 2011-02-28 00:00:00 -08:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -53,28 +53,33 @@ files:
|
|
53
53
|
- lib/style_train/color_types/keyword_color.rb
|
54
54
|
- lib/style_train/color_types/rgb_color.rb
|
55
55
|
- lib/style_train/sheet.rb
|
56
|
+
- lib/style_train/style.rb
|
56
57
|
- lib/style_train/support/gnash.rb
|
57
58
|
- lib/style_train/support/numbers.rb
|
58
59
|
- lib/style_train/theme.rb
|
59
60
|
- lib/style_train/themed_sheet.rb
|
61
|
+
- research/alexch_color_gist/color.rb
|
62
|
+
- research/alexch_color_gist/color_test.rb
|
63
|
+
- research/contexting.rb
|
64
|
+
- research/overview.txt
|
65
|
+
- research/stylesheet.txt
|
60
66
|
- spec/color/color_spec.rb
|
61
67
|
- spec/color/color_type_spec.rb
|
62
68
|
- spec/color/hex_color_spec.rb
|
63
69
|
- spec/color/keyword_color_spec.rb
|
64
70
|
- spec/color/rgb_color_spec.rb
|
65
71
|
- spec/generated_files/.gitkeep
|
72
|
+
- spec/integration.css
|
73
|
+
- spec/integration_spec.rb
|
66
74
|
- spec/numbers_spec.rb
|
67
75
|
- spec/sheet_spec.rb
|
68
76
|
- spec/spec.opts
|
69
77
|
- spec/spec_helper.rb
|
78
|
+
- spec/style_spec.rb
|
70
79
|
- spec/style_train_spec.rb
|
71
80
|
- spec/theme_spec.rb
|
72
81
|
- spec/themed_sheet_spec.rb
|
73
82
|
- style_train.gemspec
|
74
|
-
- utils/alexch_color_gist/color.rb
|
75
|
-
- utils/alexch_color_gist/color_test.rb
|
76
|
-
- utils/overview.txt
|
77
|
-
- utils/stylesheet.txt
|
78
83
|
has_rdoc: true
|
79
84
|
homepage: http://github.com/baccigalupi/style_train
|
80
85
|
licenses: []
|
@@ -115,9 +120,11 @@ test_files:
|
|
115
120
|
- spec/color/hex_color_spec.rb
|
116
121
|
- spec/color/keyword_color_spec.rb
|
117
122
|
- spec/color/rgb_color_spec.rb
|
123
|
+
- spec/integration_spec.rb
|
118
124
|
- spec/numbers_spec.rb
|
119
125
|
- spec/sheet_spec.rb
|
120
126
|
- spec/spec_helper.rb
|
127
|
+
- spec/style_spec.rb
|
121
128
|
- spec/style_train_spec.rb
|
122
129
|
- spec/theme_spec.rb
|
123
130
|
- spec/themed_sheet_spec.rb
|