automatthew-cassandra 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Manifest +21 -0
- data/README.rdoc +29 -0
- data/cassandra.gemspec +133 -0
- data/lib/cassandra.rb +236 -0
- data/lib/properties.rb +119 -0
- data/lib/tags.rb +89 -0
- data/misc/dan.cssy +160 -0
- data/misc/dan.rb +64 -0
- data/misc/meyer_reset.css +53 -0
- data/site/basic.cssy +16 -0
- data/site/basic.rb +22 -0
- data/site/cssy_title.jpg +0 -0
- data/site/flower.png +0 -0
- data/site/index.mab +32 -0
- data/site/ruby.cssy +15 -0
- data/test/assigns.rb +26 -0
- data/test/basics.css +22 -0
- data/test/basics.cssy +34 -0
- data/test/basics.rb +107 -0
- data/test/comments.rb +44 -0
- data/test/helper.rb +8 -0
- metadata +84 -0
data/Manifest
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
cassandra.gemspec
|
2
|
+
lib/cassandra.rb
|
3
|
+
lib/properties.rb
|
4
|
+
lib/tags.rb
|
5
|
+
Manifest
|
6
|
+
misc/dan.cssy
|
7
|
+
misc/dan.rb
|
8
|
+
misc/meyer_reset.css
|
9
|
+
README.rdoc
|
10
|
+
site/basic.cssy
|
11
|
+
site/basic.rb
|
12
|
+
site/cssy_title.jpg
|
13
|
+
site/flower.png
|
14
|
+
site/index.mab
|
15
|
+
site/ruby.cssy
|
16
|
+
test/assigns.rb
|
17
|
+
test/basics.css
|
18
|
+
test/basics.cssy
|
19
|
+
test/basics.rb
|
20
|
+
test/comments.rb
|
21
|
+
test/helper.rb
|
data/README.rdoc
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
= Cassandra, a.k.a Cssy
|
2
|
+
|
3
|
+
Cassandra is a CSS companion to Markaby. You declare selectors using methods named after the type selectors (i.e. tags) or after the class and id selectors of your choice, which are handled by method_missing. As in Markaby, id selectors are distinguished from class selectors by the "!" at the end of the method name. You can chain class/id selectors onto type selectors and each other.
|
4
|
+
|
5
|
+
Because in CSS you don't have to begin with a type selector, starting a selector chain with a class/id selector is currently allowed in Cassandra. This may go away in the future.
|
6
|
+
|
7
|
+
== Usage
|
8
|
+
|
9
|
+
|
10
|
+
@css = Cssy.new
|
11
|
+
@css.process do
|
12
|
+
|
13
|
+
body { background_color "#F8F7F1"}
|
14
|
+
div.content! {
|
15
|
+
width "700px"; margin "25px auto"
|
16
|
+
|
17
|
+
a {
|
18
|
+
color "#212F54";
|
19
|
+
text_decoration :none
|
20
|
+
font_weight :bold
|
21
|
+
}
|
22
|
+
|
23
|
+
ul.links! { list_style "url(flower.png)" }
|
24
|
+
}
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
@css.data #=> array of arrays
|
29
|
+
@css.to_s
|
data/cassandra.gemspec
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
|
2
|
+
# Gem::Specification for Cassandra-0.2.3
|
3
|
+
# Originally generated by Echoe
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = %q{cassandra}
|
7
|
+
s.version = "0.2.3"
|
8
|
+
|
9
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
10
|
+
s.authors = ["Matthew King"]
|
11
|
+
s.date = %q{2008-09-30}
|
12
|
+
s.description = %q{Generates CSS using Ruby, like Markaby}
|
13
|
+
s.email = %q{automatthew@gmail.com}
|
14
|
+
s.extra_rdoc_files = ["lib/cassandra.rb", "lib/properties.rb", "lib/tags.rb", "README.rdoc"]
|
15
|
+
s.files = ["cassandra.gemspec", "lib/cassandra.rb", "lib/properties.rb", "lib/tags.rb", "Manifest", "misc/dan.cssy", "misc/dan.rb", "misc/meyer_reset.css", "README.rdoc", "site/basic.cssy", "site/basic.rb", "site/cssy_title.jpg", "site/flower.png", "site/index.mab", "site/ruby.cssy", "test/assigns.rb", "test/basics.css", "test/basics.cssy", "test/basics.rb", "test/comments.rb", "test/helper.rb"]
|
16
|
+
s.has_rdoc = true
|
17
|
+
s.homepage = %q{}
|
18
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Cassandra", "--main", "README.rdoc"]
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
s.rubyforge_project = %q{cassandra}
|
21
|
+
s.rubygems_version = %q{1.2.0}
|
22
|
+
s.summary = %q{Generates CSS using Ruby, like Markaby}
|
23
|
+
s.test_files = ["test/assigns.rb", "test/basics.rb", "test/comments.rb", "test/helper.rb"]
|
24
|
+
|
25
|
+
if s.respond_to? :specification_version then
|
26
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
27
|
+
s.specification_version = 2
|
28
|
+
|
29
|
+
if current_version >= 3 then
|
30
|
+
else
|
31
|
+
end
|
32
|
+
else
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
# # Original Rakefile source (requires the Echoe gem):
|
38
|
+
#
|
39
|
+
# require 'rubygems'
|
40
|
+
#
|
41
|
+
# Version = '0.2.3'
|
42
|
+
#
|
43
|
+
# task :default => [ :test ]
|
44
|
+
#
|
45
|
+
# begin
|
46
|
+
# gem 'echoe', '>=2.7'
|
47
|
+
# require 'echoe'
|
48
|
+
# Echoe.new('cassandra', Version) do |p|
|
49
|
+
# p.project = 'cassandra'
|
50
|
+
# p.summary = "Generates CSS using Ruby, like Markaby"
|
51
|
+
# p.author = "Matthew King"
|
52
|
+
# p.email = "automatthew@gmail.com"
|
53
|
+
# p.ignore_pattern = /^(\.git).+/
|
54
|
+
# p.test_pattern = "test/*.rb"
|
55
|
+
# end
|
56
|
+
# rescue
|
57
|
+
# "(ignored echoe gemification, as you don't have the Right Stuff)"
|
58
|
+
# end
|
59
|
+
#
|
60
|
+
# module Rake::TaskManager
|
61
|
+
# def delete_task(task_class, *args, &block)
|
62
|
+
# task_name, deps = resolve_args(args)
|
63
|
+
# @tasks.delete(task_class.scope_name(@scope, task_name).to_s)
|
64
|
+
# end
|
65
|
+
# end
|
66
|
+
# class Rake::Task
|
67
|
+
# def self.delete_task(args, &block) Rake.application.delete_task(self, args, &block) end
|
68
|
+
# end
|
69
|
+
# def delete_task(args, &block) Rake::Task.delete_task(args, &block) end
|
70
|
+
#
|
71
|
+
# delete_task :publish_docs
|
72
|
+
#
|
73
|
+
# desc "Publish rdocs to rubyforge"
|
74
|
+
# task :publish_docs => [ :clean, :docs ] do
|
75
|
+
# config = YAML.load(File.read(File.expand_path("~/.rubyforge/user-config.yml")))
|
76
|
+
# pub = Rake::SshDirPublisher.new "#{config["username"]}@rubyforge.org",
|
77
|
+
# "/var/www/gforge-projects/cassandra/rdoc",
|
78
|
+
# 'doc'
|
79
|
+
# pub.upload
|
80
|
+
# end
|
81
|
+
#
|
82
|
+
# task :publish_site => [ :compile ] do
|
83
|
+
# cmd = "scp -qr site/*.{html,css,jpg,png} automatthew@rubyforge.org:/var/www/gforge-projects/cassandra"
|
84
|
+
# puts "Uploading: #{cmd}"
|
85
|
+
# system(cmd)
|
86
|
+
# end
|
87
|
+
#
|
88
|
+
# def rubyforge_config
|
89
|
+
# @rubyforge_config ||= YAML.load(File.read(File.expand_path("~/.rubyforge/user-config.yml")))
|
90
|
+
# end
|
91
|
+
#
|
92
|
+
#
|
93
|
+
#
|
94
|
+
# # List all the desired pages as dependencies on :compile
|
95
|
+
# desc "compile templates to html and css"
|
96
|
+
# task :compile => %w{ site/index.html site/basic.css site/ruby.css }
|
97
|
+
#
|
98
|
+
# task :clean do
|
99
|
+
# f = FileList['site/**/*.html', 'site/*.css']
|
100
|
+
# puts f; rm f
|
101
|
+
# end
|
102
|
+
#
|
103
|
+
# rule '.html' => [ '.mab' ] do |t|
|
104
|
+
# mab(t.source, t.name)
|
105
|
+
# end
|
106
|
+
#
|
107
|
+
# file 'site/index.html' => [ 'site/basic.css', 'site/index.mab' ]
|
108
|
+
#
|
109
|
+
# rule '.css' => [ '.cssy' ] do |t|
|
110
|
+
# cssify(t.source, t.name)
|
111
|
+
# end
|
112
|
+
#
|
113
|
+
# require 'markaby'
|
114
|
+
# $:.unshift "lib"
|
115
|
+
# require 'cassandra'
|
116
|
+
#
|
117
|
+
# def mab(source, target)
|
118
|
+
# mab = Markaby::Builder.new
|
119
|
+
# result = mab.instance_eval(File.read(source))
|
120
|
+
# File.open(target, 'w') do |f|
|
121
|
+
# f.puts result
|
122
|
+
# end
|
123
|
+
# end
|
124
|
+
#
|
125
|
+
# def cssify(source, target)
|
126
|
+
# cssy = File.read(source)
|
127
|
+
# c = Cssy.new.process(cssy, { :default => "#212F54" })
|
128
|
+
# File.open(target, 'w') do |f|
|
129
|
+
# f.puts c.to_s
|
130
|
+
# end
|
131
|
+
# end
|
132
|
+
#
|
133
|
+
#
|
data/lib/cassandra.rb
ADDED
@@ -0,0 +1,236 @@
|
|
1
|
+
require 'properties'
|
2
|
+
require 'tags'
|
3
|
+
|
4
|
+
# Cassandra is a CSS generator that takes Ruby blocks as input. You can call her Cssy, for short.
|
5
|
+
# At her grubbiest, Cssy gives you selector and property methods you can use for direct declarations
|
6
|
+
#
|
7
|
+
# css = Cssy.process do
|
8
|
+
# selector "div#main" do
|
9
|
+
# property "margin-left", "100px"
|
10
|
+
# selector "a" do
|
11
|
+
# property "color", "red"
|
12
|
+
# end
|
13
|
+
# end
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# Cssy cleans up real nice, though:
|
17
|
+
#
|
18
|
+
# css = Cssy.process do
|
19
|
+
# div.main! do
|
20
|
+
# margin_left "100px"
|
21
|
+
# a { color :red }
|
22
|
+
# end
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# Chained methods on a selector represent classes and ids (as in Markaby).
|
26
|
+
# Note that the "margin-left" property is declared with a method named margin_left. Hyphens in
|
27
|
+
# property names become underscores in Cssy method names.
|
28
|
+
# In property declarations, you can use symbols for CSS keywords (e.g. :red, :none, :absolute, :left).
|
29
|
+
#
|
30
|
+
# All the processing takes place in a single Cssy instance, so you can set instance variables and define helper methods, either directly on the instance, or mixed in from a module.
|
31
|
+
#
|
32
|
+
# css.instance_eval do
|
33
|
+
# @fg, @bg = "#333", "#ccc"
|
34
|
+
# def invert
|
35
|
+
# color @bg
|
36
|
+
# background @fg
|
37
|
+
# end
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
# Once an instance of Cssy is all loaded up with generating goodness, use to_s to output the CSS.
|
41
|
+
|
42
|
+
|
43
|
+
class Cassandra
|
44
|
+
|
45
|
+
# Clear out unneeded methods
|
46
|
+
METHODS = %w( class instance_eval send __send__ __id__ instance_variable_set )
|
47
|
+
instance_methods.each { |m| undef_method( m ) unless METHODS.include? m }
|
48
|
+
|
49
|
+
attr_reader :data
|
50
|
+
|
51
|
+
# Create a new instance of Cssy, optionally with a base selector
|
52
|
+
#
|
53
|
+
# css = Cssy.new
|
54
|
+
#
|
55
|
+
# header = Cssy.new("div#header")
|
56
|
+
def initialize(sel=nil)
|
57
|
+
@data = []
|
58
|
+
@selectors = [ sel ]
|
59
|
+
@properties = []
|
60
|
+
|
61
|
+
# Primitive state machine
|
62
|
+
# possible states are :closed_block, :chain, :open_block
|
63
|
+
@state = :closed_block
|
64
|
+
end
|
65
|
+
|
66
|
+
def instance_variables(hashlike)
|
67
|
+
hashlike.each do |key,val|
|
68
|
+
instance_variable_set("@#{key}",val)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Create a new instance and process the supplied block, returning the instance.
|
73
|
+
#
|
74
|
+
# css = Cssy.process do
|
75
|
+
# ul do
|
76
|
+
# li { list_style :none }
|
77
|
+
# end
|
78
|
+
# end
|
79
|
+
def self.process(*args, &block)
|
80
|
+
self.new.process(*args, &block)
|
81
|
+
end
|
82
|
+
|
83
|
+
# Process the supplied block (storing the result internally as an array in @data).
|
84
|
+
# Returns the Cssy instance.
|
85
|
+
#
|
86
|
+
# If no block is given, join all arguments with "\n" and eval the result. Dubious utility.
|
87
|
+
def process(*args, &block)
|
88
|
+
assigns = args[0] if args[0].is_a? Hash
|
89
|
+
string, assigns = args if args[0].is_a? String
|
90
|
+
instance_variables(assigns) if assigns
|
91
|
+
if block
|
92
|
+
instance_eval(&block)
|
93
|
+
elsif string
|
94
|
+
instance_eval(string)
|
95
|
+
end
|
96
|
+
self
|
97
|
+
end
|
98
|
+
|
99
|
+
# Output CSS as a string
|
100
|
+
def to_s
|
101
|
+
@data.map do |sel|
|
102
|
+
properties = sel.last.join("\n ")
|
103
|
+
"#{sel.first} {\n #{properties}\n}\n" unless properties.empty?
|
104
|
+
end.join
|
105
|
+
end
|
106
|
+
|
107
|
+
# Declare a CSS selector using a block. May be chained and nested.
|
108
|
+
#
|
109
|
+
# selector "a:visited" do
|
110
|
+
# color :gray
|
111
|
+
# end
|
112
|
+
def selector(sel)
|
113
|
+
if block_given?
|
114
|
+
open(sel)
|
115
|
+
yield
|
116
|
+
close
|
117
|
+
else
|
118
|
+
chain(sel)
|
119
|
+
end
|
120
|
+
self
|
121
|
+
end
|
122
|
+
|
123
|
+
alias :s :selector
|
124
|
+
|
125
|
+
# Add a property declaration for the current selector.
|
126
|
+
#
|
127
|
+
# property "margin-bottom", "42px"
|
128
|
+
#
|
129
|
+
def property(css_attr, *args)
|
130
|
+
@properties[-1] << "#{css_attr}: #{args.join(' ')};"
|
131
|
+
end
|
132
|
+
|
133
|
+
def add_comment(string)
|
134
|
+
@properties[-1] << "/* #{string} */"
|
135
|
+
end
|
136
|
+
|
137
|
+
# Catch unknown methods and treat them as CSS class or id selectors. This may
|
138
|
+
# go away in future releases.
|
139
|
+
#
|
140
|
+
# monkey { padding "24px" }
|
141
|
+
#
|
142
|
+
def method_missing(name, &block)
|
143
|
+
sel = selectify(name)
|
144
|
+
if block_given?
|
145
|
+
open(sel)
|
146
|
+
yield
|
147
|
+
close
|
148
|
+
else
|
149
|
+
chain(sel)
|
150
|
+
end
|
151
|
+
self
|
152
|
+
end
|
153
|
+
|
154
|
+
# bang methods represent CSS ids. Otherwise CSS classes.
|
155
|
+
def selectify(method_name)
|
156
|
+
matches = method_name.to_s.match( /([\w_]+)!$/)
|
157
|
+
matches ? "##{matches[1]}" : ".#{method_name}"
|
158
|
+
end
|
159
|
+
|
160
|
+
private
|
161
|
+
|
162
|
+
# define tag methods that delegate to selector
|
163
|
+
methods = HTML_TAGS.map do |tag|
|
164
|
+
<<-METHOD
|
165
|
+
def #{tag}(&block)
|
166
|
+
selector('#{tag}', &block)
|
167
|
+
end
|
168
|
+
METHOD
|
169
|
+
end.join; module_eval(methods)
|
170
|
+
|
171
|
+
# define methods for CSS properties.
|
172
|
+
CSS_PROPERTIES.each do |method_name|
|
173
|
+
define_method method_name do |*args|
|
174
|
+
css_attr = method_name.gsub('_', '-')
|
175
|
+
property(css_attr, args)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
# Pushes an empty array on the properties stack and registers
|
180
|
+
# that array (against the current selector) in @data
|
181
|
+
def new_property_set
|
182
|
+
@properties.push []
|
183
|
+
@data << [@selectors[-1], @properties[-1] ]
|
184
|
+
end
|
185
|
+
|
186
|
+
## State transitions
|
187
|
+
|
188
|
+
# Push the accumulated selector and a new property array onto the
|
189
|
+
# tops of their respected stacks
|
190
|
+
def open(new_selector)
|
191
|
+
case @state
|
192
|
+
when :closed_block, :open_block
|
193
|
+
combined_selector = [@selectors[-1], new_selector].compact.join(" ")
|
194
|
+
@selectors.push combined_selector
|
195
|
+
new_property_set
|
196
|
+
when :chain
|
197
|
+
@selectors[-1] = "#{@selectors[-1]}#{new_selector}"
|
198
|
+
new_property_set
|
199
|
+
else
|
200
|
+
raise "#open not available when state is #{@state.inspect}"
|
201
|
+
end
|
202
|
+
|
203
|
+
@state = :open_block
|
204
|
+
end
|
205
|
+
|
206
|
+
# Pushes accumulated selector on the stack without generating a new properties array.
|
207
|
+
def chain(new_selector)
|
208
|
+
case @state
|
209
|
+
when :closed_block, :open_block
|
210
|
+
combined_selector = [@selectors[-1], new_selector].compact.join(" ")
|
211
|
+
@selectors.push combined_selector
|
212
|
+
when :chain
|
213
|
+
@selectors[-1] = "#{@selectors[-1]}#{new_selector}"
|
214
|
+
else
|
215
|
+
raise "#chain not available when state is #{@state.inspect}"
|
216
|
+
end
|
217
|
+
|
218
|
+
@state = :chain
|
219
|
+
end
|
220
|
+
|
221
|
+
# Pop the selector string and property array for the closing block
|
222
|
+
# off of their respective stacks
|
223
|
+
def close
|
224
|
+
case @state
|
225
|
+
when :open_block, :closed_block
|
226
|
+
@selectors.pop
|
227
|
+
@properties.pop
|
228
|
+
else
|
229
|
+
raise "#close not available when state is #{@state.inspect}"
|
230
|
+
end
|
231
|
+
|
232
|
+
@state = :closed_block
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
Cssy = Cassy = Cassandra
|
data/lib/properties.rb
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
class Cassandra
|
2
|
+
CSS_PROPERTIES = %w{
|
3
|
+
azimuth
|
4
|
+
background
|
5
|
+
background_attachment
|
6
|
+
background_color
|
7
|
+
background_image
|
8
|
+
background_position
|
9
|
+
background_repeat
|
10
|
+
border
|
11
|
+
border_left
|
12
|
+
border_top
|
13
|
+
border_right
|
14
|
+
border_bottom
|
15
|
+
border_collapse
|
16
|
+
border_color
|
17
|
+
border_spacing
|
18
|
+
border_style
|
19
|
+
border_top
|
20
|
+
border_top_color
|
21
|
+
border_top_style
|
22
|
+
border_top_width
|
23
|
+
border_width
|
24
|
+
bottom
|
25
|
+
caption_side
|
26
|
+
clear
|
27
|
+
clip
|
28
|
+
color
|
29
|
+
content
|
30
|
+
counter_increment
|
31
|
+
counter_reset
|
32
|
+
cue
|
33
|
+
cue_after
|
34
|
+
cue_before
|
35
|
+
cursor
|
36
|
+
direction
|
37
|
+
display
|
38
|
+
elevation
|
39
|
+
empty_cells
|
40
|
+
float
|
41
|
+
font
|
42
|
+
font_family
|
43
|
+
font_size
|
44
|
+
font_size_adjust
|
45
|
+
font_stretch
|
46
|
+
font_style
|
47
|
+
font_variant
|
48
|
+
font_weight
|
49
|
+
height
|
50
|
+
left
|
51
|
+
letter_spacing
|
52
|
+
line_height
|
53
|
+
list_style
|
54
|
+
list_style_image
|
55
|
+
list_style_position
|
56
|
+
list_style_type
|
57
|
+
margin
|
58
|
+
margin_left
|
59
|
+
margin_top
|
60
|
+
margin_right
|
61
|
+
margin_bottom
|
62
|
+
marker_offset
|
63
|
+
marks
|
64
|
+
max_height
|
65
|
+
max_width
|
66
|
+
min_height
|
67
|
+
min_width
|
68
|
+
orphans
|
69
|
+
outline
|
70
|
+
outline_color
|
71
|
+
outline_style
|
72
|
+
outline_width
|
73
|
+
overflow
|
74
|
+
padding
|
75
|
+
padding_left
|
76
|
+
padding_top
|
77
|
+
padding_right
|
78
|
+
padding_bottom
|
79
|
+
page
|
80
|
+
page_break_after
|
81
|
+
page_break_before
|
82
|
+
page_break_inside
|
83
|
+
pause
|
84
|
+
pause_after
|
85
|
+
pause_before
|
86
|
+
pitch
|
87
|
+
pitch_range
|
88
|
+
play_during
|
89
|
+
position
|
90
|
+
quotes
|
91
|
+
richness
|
92
|
+
right
|
93
|
+
size
|
94
|
+
speak
|
95
|
+
speak_header
|
96
|
+
speak_numeral
|
97
|
+
speak_punctuation
|
98
|
+
speech_rate
|
99
|
+
stress
|
100
|
+
table_layout
|
101
|
+
text_align
|
102
|
+
text_decoration
|
103
|
+
text_indent
|
104
|
+
text_shadow
|
105
|
+
text_transform
|
106
|
+
top
|
107
|
+
unicode_bidi
|
108
|
+
vertical_align
|
109
|
+
visibility
|
110
|
+
voice_family
|
111
|
+
volume
|
112
|
+
white_space
|
113
|
+
widows
|
114
|
+
width
|
115
|
+
word_spacing
|
116
|
+
z_index
|
117
|
+
}
|
118
|
+
|
119
|
+
end
|
data/lib/tags.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
class Cassandra
|
2
|
+
HTML_TAGS = [
|
3
|
+
:a,
|
4
|
+
:abbr,
|
5
|
+
:acronym,
|
6
|
+
:address,
|
7
|
+
:area,
|
8
|
+
:b,
|
9
|
+
:base,
|
10
|
+
:bdo,
|
11
|
+
:big,
|
12
|
+
:blockquote,
|
13
|
+
:body,
|
14
|
+
:br,
|
15
|
+
:button,
|
16
|
+
:caption,
|
17
|
+
:cite,
|
18
|
+
:code,
|
19
|
+
:col,
|
20
|
+
:colgroup,
|
21
|
+
:dd,
|
22
|
+
:del,
|
23
|
+
:dfn,
|
24
|
+
:div,
|
25
|
+
:dl,
|
26
|
+
:dt,
|
27
|
+
:em,
|
28
|
+
:fieldset,
|
29
|
+
:form,
|
30
|
+
:h1,
|
31
|
+
:h2,
|
32
|
+
:h3,
|
33
|
+
:h4,
|
34
|
+
:h5,
|
35
|
+
:h6,
|
36
|
+
:head,
|
37
|
+
:hr,
|
38
|
+
:html,
|
39
|
+
:i,
|
40
|
+
:img,
|
41
|
+
:input,
|
42
|
+
:ins,
|
43
|
+
:kbd,
|
44
|
+
:label,
|
45
|
+
:legend,
|
46
|
+
:li,
|
47
|
+
:link,
|
48
|
+
:map,
|
49
|
+
:meta,
|
50
|
+
:noscript,
|
51
|
+
:object,
|
52
|
+
:ol,
|
53
|
+
:optgroup,
|
54
|
+
:option,
|
55
|
+
:p,
|
56
|
+
:param,
|
57
|
+
:pre,
|
58
|
+
:q,
|
59
|
+
:samp,
|
60
|
+
:script,
|
61
|
+
:select,
|
62
|
+
:small,
|
63
|
+
:span,
|
64
|
+
:strong,
|
65
|
+
:style,
|
66
|
+
:sub,
|
67
|
+
:sup,
|
68
|
+
:table,
|
69
|
+
:tbody,
|
70
|
+
:td,
|
71
|
+
:textarea,
|
72
|
+
:tfoot,
|
73
|
+
:th,
|
74
|
+
:thead,
|
75
|
+
:title,
|
76
|
+
:tr,
|
77
|
+
:tt,
|
78
|
+
:ul,
|
79
|
+
:var,
|
80
|
+
]
|
81
|
+
|
82
|
+
# define tag methods to delegate to selector_eval
|
83
|
+
methods = HTML_TAGS.map do |tag|
|
84
|
+
"def #{tag}(&block); selector_eval(@selector.first, '#{tag}', &block);end\n"
|
85
|
+
end.join
|
86
|
+
|
87
|
+
module_eval methods
|
88
|
+
|
89
|
+
end
|
data/misc/dan.cssy
ADDED
@@ -0,0 +1,160 @@
|
|
1
|
+
# # within a class
|
2
|
+
#
|
3
|
+
# class Widget
|
4
|
+
#
|
5
|
+
# # need this to get stylesheet methods
|
6
|
+
# include Cassandra
|
7
|
+
#
|
8
|
+
# # add in Grid Layout support
|
9
|
+
# include Cassandra::Grid
|
10
|
+
#
|
11
|
+
# # changes default units to 10 x 10 pixel blocks
|
12
|
+
# grid :columns => { :width => 10, :height => 10 }, :units => 'px'
|
13
|
+
#
|
14
|
+
# # define some reusable stuff
|
15
|
+
# def block ; display :block ; margin 0 ; padding 0 ; end
|
16
|
+
# def wrap ; clear :both ; end
|
17
|
+
# def left ; float :left ; end
|
18
|
+
# def dark ; color :gray ; end
|
19
|
+
# def style light ; color :silver ; end
|
20
|
+
# def large ; font :size => '13px' ; end
|
21
|
+
# def small ; font :size => '11px' ; end
|
22
|
+
#
|
23
|
+
# # generate a "CSS reset" and include some other stylesheets
|
24
|
+
# reset ; include Main ; include Products
|
25
|
+
#
|
26
|
+
# intro_text! / a.back do
|
27
|
+
# padding :top => 0, :left => 0, :bottom => 2, :right => 2
|
28
|
+
# font :weight => :bold ; background :url => '/images/icons-back.gif', :repeat => false
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# img.title { padding :bottom => 1 }
|
32
|
+
#
|
33
|
+
# div.wizard do
|
34
|
+
#
|
35
|
+
# left ; margin :right => 1
|
36
|
+
#
|
37
|
+
# ul.steps do
|
38
|
+
#
|
39
|
+
# block
|
40
|
+
#
|
41
|
+
# li.step do
|
42
|
+
# block ; display false;
|
43
|
+
# width 40 ; height 33.5
|
44
|
+
# margin :left => '2px' ; padding 1.5
|
45
|
+
# border '1px solid silver'
|
46
|
+
#
|
47
|
+
# add '.selected' { display :block }
|
48
|
+
#
|
49
|
+
# end
|
50
|
+
#
|
51
|
+
# end
|
52
|
+
#
|
53
|
+
# div.tab-selector span do
|
54
|
+
# dark ; small ; centered ; block ; left
|
55
|
+
# height 2.5 ; width 13 ; padding '12px 8px 0 8px' ; cursor :pointer
|
56
|
+
# background :url => '/images/tab/unselected.gif', :repeat => :x
|
57
|
+
# self & selected do
|
58
|
+
# font :weight => :bold ; color :black
|
59
|
+
# background :url => '/images/tab/selected.gif', :repeat => :x
|
60
|
+
# end
|
61
|
+
# end
|
62
|
+
#
|
63
|
+
# form do
|
64
|
+
#
|
65
|
+
# ul.properties do
|
66
|
+
#
|
67
|
+
# block
|
68
|
+
#
|
69
|
+
# li.property do
|
70
|
+
#
|
71
|
+
# block ; padding :bottom => 4
|
72
|
+
#
|
73
|
+
# label do
|
74
|
+
# block ; left ; dark ; large
|
75
|
+
# width 8 ; text_align :right
|
76
|
+
# padding :right => 2 ; font :weight => :bold
|
77
|
+
# end
|
78
|
+
#
|
79
|
+
# div.value { left ; dark }
|
80
|
+
#
|
81
|
+
# div.radio.value | div.checkbox.value do
|
82
|
+
# div.option do
|
83
|
+
# large ; padding :left => 2 ; height 2 ; cursor :pointer
|
84
|
+
# background :url => '/images/bt_radio_off.gif', :repeat => false
|
85
|
+
# end
|
86
|
+
# end
|
87
|
+
#
|
88
|
+
# div.text.value do
|
89
|
+
#
|
90
|
+
# small ; dark ; margin :top => '-4px'
|
91
|
+
#
|
92
|
+
# input do
|
93
|
+
# height 2 ; width 22 ; border false; background :url => '/images/textfield_bg.gif', :repeat => false
|
94
|
+
# padding 0.5 ; font :weight => :bold
|
95
|
+
# end
|
96
|
+
#
|
97
|
+
# textarea { width 28 ; height 18 }
|
98
|
+
#
|
99
|
+
# end
|
100
|
+
#
|
101
|
+
# end
|
102
|
+
#
|
103
|
+
# li.size.property do
|
104
|
+
#
|
105
|
+
# div.option do
|
106
|
+
# background :url => '/images/bt_radio_off.gif', :repeat => false
|
107
|
+
# padding :left => 2 ; height 2 ; large
|
108
|
+
#
|
109
|
+
# self & selected do
|
110
|
+
# background :url => '/images/bt_radio_on.gif', :repeat => false
|
111
|
+
# padding :left => 2 ; height 2 ; large
|
112
|
+
# end
|
113
|
+
#
|
114
|
+
# end
|
115
|
+
#
|
116
|
+
# end
|
117
|
+
#
|
118
|
+
# li.style.property do
|
119
|
+
#
|
120
|
+
# div.option do
|
121
|
+
# left ; border '1px solid silver' ; padding '1px' ; margin-left 0.5 ; opacity 0.5
|
122
|
+
# end
|
123
|
+
#
|
124
|
+
# div.option.hover | div.option.selected { border '1px solid gray' }
|
125
|
+
#
|
126
|
+
# div.option.selected { opacity 1.0 }
|
127
|
+
#
|
128
|
+
# end
|
129
|
+
#
|
130
|
+
# li.tos.property / div.option
|
131
|
+
# background :url => '/images/checkbox.gif', :repeat => false ; padding :left => 2
|
132
|
+
# end
|
133
|
+
#
|
134
|
+
# li.code.property { display false }
|
135
|
+
#
|
136
|
+
# end
|
137
|
+
#
|
138
|
+
# end
|
139
|
+
#
|
140
|
+
# end
|
141
|
+
#
|
142
|
+
# div.preview do
|
143
|
+
#
|
144
|
+
# left ; height 40
|
145
|
+
#
|
146
|
+
# iframe do
|
147
|
+
# block ; height 34 ; width 49 ; position :relative
|
148
|
+
# margin 0.5 ; padding :top => 3, :left => 0
|
149
|
+
# border '1px solid silver'
|
150
|
+
# end
|
151
|
+
#
|
152
|
+
# div.ac_results do
|
153
|
+
# padding 0.5 ; margin :top => 1
|
154
|
+
# border '1px solid silver' ; text_align :left ; dark
|
155
|
+
# background :color => :white ;
|
156
|
+
# end
|
157
|
+
#
|
158
|
+
# end
|
159
|
+
#
|
160
|
+
# end
|
data/misc/dan.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
# Experimental alternative from Dan Yoder
|
2
|
+
|
3
|
+
%w( rubygems functor ).each { |file| require file }
|
4
|
+
class CSS # :nodoc:
|
5
|
+
|
6
|
+
include Functor::Method
|
7
|
+
|
8
|
+
# Functor needs instance_exec, which needs instance_eval and send ...
|
9
|
+
METHODS = %w( class functor instance_eval instance_exec send __send__ __id__ )
|
10
|
+
instance_methods.each { |m| undef_method( m ) unless METHODS.include? m }
|
11
|
+
|
12
|
+
|
13
|
+
TAGS = %w( a abbr acronym address area b base bdo big blockquote body br button caption
|
14
|
+
cite code col colgroup dd del dfn div dl dt em fieldset form h1 h2 h3 h4 h5 h6 head hr
|
15
|
+
html i img input ins kbd label legend li link map meta noscript object ol optgroup option
|
16
|
+
p param pre q samp script select small span strong style sub sup table tbody td textarea
|
17
|
+
tfoot th thead title tr tt ul var _ )
|
18
|
+
ATTRS = %w( background border clear color display float font height letter_spacing
|
19
|
+
line-height list margin max outline padding text )
|
20
|
+
COMBINATORS = %w( + / > )
|
21
|
+
|
22
|
+
ROWS = %w( height top bottom ) ; COLS = %w( width left right )
|
23
|
+
|
24
|
+
def self.css( &block ) ; @start = block ; end
|
25
|
+
|
26
|
+
def render
|
27
|
+
__start ; instance_eval( &( self.class.module_eval { @start } ) )
|
28
|
+
@output.reverse.map { |sel, attrs| puts sel.inspect ; "#{sel.join('').strip} { #{attrs} }" }.join("\n")
|
29
|
+
end
|
30
|
+
|
31
|
+
def select( s )
|
32
|
+
selector = @selectors[-1].dup << s
|
33
|
+
@selectors << selector ; @buffers << @buffer
|
34
|
+
@buffer = '' ; yield ; @output << [ selector, @buffer ]
|
35
|
+
@selectors.pop ; @buffer = @buffers.pop
|
36
|
+
end
|
37
|
+
|
38
|
+
# grid support
|
39
|
+
def units ; 'px' ; end
|
40
|
+
def cols( n ) "#{n}#{units}" ; end
|
41
|
+
def rows( n ) "#{n}#{units}" ; end
|
42
|
+
|
43
|
+
def method_missing( name, *args, &block ) ; __process( name.to_s, args, block ) ; self ; end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def __start ; @output = [] ; @selectors = [ [] ] ; @selector = [] ; @buffers = [] ; @buffer = '' ; end
|
48
|
+
def __open( sel ) @selector << [ sel ] ; end
|
49
|
+
def __append( sel ) ( __open( sel ) if @selector.empty? ) or ( @selector[-1] << sel ) ; end
|
50
|
+
def __close( block ) s = @selector ; @selector = [] ; select( s, &block ) ; end
|
51
|
+
def __combine( op ) @output[-1][0][-1] << op ; end
|
52
|
+
|
53
|
+
functor( :__process, lambda { | name | ATTRS.include?( name ) }, Array, nil ) { | name, args, block | __attribute( name, *args ) }
|
54
|
+
functor( :__process, lambda { | name | TAGS.include?( name ) }, [], nil ) { | sel, args, block | __open( sel ) }
|
55
|
+
functor( :__process, lambda { | name | COMBINATORS.include?( name ) }, [], nil ) { | op, args, block | __combine( op ) }
|
56
|
+
functor( :__process, String, [], nil ) { | sel, args, block | __append( sel ) }
|
57
|
+
functor( :__process, lambda { | name | TAGS.include?( name ) }, [], Proc ) { | sel, args, block | __open( sel ) ; __close( block ) }
|
58
|
+
functor( :__process, String, [], Proc ) { | sel, args, block | __append( sel ) ; __close( block ) }
|
59
|
+
functor( :__attribute, String, String ) { | name, val | @buffer << "#{name}: #{val};" }
|
60
|
+
functor( :__attribute, lambda { | name | COLS.include?( name ) }, Integer ) { | name, val | __attribute( name, cols( val ) ) }
|
61
|
+
functor( :__attribute, lambda { | name | ROWS.include?( name ) }, Integer ) { | name, val | __attribute( name, rows( val ) ) }
|
62
|
+
functor( :__attribute, String, Hash ) { | name, vals | vals.each { | key, val | __attribute( "#{name}-#{key}", val ) } }
|
63
|
+
|
64
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
/* http://meyerweb.com/eric/tools/css/reset/ */
|
2
|
+
/* v1.0 | 20080212 */
|
3
|
+
|
4
|
+
html, body, div, span, applet, object, iframe,
|
5
|
+
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
6
|
+
a, abbr, acronym, address, big, cite, code,
|
7
|
+
del, dfn, em, font, img, ins, kbd, q, s, samp,
|
8
|
+
small, strike, strong, sub, sup, tt, var,
|
9
|
+
b, u, i, center,
|
10
|
+
dl, dt, dd, ol, ul, li,
|
11
|
+
fieldset, form, label, legend,
|
12
|
+
table, caption, tbody, tfoot, thead, tr, th, td {
|
13
|
+
margin: 0;
|
14
|
+
padding: 0;
|
15
|
+
border: 0;
|
16
|
+
outline: 0;
|
17
|
+
font-size: 100%;
|
18
|
+
vertical-align: baseline;
|
19
|
+
background: transparent;
|
20
|
+
}
|
21
|
+
body {
|
22
|
+
line-height: 1;
|
23
|
+
}
|
24
|
+
ol, ul {
|
25
|
+
list-style: none;
|
26
|
+
}
|
27
|
+
blockquote, q {
|
28
|
+
quotes: none;
|
29
|
+
}
|
30
|
+
blockquote:before, blockquote:after,
|
31
|
+
q:before, q:after {
|
32
|
+
content: '';
|
33
|
+
content: none;
|
34
|
+
}
|
35
|
+
|
36
|
+
/* remember to define focus styles! */
|
37
|
+
:focus {
|
38
|
+
outline: 0;
|
39
|
+
}
|
40
|
+
|
41
|
+
/* remember to highlight inserts somehow! */
|
42
|
+
ins {
|
43
|
+
text-decoration: none;
|
44
|
+
}
|
45
|
+
del {
|
46
|
+
text-decoration: line-through;
|
47
|
+
}
|
48
|
+
|
49
|
+
/* tables still need 'cellspacing="0"' in the markup */
|
50
|
+
table {
|
51
|
+
border-collapse: collapse;
|
52
|
+
border-spacing: 0;
|
53
|
+
}
|
data/site/basic.cssy
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
@full = "700px"
|
2
|
+
|
3
|
+
body { background_color "#F8F7F1"}
|
4
|
+
div.content! {
|
5
|
+
width @full; margin "25px auto"
|
6
|
+
|
7
|
+
h1 { color @default }
|
8
|
+
|
9
|
+
a {
|
10
|
+
color @default;
|
11
|
+
text_decoration :none
|
12
|
+
font_weight :bold
|
13
|
+
}
|
14
|
+
|
15
|
+
ul.links! { list_style "url(flower.png)" }
|
16
|
+
}
|
data/site/basic.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
css = Cssy.new.process do
|
2
|
+
|
3
|
+
@default = "#212F54"
|
4
|
+
|
5
|
+
body { background_color "#F8F7F1"}
|
6
|
+
div.content! {
|
7
|
+
width "700px"; margin "25px auto"
|
8
|
+
|
9
|
+
h1 { color @default }
|
10
|
+
|
11
|
+
a {
|
12
|
+
color @default;
|
13
|
+
text_decoration :none
|
14
|
+
font_weight :bold
|
15
|
+
}
|
16
|
+
|
17
|
+
ul.links! { list_style "url(flower.png)" }
|
18
|
+
}
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
css.to_s
|
data/site/cssy_title.jpg
ADDED
Binary file
|
data/site/flower.png
ADDED
Binary file
|
data/site/index.mab
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'syntax/convertors/html'
|
2
|
+
|
3
|
+
html do
|
4
|
+
head do
|
5
|
+
title "Cassandra: A CSS generator with a Ruby syntax"
|
6
|
+
link :rel => 'stylesheet', :type => 'text/css', :href => "basic.css"
|
7
|
+
link :rel => 'stylesheet', :type => 'text/css', :href => "ruby.css"
|
8
|
+
end
|
9
|
+
body do
|
10
|
+
div.content! do
|
11
|
+
img.logo! :src => "cssy_title.jpg"
|
12
|
+
div.ruby.example! do
|
13
|
+
example = <<TEXT
|
14
|
+
css = Cssy.new
|
15
|
+
css.process(:default => "#212F54") do
|
16
|
+
|
17
|
+
#{File.readlines( "site/basic.cssy").join(" ") }
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
css.to_s
|
22
|
+
TEXT
|
23
|
+
Syntax::Convertors::HTML.for_syntax("ruby").convert( example ).to_s
|
24
|
+
end
|
25
|
+
ul.links! do
|
26
|
+
li { a "GitHub", :href => "http://github.com/automatthew/cassandra" }
|
27
|
+
li { a "RDocs", :href => "/rdoc" }
|
28
|
+
li { a "Developer", :href => "http://www.automatthew.com" }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/site/ruby.cssy
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
div.ruby {
|
2
|
+
margin "30px 57px"
|
3
|
+
padding_left "20px"
|
4
|
+
border_left "3px solid #e8e7e1"
|
5
|
+
|
6
|
+
comment { color "#5A525F"; font_style :italic }
|
7
|
+
keyword { color "#794938" }
|
8
|
+
attribute { color "#234A97" }
|
9
|
+
constant { color "#691C97"; font_weight :bold }
|
10
|
+
method { color "#BF4F24" }
|
11
|
+
symbol { color "#811F24" }
|
12
|
+
string { color "#0B6125" }
|
13
|
+
ident { color "#080808" }
|
14
|
+
punct { color "#080808" }
|
15
|
+
}
|
data/test/assigns.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
here = File.dirname(__FILE__)
|
2
|
+
require "#{here}/helper"
|
3
|
+
|
4
|
+
describe "Assigns hash" do
|
5
|
+
|
6
|
+
it "becomes instance variables" do
|
7
|
+
assigns = { :width => "350px", :background => :red }
|
8
|
+
proc = lambda do
|
9
|
+
div do
|
10
|
+
form { width @width }
|
11
|
+
ul do
|
12
|
+
li { background @background }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
data = [
|
18
|
+
["div", []],
|
19
|
+
["div form", ["width: 350px;"]],
|
20
|
+
["div ul", []],
|
21
|
+
["div ul li", ["background: red;"]]
|
22
|
+
]
|
23
|
+
Cssy.process(assigns, &proc).data.should == data
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
data/test/basics.css
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
div {
|
2
|
+
background: red;
|
3
|
+
width: 9934px;
|
4
|
+
}
|
5
|
+
div ul li {
|
6
|
+
color: green;
|
7
|
+
}
|
8
|
+
div p.ugly.truly {
|
9
|
+
color: aqua;
|
10
|
+
}
|
11
|
+
div .smurf.house {
|
12
|
+
height: 256px;
|
13
|
+
}
|
14
|
+
div #menu {
|
15
|
+
padding: 10px;
|
16
|
+
}
|
17
|
+
.gargamel {
|
18
|
+
margin: 0px;
|
19
|
+
}
|
20
|
+
.outer.middle.inner {
|
21
|
+
top: 34px;
|
22
|
+
}
|
data/test/basics.cssy
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
|
2
|
+
div do
|
3
|
+
|
4
|
+
# this is a property on div
|
5
|
+
background :red
|
6
|
+
|
7
|
+
s('ul li') do
|
8
|
+
color('green')
|
9
|
+
end
|
10
|
+
|
11
|
+
p.ugly.truly do
|
12
|
+
color('aqua')
|
13
|
+
end
|
14
|
+
|
15
|
+
s('.smurf').house do
|
16
|
+
height('256px')
|
17
|
+
end
|
18
|
+
|
19
|
+
menu! do
|
20
|
+
padding("10px")
|
21
|
+
end
|
22
|
+
|
23
|
+
# this is a property on div, again
|
24
|
+
width('9934px')
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
gargamel do
|
29
|
+
margin("0px")
|
30
|
+
end
|
31
|
+
|
32
|
+
s('.outer.middle.inner') do
|
33
|
+
top("34px")
|
34
|
+
end
|
data/test/basics.rb
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
here = File.dirname(__FILE__)
|
2
|
+
require "#{here}/helper"
|
3
|
+
|
4
|
+
describe "Cassandra" do
|
5
|
+
|
6
|
+
it "can nest blocks" do
|
7
|
+
proc = lambda do
|
8
|
+
div do
|
9
|
+
form { width "35px" }
|
10
|
+
ul do
|
11
|
+
li { background :red }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
data = [
|
17
|
+
["div", []],
|
18
|
+
["div form", ["width: 35px;"]],
|
19
|
+
["div ul", []],
|
20
|
+
["div ul li", ["background: red;"]]
|
21
|
+
]
|
22
|
+
Cssy.process(&proc).data.should == data
|
23
|
+
end
|
24
|
+
|
25
|
+
it "can chain blocks" do
|
26
|
+
proc = lambda do
|
27
|
+
p.smurf { color :blue }
|
28
|
+
p.gnome.hat { color :red }
|
29
|
+
end
|
30
|
+
|
31
|
+
data = [
|
32
|
+
["p.smurf", [ "color: blue;"]],
|
33
|
+
["p.gnome.hat", ["color: red;"]]
|
34
|
+
]
|
35
|
+
Cssy.process(&proc).data.should == data
|
36
|
+
end
|
37
|
+
|
38
|
+
it "can nest and chain" do
|
39
|
+
proc = lambda do
|
40
|
+
div do
|
41
|
+
span.ugly { font_family "Arial" }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
data = [
|
46
|
+
["div", []],
|
47
|
+
["div span.ugly", ["font-family: Arial;"]]
|
48
|
+
]
|
49
|
+
Cssy.process(&proc).data.should == data
|
50
|
+
end
|
51
|
+
|
52
|
+
it "can chain and nest" do
|
53
|
+
proc = lambda do
|
54
|
+
ul.monkey do
|
55
|
+
li { list_style :none }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
data = [
|
60
|
+
["ul.monkey", []],
|
61
|
+
["ul.monkey li", ["list-style: none;"]]
|
62
|
+
]
|
63
|
+
Cssy.process(&proc).data.should == data
|
64
|
+
end
|
65
|
+
|
66
|
+
it "can chain and nest and chain and ..." do
|
67
|
+
proc = lambda do
|
68
|
+
div do
|
69
|
+
div.milk!.toast do
|
70
|
+
p.jam { margin :auto }
|
71
|
+
hr { background :green }
|
72
|
+
end
|
73
|
+
|
74
|
+
p { border :none }
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
data = [
|
79
|
+
["div", []],
|
80
|
+
["div div#milk.toast", []],
|
81
|
+
["div div#milk.toast p.jam", ["margin: auto;"]],
|
82
|
+
["div div#milk.toast hr", ["background: green;"]],
|
83
|
+
["div p", ["border: none;"]]
|
84
|
+
]
|
85
|
+
Cssy.process(&proc).data.should == data
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
it "processes strings" do
|
90
|
+
basics = [
|
91
|
+
["div", ["background: red;", "width: 9934px;"]],
|
92
|
+
["div ul li", ["color: green;"]],
|
93
|
+
["div p.ugly.truly", ["color: aqua;"]],
|
94
|
+
["div .smurf.house", ["height: 256px;"]],
|
95
|
+
["div #menu", ["padding: 10px;"]],
|
96
|
+
[".gargamel", ["margin: 0px;"]],
|
97
|
+
[".outer.middle.inner", ["top: 34px;"]]
|
98
|
+
]
|
99
|
+
c = Cssy.new
|
100
|
+
c.process(File.read( "#{here}/basics.cssy"))
|
101
|
+
c.data.should == basics
|
102
|
+
c.to_s.should == File.read( "#{here}/basics.css")
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
|
107
|
+
end
|
data/test/comments.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
here = File.dirname(__FILE__)
|
2
|
+
require "#{here}/helper"
|
3
|
+
|
4
|
+
describe "CSS comment method" do
|
5
|
+
|
6
|
+
it "can be applied at the property level" do
|
7
|
+
Cssy.process do
|
8
|
+
div do
|
9
|
+
ul do
|
10
|
+
li do
|
11
|
+
add_comment "What an ugly list!"
|
12
|
+
background :red
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end.to_s.should == <<-STRING
|
17
|
+
div ul li {
|
18
|
+
/* What an ugly list! */
|
19
|
+
background: red;
|
20
|
+
}
|
21
|
+
STRING
|
22
|
+
end
|
23
|
+
|
24
|
+
it "can be used in helper methods at property level" do
|
25
|
+
|
26
|
+
Cssy.process do
|
27
|
+
def red_comment; add_comment "What an ugly list!"; :red; end
|
28
|
+
|
29
|
+
div do
|
30
|
+
ul do
|
31
|
+
li do
|
32
|
+
background red_comment
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end.to_s.should == <<-STRING
|
37
|
+
div ul li {
|
38
|
+
/* What an ugly list! */
|
39
|
+
background: red;
|
40
|
+
}
|
41
|
+
STRING
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
data/test/helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: automatthew-cassandra
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Matthew King
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-09-30 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Generates CSS using Ruby, like Markaby
|
17
|
+
email: automatthew@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- lib/cassandra.rb
|
24
|
+
- lib/properties.rb
|
25
|
+
- lib/tags.rb
|
26
|
+
- README.rdoc
|
27
|
+
files:
|
28
|
+
- cassandra.gemspec
|
29
|
+
- lib/cassandra.rb
|
30
|
+
- lib/properties.rb
|
31
|
+
- lib/tags.rb
|
32
|
+
- Manifest
|
33
|
+
- misc/dan.cssy
|
34
|
+
- misc/dan.rb
|
35
|
+
- misc/meyer_reset.css
|
36
|
+
- README.rdoc
|
37
|
+
- site/basic.cssy
|
38
|
+
- site/basic.rb
|
39
|
+
- site/cssy_title.jpg
|
40
|
+
- site/flower.png
|
41
|
+
- site/index.mab
|
42
|
+
- site/ruby.cssy
|
43
|
+
- test/assigns.rb
|
44
|
+
- test/basics.css
|
45
|
+
- test/basics.cssy
|
46
|
+
- test/basics.rb
|
47
|
+
- test/comments.rb
|
48
|
+
- test/helper.rb
|
49
|
+
has_rdoc: true
|
50
|
+
homepage: ""
|
51
|
+
post_install_message:
|
52
|
+
rdoc_options:
|
53
|
+
- --line-numbers
|
54
|
+
- --inline-source
|
55
|
+
- --title
|
56
|
+
- Cassandra
|
57
|
+
- --main
|
58
|
+
- README.rdoc
|
59
|
+
require_paths:
|
60
|
+
- lib
|
61
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: "0"
|
66
|
+
version:
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: "0"
|
72
|
+
version:
|
73
|
+
requirements: []
|
74
|
+
|
75
|
+
rubyforge_project: cassandra
|
76
|
+
rubygems_version: 1.2.0
|
77
|
+
signing_key:
|
78
|
+
specification_version: 2
|
79
|
+
summary: Generates CSS using Ruby, like Markaby
|
80
|
+
test_files:
|
81
|
+
- test/assigns.rb
|
82
|
+
- test/basics.rb
|
83
|
+
- test/comments.rb
|
84
|
+
- test/helper.rb
|