shway 3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +11 -0
- data/Manifest +41 -0
- data/README +14 -0
- data/Rakefile +47 -0
- data/init.rb +2 -0
- data/install.rb +0 -0
- data/install_files/javascripts/iepngfix.htc +193 -0
- data/install_files/javascripts/iepngfix_tilebg.js +155 -0
- data/install_files/stylesheets/reset.css +47 -0
- data/install_files/templates/example_presenter.rb +12 -0
- data/install_files/templates/example_stylesheet.css.rb +20 -0
- data/lib/rubygems/commands/shway_init_command.rb +112 -0
- data/lib/rubygems_plugin.rb +3 -0
- data/lib/shway/controllers/shway_controller.rb +22 -0
- data/lib/shway/css/css_helper.rb +221 -0
- data/lib/shway/css/css_parser.rb +155 -0
- data/lib/shway/css/css_styles.rb +368 -0
- data/lib/shway/extensions/routing_extensions.rb +22 -0
- data/lib/shway/helpers/html_helper.rb +54 -0
- data/lib/shway/helpers/shway_controller_helper.rb +51 -0
- data/lib/shway/helpers/shway_helper.rb +187 -0
- data/lib/shway/presenters/shway_model_presenter.rb +10 -0
- data/lib/shway/presenters/shway_presenter.rb +184 -0
- data/lib/shway/test/shway_test_helper.rb +78 -0
- data/lib/shway.rb +129 -0
- data/shway.gemspec +31 -0
- data/templates/css.html.erb +3 -0
- data/templates/css.rhtml +3 -0
- data/test/shway_core/css_config_test.rb +186 -0
- data/test/shway_core/css_helper_test.rb +655 -0
- data/test/shway_core/css_parser_test.rb +219 -0
- data/test/shway_core/html_helper_test.rb +32 -0
- data/test/shway_core/shway_controller_test.rb +44 -0
- data/test/shway_core/shway_core_test_helper.rb +45 -0
- data/test/shway_core/shway_helper_test.rb +280 -0
- data/test/shway_core/shway_presenter_test.rb +173 -0
- data/test/shway_core/shway_routes_test.rb +31 -0
- data/test/shway_core/views/mock_foos/_list_header.html.erb +1 -0
- data/test/shway_core/views/mock_foos/_list_item.html.erb +5 -0
- data/test/shway_core/views/model_list/list_for_action.html.erb +1 -0
- data/test/shway_core/views/model_list/list_item_for_action.html.erb +1 -0
- data/test/shway_core/views/shway_helper_test.html.erb +24 -0
- metadata +123 -0
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
module Shway
|
|
2
|
+
|
|
3
|
+
module Css
|
|
4
|
+
|
|
5
|
+
module CssHelper
|
|
6
|
+
|
|
7
|
+
def self.included(mod)
|
|
8
|
+
# include Shway::Css
|
|
9
|
+
mod.send :include, Shway::Css
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.css_styles_from_namespace_stylesheet(stylesheet)
|
|
13
|
+
CssStyles.css_styles_from_namespace_stylesheet(stylesheet)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
#########################################
|
|
17
|
+
|
|
18
|
+
@@ALL_SIDES = %w{top right bottom left}
|
|
19
|
+
|
|
20
|
+
def link_styles(name, color=nil, styles=nil, hover_color=nil, hover_styles=nil, args={})
|
|
21
|
+
name = "#{name} a" unless name.strip == 'a'
|
|
22
|
+
normalize_params(args, :color => color, :styles => styles, :hover_color => hover_color, :hover_styles => hover_styles)
|
|
23
|
+
color = args[:color]# || 'black'
|
|
24
|
+
hover_color = args[:hover_color] || color
|
|
25
|
+
styles = args[:styles]
|
|
26
|
+
hover_styles = args[:hover_styles] || styles
|
|
27
|
+
html = []
|
|
28
|
+
[ {:name => "#{name}:link ", :color => color, :styles => styles, :decoration => 'none '},
|
|
29
|
+
{:name => "#{name}:visited", :color => color, :styles => styles, :decoration => 'none '},
|
|
30
|
+
{:name => "#{name}:active ", :color => hover_color, :styles => hover_styles, :decoration => 'underline'},
|
|
31
|
+
{:name => "#{name}:hover ", :color => hover_color, :styles => hover_styles, :decoration => 'underline'},
|
|
32
|
+
].each do |style|
|
|
33
|
+
color_style = color ? "color: #{style[:color]}" : ''
|
|
34
|
+
html << "#{style[:name]} {text-decoration: #{style[:decoration]};#{color_style};#{style[:styles]}}"
|
|
35
|
+
end
|
|
36
|
+
html = html.join
|
|
37
|
+
html
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
####################
|
|
41
|
+
#These methods are used for css generated in helpers
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
#TODO I think I can get rid of this ie6 stuff now.
|
|
45
|
+
def hashes_to_style_tag(ie6=false, ids_and_hashes=nil)
|
|
46
|
+
ids_and_hashes, ie6 = ie6, false if ie6.class == Hash #this is an interesting idiom for moving the args into the right vars
|
|
47
|
+
|
|
48
|
+
#convert all the keys to strings so we can sort by them. (apparently you cab't sort symbols)
|
|
49
|
+
new_ids_and_hashes = {}
|
|
50
|
+
ids_and_hashes.each do |key,value|
|
|
51
|
+
new_ids_and_hashes[key.to_s] = value
|
|
52
|
+
end
|
|
53
|
+
ids_and_hashes = new_ids_and_hashes
|
|
54
|
+
|
|
55
|
+
styletag = []
|
|
56
|
+
if ie6
|
|
57
|
+
styletag << '<!--[if lt IE 7]>'
|
|
58
|
+
end
|
|
59
|
+
styletag << '<style>'
|
|
60
|
+
ids_and_hashes.keys.sort.each do |id|
|
|
61
|
+
styletag << "##{id}{#{css_for_hash ids_and_hashes[id]}}"
|
|
62
|
+
end
|
|
63
|
+
styletag << '</style>'
|
|
64
|
+
if ie6
|
|
65
|
+
styletag << '<![endif]-->'
|
|
66
|
+
end
|
|
67
|
+
styletag.join
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def id_att(css_id)
|
|
71
|
+
html_att 'id', css_id
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def class_att(css_class)
|
|
75
|
+
html_att 'class', css_class
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def html_att(att_name, att_value)
|
|
79
|
+
%{#{att_name}="#{att_value}"} if att_value
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# you can supply an array or a string with space or comma delimiters
|
|
83
|
+
# it gets transformed into a comma separated list, ala the css selector syntax
|
|
84
|
+
# you can put ? symbols in the selectors and have them replaced with whatever you supply as the replace param
|
|
85
|
+
# eg: css_selectors "#?_content .?_nw .?_sw .?id .?_se .?_ne", 'test'
|
|
86
|
+
# yields "#test_content .test_nw .test_sw .testid .test_se .test_ne"
|
|
87
|
+
def self.css_selectors(selectors, replace=nil)
|
|
88
|
+
selectors = (selectors.collect{ |selector| selector.to_s}.join ',') if selectors.class == Array
|
|
89
|
+
selectors = selectors.split(' ').join(',')
|
|
90
|
+
selectors.gsub!('?', replace.to_s) if replace
|
|
91
|
+
selectors
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def css_for_hash(selectors=[], replace=nil, hash={})
|
|
95
|
+
Shway::Css::CssHelper.css_for_hash(selectors, replace, hash)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def self.css_for_hash(selectors=[], replace=nil, hash={})
|
|
99
|
+
shared_css_for_hash(false,:main,selectors,replace,hash)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def self.internal_css_for_hash(browser,selectors=[], replace=nil, hash={})
|
|
103
|
+
shared_css_for_hash(true,browser,selectors,replace,hash)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
#this should be private
|
|
107
|
+
def self.shared_css_for_hash(internal,browser,selectors=[], replace=nil, hash={})
|
|
108
|
+
#this will ignore any params that have nil values
|
|
109
|
+
if selectors.class == Hash
|
|
110
|
+
hash = selectors
|
|
111
|
+
selectors = nil
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
hash = hash.merge :use_style => nil
|
|
115
|
+
|
|
116
|
+
#disallow improper usage
|
|
117
|
+
unless internal
|
|
118
|
+
[:safari,:ie6,:ie7].each do |browser|
|
|
119
|
+
raise "Browser styles can only be defined using css_style, not with css_for_hash. (:#{browser})" unless hash[browser].blank?
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
raise "You can not set a value for :main in css hashes." if hash[:main]
|
|
123
|
+
raise "When generating css from a hash, :id and :class should NOT be set. (:id => #{hash[:id]}, :class => #{hash[:class]})" if hash[:id] || hash[:class]
|
|
124
|
+
|
|
125
|
+
raise "alpha_filter can only be specified fot css_style, not css_for_hash, since it is browser dependent. (#{name})" if hash[:alpha_filter]
|
|
126
|
+
|
|
127
|
+
#TODO: add a way to switch between versions. maybe development uses verbose/readable and the others use terse?
|
|
128
|
+
readable = RAILS_ENV == 'development' || RAILS_ENV == 'test'
|
|
129
|
+
|
|
130
|
+
css = []
|
|
131
|
+
|
|
132
|
+
#GOTCHA!! for styles like margin and padding, we need to sort everything alphabetically so you can set a margin, and then override just margin-top
|
|
133
|
+
hash.delete_if {|key, value| value.nil? }.sort{|a,b| a[0].to_s<=>b[0].to_s}.each do |key,values|
|
|
134
|
+
#process all values as arrays so that the ones that are arrays can be handled as well
|
|
135
|
+
values = [values] unless values.kind_of? Array
|
|
136
|
+
processed_values = []
|
|
137
|
+
values.each do |value|
|
|
138
|
+
#lookup the css_value if it's a symbol
|
|
139
|
+
#GOTCHA TODO should I just always just return this as a string
|
|
140
|
+
value = Shway::Css::CssStyles.get_css_value(value).to_s if value.kind_of? Symbol
|
|
141
|
+
#this is where we process things and add px, etc.
|
|
142
|
+
begin
|
|
143
|
+
#NOTE: need to set some styles, like z-index to NOT append 'px'
|
|
144
|
+
raise 'escape' if %w{z_index}.include? key.to_s
|
|
145
|
+
Integer(value)
|
|
146
|
+
processed_values << "#{value.to_s}px"
|
|
147
|
+
rescue
|
|
148
|
+
processed_values << value
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
css << "#{key.to_s.dasherize}:#{processed_values.join(' ')};"
|
|
152
|
+
end
|
|
153
|
+
styles = readable ? " #{css.join("\n ")}" : css.join
|
|
154
|
+
styles.strip!
|
|
155
|
+
styles = nil if styles.blank?
|
|
156
|
+
return styles unless selectors
|
|
157
|
+
|
|
158
|
+
selectors = css_selectors(selectors, replace)
|
|
159
|
+
|
|
160
|
+
if readable
|
|
161
|
+
ret = []
|
|
162
|
+
ret << "#{selectors} {"
|
|
163
|
+
ret << "#{styles}"
|
|
164
|
+
ret << "}"
|
|
165
|
+
ret << ""
|
|
166
|
+
ret.join "\n"
|
|
167
|
+
else
|
|
168
|
+
"#{selectors}{#{styles}}"
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def style_tag_for_ie6_css(*args)
|
|
174
|
+
style_tag_for_css_shared true, *args
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def style_tag_for_css(*args)
|
|
178
|
+
style_tag_for_css_shared false, *args
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def style_tag_for_css_shared(ie6=false, *args)
|
|
182
|
+
args.collect! do |css|
|
|
183
|
+
css.class == Array ? css_for_hash(*css) : css
|
|
184
|
+
end
|
|
185
|
+
css = css_for_hashes *args
|
|
186
|
+
if ie6
|
|
187
|
+
"<!--[if lt IE 7]><style>#{css}</style><![endif]-->"
|
|
188
|
+
else
|
|
189
|
+
"<style>#{css}</style>"
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def css_for_hashes(*args)
|
|
194
|
+
args.collect! do |css|
|
|
195
|
+
css.class == Array ? css_for_hash(*css) : css
|
|
196
|
+
end
|
|
197
|
+
args.join
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def expand_css_array(array)
|
|
201
|
+
array = [array] unless array.kind_of? Array
|
|
202
|
+
array = case array.size
|
|
203
|
+
when 4
|
|
204
|
+
array
|
|
205
|
+
when 1
|
|
206
|
+
[array.first,array.first,array.first,array.first]
|
|
207
|
+
when 2
|
|
208
|
+
[array.first,array.last,array.first,array.last]
|
|
209
|
+
when 3
|
|
210
|
+
[array[0],array[1],array[2],array[1]]
|
|
211
|
+
else
|
|
212
|
+
[array[0],array[1],array[2],array[3]]
|
|
213
|
+
end
|
|
214
|
+
array
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
end
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
module Shway
|
|
2
|
+
|
|
3
|
+
module Css
|
|
4
|
+
|
|
5
|
+
# rule : P { font-size: 10pt }
|
|
6
|
+
class CssRule
|
|
7
|
+
|
|
8
|
+
attr_accessor :selectors, :declarations
|
|
9
|
+
|
|
10
|
+
CSS_RULES_REGEX = /([^{]*\{[^}]*\})/m #this gets a full rule, including the selectors and declaration, with braces
|
|
11
|
+
def self.parse_all(rules_string)
|
|
12
|
+
rules = []
|
|
13
|
+
rule_strings = rules_string.scan CSS_RULES_REGEX
|
|
14
|
+
rule_strings.collect(&:first).each do |rule_string|
|
|
15
|
+
rule = CssRule.parse(rule_string)
|
|
16
|
+
rules << rule if rule
|
|
17
|
+
end
|
|
18
|
+
rules
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
CSS_RULE_REGEX = /([^{]*)\{([^}]*)\}/m #this gets the selectors and the declarations from a single rule.
|
|
22
|
+
def self.parse(rule_string)
|
|
23
|
+
selectors_and_declarations_strings = rule_string.scan CSS_RULE_REGEX
|
|
24
|
+
raise "The rule_string supplied appears to have multiple rules in it, and it should only have one. (#{rule_string})" if selectors_and_declarations_strings.size > 1
|
|
25
|
+
raise "The rule_string does not appear to contain a rule. (#{rule_string})" if selectors_and_declarations_strings.first.size < 2
|
|
26
|
+
|
|
27
|
+
selectors_string, declarations_string = selectors_and_declarations_strings.first
|
|
28
|
+
selectors = CssSelector.parse_all(selectors_string)
|
|
29
|
+
declarations = CssDeclaration.parse_all(declarations_string)
|
|
30
|
+
CssRule.new selectors, declarations
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def initialize(selectors=nil,declarations=nil)
|
|
34
|
+
raise "CssRule selectors cannot be empty." if selectors.blank?
|
|
35
|
+
raise "CssRule declarations cannot be empty." if declarations.blank?
|
|
36
|
+
@selectors = selectors if selectors
|
|
37
|
+
@declarations = declarations if declarations
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def to_s
|
|
41
|
+
"#{selectors.join(',')}{#{declarations.join(';')};}"
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
end #CssRule
|
|
46
|
+
|
|
47
|
+
# selector : P
|
|
48
|
+
class CssSelector
|
|
49
|
+
|
|
50
|
+
attr_accessor :pattern
|
|
51
|
+
|
|
52
|
+
CSS_SELECTOR_REGEX = /[{};,]/
|
|
53
|
+
|
|
54
|
+
def self.parse(selector_string)
|
|
55
|
+
CssSelector.new(selector_string)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def self.parse_all(selectors_string)
|
|
59
|
+
selectors = []
|
|
60
|
+
selectors_string.split(',').each do |selector_string|
|
|
61
|
+
selector = CssSelector.parse selector_string
|
|
62
|
+
selectors << selector if selector
|
|
63
|
+
end
|
|
64
|
+
selectors
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def initialize(pattern=nil)
|
|
68
|
+
raise "CssSelector patterns cannot be nil." if pattern.blank?
|
|
69
|
+
raise "CssSelector patterns cannot contain curly braces, semi-colons or commas (#{pattern})" unless (pattern =~ CSS_SELECTOR_REGEX).nil?
|
|
70
|
+
@pattern = pattern.strip if pattern
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def to_s
|
|
74
|
+
pattern || ''
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
end #CssSelector
|
|
78
|
+
|
|
79
|
+
# declaration : { font-size: 10pt }
|
|
80
|
+
class CssDeclaration
|
|
81
|
+
|
|
82
|
+
attr_accessor :property, :value
|
|
83
|
+
|
|
84
|
+
def self.parse(declaration_string)
|
|
85
|
+
property_string, value_string = declaration_string.strip.split(':').collect{|s|s.strip}
|
|
86
|
+
return nil if property_string.blank? && value_string.blank?
|
|
87
|
+
CssDeclaration.new(CssProperty.parse(property_string), CssValue.parse(value_string))
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def self.parse_all(declarations_string)
|
|
91
|
+
declarations = []
|
|
92
|
+
declarations_string.split(';').each do |declaration_string|
|
|
93
|
+
declaration = CssDeclaration.parse declaration_string
|
|
94
|
+
declarations << declaration if declaration
|
|
95
|
+
end
|
|
96
|
+
declarations
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def initialize(property=nil, value=nil)
|
|
100
|
+
@property = property if property
|
|
101
|
+
@value = value if value
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def to_s
|
|
105
|
+
"#{property.name}:#{value.value}"
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
end #CssDeclaration
|
|
109
|
+
|
|
110
|
+
# property : font-size
|
|
111
|
+
class CssProperty
|
|
112
|
+
|
|
113
|
+
attr_accessor :name
|
|
114
|
+
|
|
115
|
+
CSS_PROPERTY_REGEX = /[^-a-z]/
|
|
116
|
+
|
|
117
|
+
def self.parse(property_string)
|
|
118
|
+
CssProperty.new(property_string)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def initialize(name=nil)
|
|
122
|
+
raise "CssProperty names cannot be nil." if name.blank?
|
|
123
|
+
raise "CssProperty names must contain only lower case letters and hyphens (#{name})" unless (name =~ CSS_PROPERTY_REGEX).nil?
|
|
124
|
+
@name = name.strip if name
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def to_s
|
|
128
|
+
name || ''
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
end #CssProperty
|
|
132
|
+
|
|
133
|
+
# value : 10pt
|
|
134
|
+
class CssValue
|
|
135
|
+
|
|
136
|
+
attr_accessor :value
|
|
137
|
+
|
|
138
|
+
def self.parse(value_string)
|
|
139
|
+
CssValue.new(value_string)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def initialize(value=nil)
|
|
143
|
+
@value = value.strip if value
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def to_s
|
|
147
|
+
value || ''
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
end #CssValue
|
|
151
|
+
|
|
152
|
+
end #Css
|
|
153
|
+
|
|
154
|
+
end #Shway
|
|
155
|
+
|