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.
Files changed (43) hide show
  1. data/CHANGELOG +11 -0
  2. data/Manifest +41 -0
  3. data/README +14 -0
  4. data/Rakefile +47 -0
  5. data/init.rb +2 -0
  6. data/install.rb +0 -0
  7. data/install_files/javascripts/iepngfix.htc +193 -0
  8. data/install_files/javascripts/iepngfix_tilebg.js +155 -0
  9. data/install_files/stylesheets/reset.css +47 -0
  10. data/install_files/templates/example_presenter.rb +12 -0
  11. data/install_files/templates/example_stylesheet.css.rb +20 -0
  12. data/lib/rubygems/commands/shway_init_command.rb +112 -0
  13. data/lib/rubygems_plugin.rb +3 -0
  14. data/lib/shway/controllers/shway_controller.rb +22 -0
  15. data/lib/shway/css/css_helper.rb +221 -0
  16. data/lib/shway/css/css_parser.rb +155 -0
  17. data/lib/shway/css/css_styles.rb +368 -0
  18. data/lib/shway/extensions/routing_extensions.rb +22 -0
  19. data/lib/shway/helpers/html_helper.rb +54 -0
  20. data/lib/shway/helpers/shway_controller_helper.rb +51 -0
  21. data/lib/shway/helpers/shway_helper.rb +187 -0
  22. data/lib/shway/presenters/shway_model_presenter.rb +10 -0
  23. data/lib/shway/presenters/shway_presenter.rb +184 -0
  24. data/lib/shway/test/shway_test_helper.rb +78 -0
  25. data/lib/shway.rb +129 -0
  26. data/shway.gemspec +31 -0
  27. data/templates/css.html.erb +3 -0
  28. data/templates/css.rhtml +3 -0
  29. data/test/shway_core/css_config_test.rb +186 -0
  30. data/test/shway_core/css_helper_test.rb +655 -0
  31. data/test/shway_core/css_parser_test.rb +219 -0
  32. data/test/shway_core/html_helper_test.rb +32 -0
  33. data/test/shway_core/shway_controller_test.rb +44 -0
  34. data/test/shway_core/shway_core_test_helper.rb +45 -0
  35. data/test/shway_core/shway_helper_test.rb +280 -0
  36. data/test/shway_core/shway_presenter_test.rb +173 -0
  37. data/test/shway_core/shway_routes_test.rb +31 -0
  38. data/test/shway_core/views/mock_foos/_list_header.html.erb +1 -0
  39. data/test/shway_core/views/mock_foos/_list_item.html.erb +5 -0
  40. data/test/shway_core/views/model_list/list_for_action.html.erb +1 -0
  41. data/test/shway_core/views/model_list/list_item_for_action.html.erb +1 -0
  42. data/test/shway_core/views/shway_helper_test.html.erb +24 -0
  43. 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
+