cascading_rubies 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,137 @@
1
+ = Cascading Rubies
2
+
3
+ Ruby DSL for generating CSS.
4
+
5
+ I wrote this small DSL because I like the concept of Sass -- just not
6
+ all the nuances of the syntax. I wondered how closely a Ruby DSL itself could
7
+ resemble final CSS output. This is the fruit of my experimentation.
8
+
9
+ I originally was going to call this RCSS, but that name is already taken.
10
+
11
+ Please note: This is very early beta, and the syntax may change. Also, this is
12
+ my very first DSL, and could very well be the biggest kludge you have ever seen.
13
+ But it works, and there's good test coverage, so hey.
14
+
15
+ == Syntax
16
+
17
+ header {
18
+ background_color '#eee'
19
+ margin_bottom '10px'
20
+ nav {
21
+ border '1px solid #000'
22
+ a(:link, :active, :visited) { color 'blue' }
23
+ a(:hover) { color 'red' }
24
+ }
25
+ div.search {
26
+ float 'right'
27
+ }
28
+ }
29
+
30
+ Output:
31
+
32
+ #header { background-color: #eee; margin-bottom: 10px; }
33
+ #header #nav { border: 1px solid #000; }
34
+ #header #nav a:link, #header #nav a:active, #header #nav a:visited { color: blue; }
35
+ #header #nav a:hover { color: red; }
36
+ #header div.search { float: right; }
37
+
38
+ Since the syntax is just Ruby, you can add comments, variables, and do just about anything
39
+ you can in plain Ruby.
40
+
41
+ === Tags/IDs
42
+
43
+ Tags are determined from the array #CascadingRubies::TAGS. If the name is present there, it is
44
+ assumed to be a tag -- otherwise the name is output as a selector <tt>#id</tt>.
45
+
46
+ === Classes
47
+
48
+ A leading underscore is used to denote a class selector, e.g. <tt>_search { }</tt> becomes
49
+ <tt>.search { }</tt> -- or you can put a tag in front of it like so: <tt>div.search { }</tt>.
50
+
51
+ === Comma-Separated Selectors
52
+
53
+ To output a comma-separated list of selectors, chain selectors together with semicolons
54
+ or newlines, like so: <tt>li; a { }</tt>.
55
+
56
+ === Examples
57
+
58
+ See files in example directory for more help.
59
+
60
+ == Installation
61
+
62
+ sudo gem install cascading_rubies -s http://gemcutter.org
63
+
64
+ == Usage
65
+
66
+ The gem includes a binary called +rcss+. Run it without args for usage details.
67
+ Here are some examples:
68
+
69
+ rcss base.rcss nav.rcss # print both rendered css files to screen
70
+ rcss -w base.rcss nav.rcss # write rendered base.css and nav.css
71
+ rcss base.rcss nav.rcss > all.css # write to single file
72
+ rcss -w stylesheets # render all .rcss files in directory
73
+
74
+ To use the library from within your own code:
75
+
76
+ require 'rubygems'
77
+ require 'cascading_rubies'
78
+
79
+ css = CascadingRubies.open(path_to_file)
80
+ # or...
81
+ css = CascadingRubies.new do
82
+ # css here
83
+ end
84
+
85
+ rendered = css.to_s
86
+
87
+ == Shortcomings
88
+
89
+ There are lots, no doubt. Here are few I thought up just now:
90
+
91
+ * CascadingRubies#s is the method that builds selectors, so you can't specify an id #s directly
92
+ in the DSL. Do this instead: <tt>s('#s') { ... }</tt>
93
+ * And there are a couple other names you can't use as ids (unless you use +s+):
94
+ * to\_s
95
+ * instance\_eval
96
+ * class
97
+ * inspect
98
+ * (others?)
99
+ * You can't build a selector like div#links without using the raw selector method:
100
+ <tt>s('div#links') { ... }</tt>
101
+
102
+ == Feedback
103
+
104
+ I'd love to hear from you if you have suggestions for improvement, bug fixes,
105
+ or whatever. Email me at tim@timmorgan.org or fork the project and send a
106
+ pull request.
107
+
108
+ To run the tests, do this:
109
+ ruby test/test_cascading_rubies.rb
110
+
111
+ The library has been tested with Ruby 1.8.6, Ruby 1.8.7 and Ruby 1.9.1p0.
112
+ If you find problems with your Ruby of choice, please let me know.
113
+
114
+ == License
115
+
116
+ The MIT License
117
+
118
+ Copyright (c) 2009 Tim Morgan
119
+
120
+ Permission is hereby granted, free of charge, to any person obtaining a copy
121
+ of this software and associated documentation files (the "Software"), to deal
122
+ in the Software without restriction, including without limitation the rights
123
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
124
+ copies of the Software, and to permit persons to whom the Software is
125
+ furnished to do so, subject to the following conditions:
126
+
127
+ The above copyright notice and this permission notice shall be included in
128
+ all copies or substantial portions of the Software.
129
+
130
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
131
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
132
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
133
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
134
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
135
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
136
+ THE SOFTWARE.
137
+
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $: << File.expand_path(File.dirname(__FILE__) + '/../lib')
4
+ require 'rubygems'
5
+ require 'cascading_rubies'
6
+
7
+ WRITE_OUT = ARGV.delete('-w') || ARGV.delete('--write')
8
+
9
+ def handle(path)
10
+ css = CascadingRubies.open(path)
11
+ if WRITE_OUT
12
+ File.open(path.sub(/\.[^\.]+$/, '.css'), 'w') { |f| f.write(css) }
13
+ else
14
+ puts css
15
+ end
16
+ end
17
+
18
+ ARGV.each do |path|
19
+ if File.directory?(path)
20
+ Dir[path + '/*.rcss'].each { |p| handle(p) }
21
+ elsif File.exist?(path)
22
+ handle(path)
23
+ else
24
+ puts "File or path not found: #{path}"
25
+ exit(1)
26
+ end
27
+ end
28
+
29
+ unless ARGV.any?
30
+ puts 'Builds CSS from Ruby -- see http://github.com/seven1m/cascading_rubies'
31
+ puts 'Usage: rcss [-w] path1 [path2 [...]]'
32
+ puts 'path can be one or more files or a directory of .rcss files'
33
+ puts
34
+ puts 'Options:'
35
+ puts ' -w --write write .css file(s) at same path'
36
+ puts
37
+ end
@@ -0,0 +1,7 @@
1
+ # Wrap the code in a block like this, calling the "css" method.
2
+ # This and the other block example should easily allow code outside the block
3
+ # to reference Kernel level methods, require additional code, etc.
4
+
5
+ css do
6
+ nav { color :red }
7
+ end
@@ -0,0 +1,7 @@
1
+ # Wrap the code in a block like this, calling the "CascadingRubies.css" class method.
2
+ # This and the other block example should easily allow code outside the block
3
+ # to reference Kernel level methods, require additional code, etc.
4
+
5
+ CascadingRubies.css do
6
+ nav { color :red }
7
+ end
@@ -0,0 +1,39 @@
1
+ # To see output: ruby bin/rcss example/example.rcss
2
+
3
+ require 'rubygems'; require 'sass'; Color = Sass::Constant::Color
4
+
5
+ bg_color = Color.parse('#eee')
6
+ footer_bg_color = bg_color.minus(Color.parse('#222'))
7
+
8
+ CascadingRubies.css do
9
+
10
+ header {
11
+ border '1px solid black'
12
+ background_color bg_color
13
+ padding '10px'
14
+ _search {
15
+ float :right
16
+ margin_right '20px'
17
+ a { text_decoration 'none' }
18
+ }
19
+ nav do |n|
20
+ n.margin '10px'
21
+ end
22
+ }
23
+
24
+ s('body>#content') {
25
+ margin '10px'
26
+ }
27
+
28
+ div.bordered {
29
+ border '1px solid #ccc'
30
+ }
31
+
32
+ a(:visited) { color 'purple' }
33
+ a(:link, :active) { color 'blue' }
34
+
35
+ footer {
36
+ background_color footer_bg_color
37
+ }
38
+
39
+ end
@@ -0,0 +1,6 @@
1
+ # Code in an rcss file does not strictly have to be wrapped in a block.
2
+ # Unlike the two block examples, the entire file is run through instance_eval,
3
+ # which makes using external libraries and other code a bit more difficult,
4
+ # but allows for a super clean file.
5
+
6
+ nav { color :red }
@@ -0,0 +1,113 @@
1
+ #!/usr/bin/env ruby
2
+ #--
3
+ # Copyright 2004, 2006 by Jim Weirich (jim@weirichhouse.org).
4
+ # All rights reserved.
5
+
6
+ # Permission is granted for use, copying, modification, distribution,
7
+ # and distribution of modified versions of this work as long as the
8
+ # above copyright notice is included.
9
+ #++
10
+
11
+ ######################################################################
12
+ # BlankSlate provides an abstract base class with no predefined
13
+ # methods (except for <tt>\_\_send__</tt> and <tt>\_\_id__</tt>).
14
+ # BlankSlate is useful as a base class when writing classes that
15
+ # depend upon <tt>method_missing</tt> (e.g. dynamic proxies).
16
+ #
17
+ class BlankSlate #:nodoc:
18
+ class << self
19
+
20
+ # Hide the method named +name+ in the BlankSlate class. Don't
21
+ # hide +instance_eval+ or any method beginning with "__".
22
+ def hide(name)
23
+ if instance_methods.include?(name.to_s) and
24
+ name !~ /^(__|instance_eval)/
25
+ @hidden_methods ||= {}
26
+ @hidden_methods[name.to_sym] = instance_method(name)
27
+ undef_method name
28
+ end
29
+ end
30
+
31
+ def find_hidden_method(name)
32
+ @hidden_methods ||= {}
33
+ @hidden_methods[name] || superclass.find_hidden_method(name)
34
+ end
35
+
36
+ # Redefine a previously hidden method so that it may be called on a blank
37
+ # slate object.
38
+ def reveal(name)
39
+ bound_method = nil
40
+ unbound_method = find_hidden_method(name)
41
+ fail "Don't know how to reveal method '#{name}'" unless unbound_method
42
+ define_method(name) do |*args|
43
+ bound_method ||= unbound_method.bind(self)
44
+ bound_method.call(*args)
45
+ end
46
+ end
47
+ end
48
+
49
+ instance_methods.each { |m| hide(m) }
50
+ end
51
+
52
+ ######################################################################
53
+ # Since Ruby is very dynamic, methods added to the ancestors of
54
+ # BlankSlate <em>after BlankSlate is defined</em> will show up in the
55
+ # list of available BlankSlate methods. We handle this by defining a
56
+ # hook in the Object and Kernel classes that will hide any method
57
+ # defined after BlankSlate has been loaded.
58
+ #
59
+ module Kernel
60
+ class << self
61
+ alias_method :blank_slate_method_added, :method_added
62
+
63
+ # Detect method additions to Kernel and remove them in the
64
+ # BlankSlate class.
65
+ def method_added(name)
66
+ result = blank_slate_method_added(name)
67
+ return result if self != Kernel
68
+ BlankSlate.hide(name)
69
+ result
70
+ end
71
+ end
72
+ end
73
+
74
+ ######################################################################
75
+ # Same as above, except in Object.
76
+ #
77
+ class Object
78
+ class << self
79
+ alias_method :blank_slate_method_added, :method_added
80
+
81
+ # Detect method additions to Object and remove them in the
82
+ # BlankSlate class.
83
+ def method_added(name)
84
+ result = blank_slate_method_added(name)
85
+ return result if self != Object
86
+ BlankSlate.hide(name)
87
+ result
88
+ end
89
+
90
+ def find_hidden_method(name)
91
+ nil
92
+ end
93
+ end
94
+ end
95
+
96
+ ######################################################################
97
+ # Also, modules included into Object need to be scanned and have their
98
+ # instance methods removed from blank slate. In theory, modules
99
+ # included into Kernel would have to be removed as well, but a
100
+ # "feature" of Ruby prevents late includes into modules from being
101
+ # exposed in the first place.
102
+ #
103
+ class Module
104
+ alias blankslate_original_append_features append_features
105
+ def append_features(mod)
106
+ result = blankslate_original_append_features(mod)
107
+ return result if mod != Object
108
+ instance_methods.each do |name|
109
+ BlankSlate.hide(name)
110
+ end
111
+ result
112
+ end
113
+ end
@@ -0,0 +1,144 @@
1
+ # Ruby DSL for generating CSS.
2
+ # Copyright (c) 2009 Tim Morgan
3
+
4
+ require File.dirname(__FILE__) + '/blankslate'
5
+
6
+ class CascadingRubies < BlankSlate #:doc:
7
+
8
+ [:class, :respond_to?, :inspect].each { |m| reveal(m) rescue nil }
9
+ undef_method(:p)
10
+
11
+ # List of tags taken from http://www.w3schools.com/tags/default.asp
12
+ TAGS = %w(a abbr acronym address applet area b base basefont bdo big blockquote body br button caption center cite code col colgroup dd del dir div dfn dl dt em fieldset font form frame frameset h1 h2 h3 h4 h5 h6 head hr html i iframe img input ins isindex kbd label legend li link map meta noframes noscript object ol optgroup option p param pre q samp script select small span strike strong style sub sup table tbody td textarea tfoot th thead title tr tt u ul var xmp)
13
+
14
+ attr_reader :__selectors, :__css, :__context_name, :__has_children #:nodoc:
15
+
16
+ # Creates a CascadingRubies object. Normally, you should not pass in any arguments,
17
+ # except a block of style definitions. The block can optionally take a single argument --
18
+ # if so, the newly created object is yielded to the block, and instance_eval is not used.
19
+ #
20
+ # Each block in the style definitions is effectively going to trigger a new object to
21
+ # be created, so the block argument is optional <em>for each block</em>, and the determination to
22
+ # use instance_eval is subsequently <em>per block</em>:
23
+ # CascadingRubies.new do |css|
24
+ # css.header do |header|
25
+ # header.background_color '#ccc'
26
+ # end
27
+ # css.p {
28
+ # margin_bottom '15px'
29
+ # }
30
+ # end
31
+ #
32
+ # If you do not pass a block (or even if you do), you can execute additional style definitions
33
+ # by either calling methods directly on the object:
34
+ # obj = CascadingRubies.new
35
+ # obj.nav { margin '10px'; a { color :red } }
36
+ # or you can instance_eval another block of code:
37
+ # obj.instance_eval do
38
+ # p { margin_bottom '15px' }
39
+ # end
40
+ def initialize(context_name=nil, selectors=[], classed=false, &dsl_code)
41
+ @__context_name = context_name
42
+ @__css = ''
43
+ @__selectors = selectors
44
+ @__classed = classed # if true, method_missing calls are css class selectors -- not id selectors
45
+ if dsl_code.nil?
46
+ # do nothing
47
+ elsif dsl_code.arity == 1
48
+ dsl_code[self]
49
+ else
50
+ instance_eval(&dsl_code)
51
+ end
52
+ end
53
+
54
+ # Create a new style "selector" without going through method_missing.
55
+ # Use this to create style definitions that cannot be created with the DSL directly, e.g.
56
+ # * <tt>s('##s') { color :blue }</tt> => <tt>##s { color: blue; }</tt>
57
+ # * <tt>s('div##search') { margin 0 }</tt> => <tt>div##search { margin: 0; }</tt>
58
+ def s(selector, *args, &dsl_code)
59
+ if args.any? and dsl_code.nil? # css rule
60
+ @__css << "#{selector}: #{args.join(' ')}; "
61
+ else
62
+ if args.any? and dsl_code # pseudo-class selector
63
+ selector_name = args.map do |arg|
64
+ [[@__context_name, selector].compact.join(' '), ':' + arg.to_s].join('')
65
+ end.join(', ')
66
+ else # regular selector
67
+ selector_name = [@__context_name, selector].compact.join(@__classed ? '' : ' ')
68
+ end
69
+ if @__bare and not @__bare.__has_children # e.g. li; a { }
70
+ selector_name = "#{@__bare.__context_name}, #{selector_name}"
71
+ end
72
+ if dsl_code
73
+ compiled = self.class.new(selector_name, &dsl_code)
74
+ @__selectors << "#{selector_name} { #{compiled.__css}}" unless compiled.__css.empty?
75
+ @__selectors += compiled.__selectors
76
+ @__bare = nil
77
+ else # e.g. div.something
78
+ @__bare = self.class.new(selector_name, @__selectors, true, &dsl_code)
79
+ end
80
+ end
81
+ end
82
+
83
+ def method_missing(method_name, *args, &dsl_code) #:nodoc:
84
+ @__has_children = true
85
+ selector = dsl_code ? __method_name_to_selector(method_name) : __dashify(method_name)
86
+ s(selector, *args, &dsl_code)
87
+ end
88
+
89
+ # Returns the complete CSS style definitions as a string.
90
+ def to_s
91
+ @__selectors.join("\n")
92
+ end
93
+
94
+ # Creates a CascadingRubies object, then opens the file and executes the style
95
+ # definitions in the context of the object. Returns the newly created object.
96
+ def self.open(path)
97
+ if (code = File.read(path)) =~ /^css do|CascadingRubies\.css do/
98
+ eval(code)
99
+ else
100
+ css(code)
101
+ end
102
+ @obj
103
+ end
104
+
105
+ # Wraps the creation of a CascadingRubies object and doing the instance_eval execution
106
+ # in a neat package for use inside rcss files. An rcss file can use the optional block
107
+ # syntax to wrap style definitions, allowing code to be run outside the instance_eval
108
+ # confines. Use this method in an .rcss file like so:
109
+ # css do
110
+ # a { color :red }
111
+ # end
112
+ # or:
113
+ # CascadingRubies.css do
114
+ # a { color :red }
115
+ # end
116
+ def self.css(code=nil, &block)
117
+ @obj = self.new
118
+ if code
119
+ @obj.instance_eval(code)
120
+ else
121
+ @obj.instance_eval(&block)
122
+ end
123
+ end
124
+
125
+ private
126
+
127
+ def __method_name_to_selector(method_name)
128
+ selector = method_name.to_s
129
+ if selector.sub!(/^_/, '.')
130
+ __dashify(selector)
131
+ elsif TAGS.include?(selector)
132
+ __dashify(selector)
133
+ elsif @__classed
134
+ '.' + __dashify(selector)
135
+ else
136
+ '#' + __dashify(selector)
137
+ end
138
+ end
139
+
140
+ def __dashify(name)
141
+ name.to_s.gsub(/_/, '-').downcase
142
+ end
143
+
144
+ end
@@ -0,0 +1,138 @@
1
+ $: << File.expand_path(File.dirname(__FILE__) + '/../lib')
2
+
3
+ require 'cascading_rubies'
4
+ require 'test/unit'
5
+
6
+ class TestCascadingRubies < Test::Unit::TestCase
7
+
8
+ # selectors
9
+
10
+ def test_id_selector
11
+ assert_produces "#nav { color: red; }", "nav { color :red }"
12
+ end
13
+
14
+ def test_class_selector
15
+ assert_produces ".links { color: red; }", "_links { color :red }"
16
+ end
17
+
18
+ def test_class_selector_with_tag
19
+ assert_produces "div.links { color: red; }", "div.links { color :red }"
20
+ end
21
+
22
+ def test_tag_selector
23
+ assert_produces "div { color: red; }", "div { color :red }"
24
+ end
25
+
26
+ def test_raw_selector
27
+ assert_produces "body>#content { color: red; }", "s('body>#content') { color :red }"
28
+ assert_produces "#s { color: red; }", "s('#s') { color :red }"
29
+ end
30
+
31
+ def test_pseudo_class_selector
32
+ assert_produces "a:link { color: red; }", "a(:link) { color :red }"
33
+ assert_produces "a:hover, a:active { color: red; }", "a(:hover, :active) { color :red }"
34
+ end
35
+
36
+ def test_multiple_comma_separated_selectors
37
+ assert_produces "#nav li, #nav a { color: red; }", "nav { li; a { color :red } }" # double
38
+ assert_produces "#nav li, #nav div, #nav a { color: red; }", "nav { li; div; a { color :red } }" # triple
39
+ output = <<-CSS
40
+ #nav li, #nav a:link, #nav a:visited { color: red; }
41
+ #nav a { color: green; }
42
+ CSS
43
+ code = <<-CSS
44
+ nav {
45
+ li; a(:link, :visited) {
46
+ color :red
47
+ }
48
+ a {
49
+ color :green
50
+ }
51
+ }
52
+ CSS
53
+ assert_produces output.gsub(/^\s+/, '').chomp, code # following selector isn't affected
54
+ end
55
+
56
+ def test_empty_selectors_not_printed
57
+ assert_produces "#nav li { color: red; }", "nav { li { color :red } }"
58
+ end
59
+
60
+ # nesting
61
+
62
+ def test_nested_selectors
63
+ output = <<-CSS
64
+ #header { color: red; }
65
+ #header #nav { color: blue; }
66
+ #header #nav a { color: green; }
67
+ CSS
68
+ code = <<-CSS
69
+ header {
70
+ color :red
71
+ nav {
72
+ color :blue
73
+ a {
74
+ color :green
75
+ }
76
+ }
77
+ }
78
+ CSS
79
+ assert_produces output.gsub(/^\s+/, '').chomp, code
80
+ end
81
+
82
+ def test_nested_pseudo_class_selector
83
+ output = <<-CSS
84
+ #header { color: red; }
85
+ #header a:link { color: blue; }
86
+ CSS
87
+ code = <<-CSS
88
+ header {
89
+ color :red
90
+ a(:link) {
91
+ color :blue
92
+ }
93
+ }
94
+ CSS
95
+ assert_produces output.gsub(/^\s+/, '').chomp, code
96
+ end
97
+
98
+ # rules
99
+
100
+ def test_underscores_replaced_with_dashes
101
+ assert_produces "a { text-decoration: none; }", "a { text_decoration 'none' }"
102
+ end
103
+
104
+ def test_symbols_as_values
105
+ assert_produces "a { text-decoration: none; }", "a { text_decoration :none }"
106
+ end
107
+
108
+ # misc
109
+
110
+ def test_use_p_tag
111
+ assert_produces "p { color: red; }", "p { color :red }"
112
+ end
113
+
114
+ def test_puts
115
+ assert_produces "a { color: red; }", "a { color :red }"
116
+ assert_nothing_raised do
117
+ puts @css
118
+ end
119
+ end
120
+
121
+ def test_examples
122
+ Dir[File.dirname(__FILE__) + '/../example/*.rcss'].each do |path|
123
+ assert_nothing_raised do
124
+ @css = CascadingRubies.open(path)
125
+ end
126
+ assert @css.to_s != ''
127
+ end
128
+ end
129
+
130
+ private
131
+
132
+ def assert_produces(output, code)
133
+ @css = CascadingRubies.new
134
+ @css.instance_eval(code)
135
+ assert_equal output, @css.to_s
136
+ end
137
+
138
+ end
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cascading_rubies
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.2
5
+ platform: ruby
6
+ authors:
7
+ - Tim Morgan
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-10-21 00:00:00 -05:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: tim@timmorgan.org
18
+ executables:
19
+ - rcss
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - README.rdoc
26
+ - lib/cascading_rubies.rb
27
+ - lib/blankslate.rb
28
+ - bin/rcss
29
+ - test/test_cascading_rubies.rb
30
+ - example/example.rcss
31
+ - example/block_example_1.rcss
32
+ - example/block_example_2.rcss
33
+ - example/no_block_example.rcss
34
+ has_rdoc: true
35
+ homepage: http://github.com/seven1m/cascading_rubies
36
+ licenses: []
37
+
38
+ post_install_message:
39
+ rdoc_options: []
40
+
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: "0"
48
+ version:
49
+ required_rubygems_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: "0"
54
+ version:
55
+ requirements: []
56
+
57
+ rubyforge_project:
58
+ rubygems_version: 1.3.5
59
+ signing_key:
60
+ specification_version: 3
61
+ summary: Ruby DSL for generating CSS.
62
+ test_files: []
63
+