any_view 0.1.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 (52) hide show
  1. data/.document +5 -0
  2. data/.gitignore +21 -0
  3. data/LICENSE +47 -0
  4. data/README.rdoc +369 -0
  5. data/Rakefile +57 -0
  6. data/lib/any_view/asset_tag_helpers.rb +103 -0
  7. data/lib/any_view/core_ext/array.rb +7 -0
  8. data/lib/any_view/core_ext/hash.rb +41 -0
  9. data/lib/any_view/core_ext/string.rb +17 -0
  10. data/lib/any_view/form_builder/abstract_form_builder.rb +128 -0
  11. data/lib/any_view/form_builder/standard_form_builder.rb +37 -0
  12. data/lib/any_view/form_helpers.rb +217 -0
  13. data/lib/any_view/format_helpers.rb +49 -0
  14. data/lib/any_view/tag_helpers.rb +47 -0
  15. data/lib/any_view/tilt_base.rb +94 -0
  16. data/lib/any_view.rb +30 -0
  17. data/test/fixtures/basic_form_for.erb +3 -0
  18. data/test/fixtures/builder_type_form_for.erb +3 -0
  19. data/test/fixtures/capture_concat.erb +14 -0
  20. data/test/fixtures/capture_concat.haml +13 -0
  21. data/test/fixtures/content_for.erb +11 -0
  22. data/test/fixtures/content_for.haml +9 -0
  23. data/test/fixtures/content_tag.erb +11 -0
  24. data/test/fixtures/content_tag.haml +9 -0
  25. data/test/fixtures/delete_form_for.erb +3 -0
  26. data/test/fixtures/field_set_tag.erb +3 -0
  27. data/test/fixtures/fields_for.erb +8 -0
  28. data/test/fixtures/fields_for.haml +6 -0
  29. data/test/fixtures/fields_for_basic.erb +3 -0
  30. data/test/fixtures/fields_for_nil.erb +3 -0
  31. data/test/fixtures/form_for.erb +56 -0
  32. data/test/fixtures/form_for.haml +47 -0
  33. data/test/fixtures/form_for_nil.erb +3 -0
  34. data/test/fixtures/form_tag.erb +57 -0
  35. data/test/fixtures/form_tag.haml +45 -0
  36. data/test/fixtures/form_tag_methods.erb +19 -0
  37. data/test/fixtures/form_tag_methods.haml +15 -0
  38. data/test/fixtures/link_to.erb +5 -0
  39. data/test/fixtures/link_to.haml +4 -0
  40. data/test/fixtures/mail_to.erb +3 -0
  41. data/test/fixtures/mail_to.haml +3 -0
  42. data/test/fixtures/multipart.erb +12 -0
  43. data/test/fixtures/multipart_form_for.erb +3 -0
  44. data/test/fixtures/put_form_for.erb +3 -0
  45. data/test/fixtures/standard_form_builder.erb +3 -0
  46. data/test/helper.rb +121 -0
  47. data/test/test_asset_tag_helpers.rb +176 -0
  48. data/test/test_form_builder.rb +607 -0
  49. data/test/test_form_helpers.rb +453 -0
  50. data/test/test_format_helpers.rb +59 -0
  51. data/test/test_tag_helpers.rb +65 -0
  52. metadata +160 -0
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,47 @@
1
+ Copyright (c) 2009 Daniel Neighman
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ This software is hevily based on the Pardino framework helpers and as such is bound by it's licence agreement reproduced below.
23
+
24
+ ------------------------------------------------------------------------
25
+
26
+ Copyright (c) 2009 Padrino
27
+
28
+ Permission is hereby granted, free of charge, to any person obtaining
29
+ a copy of this software and associated documentation files (the
30
+ "Software"), to deal in the Software without restriction, including
31
+ without limitation the rights to use, copy, modify, merge, publish,
32
+ distribute, sublicense, and/or sell copies of the Software, and to
33
+ permit persons to whom the Software is furnished to do so, subject to
34
+ the following conditions:
35
+
36
+ The above copyright notice and this permission notice shall be
37
+ included in all copies or substantial portions of the Software.
38
+
39
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
40
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
41
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
42
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
43
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
44
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
45
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
46
+
47
+
data/README.rdoc ADDED
@@ -0,0 +1,369 @@
1
+ = AnyView
2
+
3
+ The AnyView gem provides helpers for common web related view rendering. The AnyView gem is a collection of mixins that work together to provide tags, forms asset paths and more. AnyView is based heavily on the Padrino framework helpers module.
4
+
5
+ The requirements of AnyView are kept very small. There's two required methods inside your view context.
6
+
7
+ capture_content(*args, &block)
8
+
9
+ and
10
+
11
+ concat_content(string, opts ={})
12
+
13
+ By implementing these two methods on your view context, you're able to get just about all the view helpers in anyview including form_for helpers.
14
+
15
+ == Installation
16
+
17
+ $ sudo gem install any_view
18
+
19
+ This will install the required gems. Next, simply include the AnyView module into your view context
20
+
21
+ class ViewContext
22
+ include AnyView
23
+ end
24
+
25
+ If you're using Tilt, then AnyView can provide the capture_content and concat_content helpers too. These will work for erubis, erb and haml templates.
26
+
27
+ class ViewContext
28
+ include AnyView::TiltBase
29
+ include AnyView
30
+ end
31
+
32
+ A full setup for a custom class, including rendering the tilt templates might look like this:
33
+
34
+ class Renderer
35
+ def self.path
36
+ @path ||= File.expand_path(~'./views')
37
+ end
38
+
39
+ def self.template(name)
40
+ @templates ||= {}
41
+ @templates[name] ||= Tilt.new(File.join(path, name))
42
+ @templates[name]
43
+ end
44
+
45
+ def template(name)
46
+ self.class.template(name)
47
+ end
48
+
49
+ def render(name, locals = {})
50
+ template(name).render(ViewContext.new, locals)
51
+ end
52
+ end
53
+
54
+
55
+ Usage would be as simple as
56
+ Renderer.new.render("my_template.erb")
57
+
58
+ == Usage
59
+
60
+ === Tag Helpers
61
+
62
+ Tag helpers are the basic building blocks used to construct html 'tags' within a view template. There
63
+ are three major functions for this category: <tt>tag</tt>, <tt>content_tag</tt> and <tt>input_tag</tt>.
64
+
65
+ The tag and content_tag are for building arbitrary html tags with a name and specified options. If
66
+ the tag contains 'content' within then <tt>content_tag</tt> is used. For example:
67
+
68
+ tag(:br, :style => ‘clear:both’) => <br style="clear:both" />
69
+ content_tag(:p, "demo", :class => ‘light’) => <p class="light">demo</p>
70
+
71
+ The input_tag is used to build tags that are related to accepting input from the user:
72
+
73
+ input_tag :text, :class => "demo" => <input type='text' class='demo' />
74
+ input_tag :password, :value => "secret", :class => "demo"
75
+
76
+ Note that all of these accept html options and result in returning a string containing html tags.
77
+
78
+ The list of defined helpers in the 'tag helpers' category:
79
+
80
+ * <tt>tag(name, options={})</tt>
81
+ * Creates an html tag with the given name and options
82
+ * <tt>tag(:br, :style => 'clear:both')</tt> => <br style="clear:both" />
83
+ * <tt>tag(:p, :content => "demo", :class => 'large')</tt> => <p class="large">demo</p>
84
+ * <tt>content_tag(name, content, options={})</tt>
85
+ * Creates an html tag with given name, content and options
86
+ * <tt>content_tag(:p, "demo", :class => 'light')</tt> => <p class="light">demo</p>
87
+ * <tt>content_tag(:p, :class => 'dark') { ...content... }</tt> => <p class="dark">...content...</p>
88
+ * <tt>input_tag(type, options = {})</tt>
89
+ * Creates an html input field with given type and options
90
+ * <tt>input_tag :text, :class => "demo"</tt>
91
+ * <tt>input_tag :password, :value => "secret", :class => "demo"</tt>
92
+
93
+ === Asset Helpers
94
+
95
+ Asset helpers are intended to help insert useful html onto a view template such as stylesheet link tags ,
96
+ hyperlinks, mail_to links, images, stylesheets and javascript. An example of their uses would be on a
97
+ simple view template:
98
+
99
+ # app/views/example.haml
100
+ ...
101
+ %head
102
+ = stylesheet_link_tag 'layout'
103
+ = javascript_include_tag 'application'
104
+ %body
105
+ ...
106
+ %p= link_to 'Blog', '/blog', :class => 'example'
107
+ %p Mail me at #{mail_to 'fake@faker.com', "Fake Email Link", :cc => "test@demo.com"}
108
+ %p= image_tag 'padrino.png', :width => '35', :class => 'logo'
109
+
110
+ The list of defined helpers in the 'asset helpers' category:
111
+
112
+ * <tt>link_to(*args, &block)</tt>
113
+ * Creates a link element with given name, url and options
114
+ * <tt>link_to 'click me', '/dashboard', :class => 'linky'</tt>
115
+ * <tt>link_to('/dashboard', :class => 'blocky') { ...content... }</tt>
116
+ * <tt>mail_to(email, caption=nil, mail_options={})</tt>
117
+ * Creates a mailto link tag to the specified email_address
118
+ * <tt>mail_to "me@demo.com"</tt>
119
+ * <tt>mail_to "me@demo.com", "My Email", :subject => "Feedback", :cc => 'test@demo.com'</tt>
120
+ * <tt>image_tag(url, options={})</tt>
121
+ * Creates an image element with given url and options
122
+ * <tt>image_tag('icons/avatar.png')</tt>
123
+ * <tt>stylesheet_link_tag(*sources)</tt>
124
+ * Returns a stylesheet link tag for the sources specified as arguments
125
+ * <tt>stylesheet_link_tag 'style', 'application', 'layout'</tt>
126
+ * <tt>javascript_include_tag(*sources)</tt>
127
+ * Returns an html script tag for each of the sources provided.
128
+ * <tt>javascript_include_tag 'application', 'special'</tt>
129
+
130
+ To make use of these in a situation where you're application is in a mounted url space, you should include a method +uri_root+ in your view_context. This allows you to put a uri prifix on the "/stylesheets/my_style.css" relative url
131
+
132
+ === Form Helpers
133
+
134
+ Form helpers are the 'standard' form tag helpers you would come to expect when building forms. A simple
135
+ example of constructing a non-object form would be:
136
+
137
+ - form_tag '/destroy', :class => 'destroy-form', :method => :delete do
138
+ - field_set_tag do
139
+ %p
140
+ = label_tag :username, :class => 'first'
141
+ = text_field_tag :username, :value => params[:username]
142
+ %p
143
+ = label_tag :password, :class => 'first'
144
+ = password_field_tag :password, :value => params[:password]
145
+ %p
146
+ = label_tag :strategy
147
+ = select_tag :strategy, :options => ['delete', 'destroy'], :selected => 'delete'
148
+ %p
149
+ = check_box_tag :confirm_delete
150
+ - field_set_tag(:class => 'buttons') do
151
+ = submit_tag "Remove"
152
+
153
+ The list of defined helpers in the 'form helpers' category:
154
+
155
+ * <tt>form_tag(url, options={}, &block)</tt>
156
+ * Constructs a form without object based on options
157
+ * Supports form methods 'put' and 'delete' through hidden field
158
+ * <tt>form_tag('/register', :class => 'example') { ... }</tt>
159
+ * <tt>field_set_tag(*args, &block)</tt>
160
+ * Constructs a field_set to group fields with given options
161
+ * <tt>field_set_tag(:class => 'office-set') { }</tt>
162
+ * <tt>field_set_tag("Office", :class => 'office-set') { }</tt>
163
+ * <tt>error_messages_for(record, options={})</tt>
164
+ * Constructs list html for the errors for a given object
165
+ * <tt>error_messages_for @user</tt>
166
+ * <tt>label_tag(name, options={}, &block)</tt>
167
+ * Constructs a label tag from the given options
168
+ * <tt>label_tag :username, :class => 'long-label'</tt>
169
+ * <tt>label_tag(:username, :class => 'blocked-label') { ... }</tt>
170
+ * <tt>hidden_field_tag(name, options={})</tt>
171
+ * Constructs a hidden field input from the given options
172
+ * <tt>hidden_field_tag :session_key, :value => 'secret'</tt>
173
+ * <tt>text_field_tag(name, options={})</tt>
174
+ * Constructs a text field input from the given options
175
+ * <tt>text_field_tag :username, :class => 'long'</tt>
176
+ * <tt>text_area_tag(name, options={})</tt>
177
+ * Constructs a text area input from the given options
178
+ * <tt>text_area_tag :username, :class => 'long'</tt>
179
+ * <tt>password_field_tag(name, options={})</tt>
180
+ * Constructs a password field input from the given options
181
+ * <tt>password_field_tag :password, :class => 'long'</tt>
182
+ * <tt>check_box_tag(name, options={})</tt>
183
+ * Constructs a checkbox input from the given options
184
+ * <tt>check_box_tag :remember_me, :checked => true</tt>
185
+ * <tt>radio_button_tag(name, options={})</tt>
186
+ * Constructs a radio button input from the given options
187
+ * <tt>radio_button_tag :gender, :value => 'male'</tt>
188
+ * <tt>select_tag(name, settings={})</tt>
189
+ * Constructs a select tag with options from the given settings
190
+ * <tt>select_tag(:favorite_color, :options => ['1', '2', '3'], :selected => '1')</tt>
191
+ * <tt>select_tag(:more_color, :options => [['label', '1'], ['label2', '2']])</tt>
192
+ * <tt>select_tag(:multiple_color, :options => [...], :multiple => true)</tt>
193
+ * <tt>file_field_tag(name, options={})</tt>
194
+ * Constructs a file field input from the given options
195
+ * <tt>file_field_tag :photo, :class => 'long'</tt>
196
+ * <tt>submit_tag(caption, options={})</tt>
197
+ * Constructs a submit button from the given options
198
+ * <tt>submit_tag "Create", :class => 'success'</tt>
199
+ * <tt>button_tag(caption, options={})</tt>
200
+ * Constructs an input (type => 'button') from the given options
201
+ * <tt>button_tag "Cancel", :class => 'clear'</tt>
202
+ * <tt>image_submit_tag(source, options={})</tt>
203
+ * Constructs an image submit button from the given options
204
+ * <tt>image_submit_tag "submit.png", :class => 'success'</tt>
205
+
206
+ === FormBuilders
207
+
208
+ Form builders are full-featured objects allowing the construction of complex object-based forms
209
+ using a simple, intuitive syntax.
210
+
211
+ A form_for using these basic fields might look like:
212
+
213
+ - form_for @user, '/register', :id => 'register' do |f|
214
+ = f.error_messages
215
+ %p
216
+ = f.label :username, :caption => "Nickname"
217
+ = f.text_field :username
218
+ %p
219
+ = f.label :email
220
+ = f.text_field :email
221
+ %p
222
+ = f.label :password
223
+ = f.password_field :password
224
+ %p
225
+ = f.label :is_admin, :caption => "Admin User?"
226
+ = f.check_box :is_admin
227
+ %p
228
+ = f.label :color, :caption => "Favorite Color?"
229
+ = f.select :color, :options => ['red', 'black']
230
+ %p
231
+ - fields_for @user.location do |location|
232
+ = location.text_field :street
233
+ = location.text_field :city
234
+ %p
235
+ = f.submit "Create", :class => 'button'
236
+
237
+ The list of defined helpers in the 'form builders' category:
238
+
239
+ * <tt>form_for(object, url, settings={}, &block)</tt>
240
+ * Constructs a form using given or default form_builder
241
+ * Supports form methods 'put' and 'delete' through hidden field
242
+ * Defaults to StandardFormBuilder but you can easily create your own!
243
+ * <tt>form_for(@user, '/register', :id => 'register') { |f| ...field-elements... }</tt>
244
+ * <tt>fields_for(object, settings={}, &block)</tt>
245
+ * Constructs fields for a given object for use in an existing form
246
+ * Defaults to StandardFormBuilder but you can easily create your own!
247
+ * <tt>fields_for @user.assignment do |assignment| ... end</tt>
248
+ * <tt>fields_for :assignment do |assigment| ... end</tt>
249
+
250
+ The following are fields provided by AbstractFormBuilder that can be used within a form_for or fields_for:
251
+
252
+ * <tt>error_messages(options={})</tt>
253
+ * Displays list html for the errors on form object
254
+ * <tt>f.errors_messages</tt>
255
+ * <tt>label(field, options={})</tt>
256
+ * <tt>f.label :name, :class => 'long'</tt>
257
+ * <tt>text_field(field, options={})</tt>
258
+ * <tt>f.text_field :username, :class => 'long'</tt>
259
+ * <tt>check_box(field, options={})</tt>
260
+ * Uses hidden field to provide a 'unchecked' value for field
261
+ * <tt>f.check_box :remember_me, :uncheck_value => 'false'</tt>
262
+ * <tt>radio_button(field, options={})</tt>
263
+ * <tt>f.radio_button :gender, :value => 'male'</tt>
264
+ * <tt>hidden_field(field, options={})</tt>
265
+ * <tt>f.hidden_field :session_id, :class => 'hidden'</tt>
266
+ * <tt>text_area(field, options={})</tt>
267
+ * <tt>f.text_area :summary, :class => 'long'</tt>
268
+ * <tt>password_field(field, options={})</tt>
269
+ * <tt>f.password_field :secret, :class => 'long'</tt>
270
+ * <tt>file_field(field, options={})</tt>
271
+ * <tt>f.file_field :photo, :class => 'long'</tt>
272
+ * <tt>select(field, options={})</tt>
273
+ * <tt>f.select(:state, :options => ['California', 'Texas', 'Wyoming'])</tt>
274
+ * <tt>f.select(:state, :collection => @states, :fields => [:name, :id])</tt>
275
+ * <tt>f.select(:state, :options => [...], :include_blank => true)</tt>
276
+ * <tt>submit(caption, options={})</tt>
277
+ * <tt>f.submit "Update", :class => 'long'</tt>
278
+ * <tt>image_submit(source, options={})</tt>
279
+ * <tt>f.image_submit "submit.png", :class => 'long'</tt>
280
+
281
+ There is also an additional StandardFormBuilder which builds on the abstract fields that can be used within a form_for.
282
+
283
+ A form_for using these standard fields might be:
284
+
285
+ - form_for @user, '/register', :id => 'register' do |f|
286
+ = f.error_messages
287
+ = f.text_field_block :name, :caption => "Full name"
288
+ = f.text_field_block :email
289
+ = f.check_box_block :remember_me
290
+ = f.select_block :fav_color, :options => ['red', 'blue']
291
+ = f.password_field_block :password
292
+ = f.submit_block "Create", :class => 'button'
293
+
294
+ and would generate this html (with each input contained in a paragraph and containing a label):
295
+
296
+ <form id="register" action="/register" method="post">
297
+ <p><label for="user_name">Full name: </label><input type="text" id="user_name" name="user[name]"></p>
298
+ ...omitted...
299
+ <p><input type="submit" value="Create" class="button"></p>
300
+ </form>
301
+
302
+ The following are fields provided by StandardFormBuilder that can be used within a form_for or fields_for:
303
+
304
+ * <tt>text_field_block(field, options={}, label_options={})</tt>
305
+ * <tt>text_field_block(:nickname, :class => 'big', :caption => "Username")</tt>
306
+ * <tt>text_area_block(field, options={}, label_options={})</tt>
307
+ * <tt>text_area_block(:about, :class => 'big')</tt>
308
+ * <tt>password_field_block(field, options={}, label_options={})</tt>
309
+ * <tt>password_field_block(:code, :class => 'big')</tt>
310
+ * <tt>file_field_block(field, options={}, label_options={})</tt>
311
+ * <tt>file_field_block(:photo, :class => 'big')</tt>
312
+ * <tt>check_box_block(field, options={}, label_options={})</tt>
313
+ * <tt>check_box_block(:remember_me, :class => 'big')</tt>
314
+ * <tt>select_block(field, options={}, label_options={})</tt>
315
+ * <tt>select_block(:country, :option => ['USA', 'Canada'])</tt>
316
+ * <tt>submit_block(caption, options={})</tt>
317
+ * <tt>submit_block(:username, :class => 'big')</tt>
318
+ * <tt>image_submit_block(source, options={})</tt>
319
+ * <tt>image_submit_block('submit.png', :class => 'big')</tt>
320
+
321
+ You can also easily build your own FormBuilder which allows for customized fields and behavior:
322
+
323
+ class MyCustomFormBuilder < AbstractFormBuilder
324
+ # Here we have access to a number of useful variables
325
+ #
326
+ # * view_context (use this to invoke any helpers)(ex. view_context.hidden_field_tag(...))
327
+ # * object (the record for this form) (ex. object.valid?)
328
+ # * object_name (object's underscored type) (ex. object_name => 'admin_user')
329
+ #
330
+ # We also have access to self.field_types => [:text_field, :text_area, ...]
331
+ # In addition, we have access to all the existing field tag helpers (text_field, hidden_field, file_field, ...)
332
+ end
333
+
334
+ Once a custom builder is defined, any call to form_for can use the new builder:
335
+
336
+ - form_for @user, '/register', :builder => MyCustomFormBuilder, :id => 'register' do |f|
337
+ ...fields here...
338
+
339
+ === Format Helpers
340
+
341
+ Format helpers are several useful utilities for manipulating the format of text to achieve a goal.
342
+ The format helper <tt>escape_html</tt> is also aliased as <tt>h</tt> and <tt>sanitize_html</tt>
343
+
344
+ The escape_html function is for taking an html string and escaping certain characters.
345
+ <tt>escape_html</tt> will escape ampersands, brackets and quotes to their HTML/XML entities. This is useful
346
+ to sanitize user content before displaying this on a template.
347
+
348
+ escape_html('<hello>&<goodbye>') # => &lt;hello&gt;&amp;&lt;goodbye&gt;
349
+
350
+ Format helpers also includes a number of useful text manipulation functions such as <tt>simple_format</tt>, and <tt>truncate</tt>.
351
+
352
+ simple_format("hello\nworld") # => "<p>hello<br/>world</p>"
353
+ truncate("Once upon a time in a world far far away", :length => 8) => "Once upon..."
354
+
355
+ The list of defined helpers in the 'format helpers' category:
356
+
357
+ * <tt>simple_format(text, html_options)</tt>
358
+ * Returns text transformed into HTML using simple formatting rules.
359
+ * <tt>simple_format("hello\nworld")</tt> => "<p>hello<br/>world</p>"
360
+ * <tt>truncate(text, *args)</tt>
361
+ * Truncates a given text after a given :length if text is longer than :length (defaults to 30).
362
+ * <tt>truncate("Once upon a time in a world far far away", :length => 8)</tt> => "Once upon..."
363
+ * <tt>escape_html</tt> (alias <tt>h</tt> and <tt>h!</tt>)
364
+ * (from RackUtils) Escape ampersands, brackets and quotes to their HTML/XML entities.
365
+
366
+ == Copyright
367
+
368
+ Copyright (c) 2009 Daniel Neighman. See LICENSE for details.
369
+
data/Rakefile ADDED
@@ -0,0 +1,57 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "any_view"
8
+ gem.summary = %Q{View helpers designed to work just about anywhere}
9
+ gem.description = %Q{View helpers with an absolute minimum of requirements}
10
+ gem.email = "has.sox@gmail.com"
11
+ gem.homepage = "http://github.com/hassox/any_view"
12
+ gem.authors = ["Daniel Neighman"]
13
+ gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
14
+ gem.add_development_dependency "haml", ">= 2.2.1"
15
+ gem.add_development_dependency "shoulda", ">= 0"
16
+ gem.add_development_dependency "rack-test", ">= 0.5.0"
17
+ gem.add_development_dependency "webrat", ">= 0.5.1"
18
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
19
+ end
20
+ Jeweler::GemcutterTasks.new
21
+ rescue LoadError
22
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
23
+ end
24
+
25
+ require 'rake/testtask'
26
+ Rake::TestTask.new(:test) do |test|
27
+ test.libs << 'lib' << 'test'
28
+ test.pattern = 'test/**/test_*.rb'
29
+ test.verbose = true
30
+ end
31
+
32
+ begin
33
+ require 'rcov/rcovtask'
34
+ Rcov::RcovTask.new do |test|
35
+ test.libs << 'test'
36
+ test.pattern = 'test/**/test_*.rb'
37
+ test.verbose = true
38
+ end
39
+ rescue LoadError
40
+ task :rcov do
41
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
42
+ end
43
+ end
44
+
45
+ task :test => :check_dependencies
46
+
47
+ task :default => :test
48
+
49
+ require 'rake/rdoctask'
50
+ Rake::RDocTask.new do |rdoc|
51
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
52
+
53
+ rdoc.rdoc_dir = 'rdoc'
54
+ rdoc.title = "any_view #{version}"
55
+ rdoc.rdoc_files.include('README*')
56
+ rdoc.rdoc_files.include('lib/**/*.rb')
57
+ end
@@ -0,0 +1,103 @@
1
+ module AnyView
2
+ module Helpers
3
+ module AssetTagHelpers
4
+ MAIL_ATTRIBUTES = [:cc, :bcc, :subject, :body]
5
+
6
+ # Creates a link element with given name, url and options
7
+ # link_to("/url", :class => "foo"){ "link text" }
8
+ # link_to 'click me', '/dashboard', :class => 'linky'
9
+ def link_to(*args, &block)
10
+ options = args.extract_options!
11
+ text, url = args
12
+ if url.nil?
13
+ url = text
14
+ text = capture_content(&block)
15
+ end
16
+ options.reverse_merge!(:href => url)
17
+ options[:content] = text
18
+ result = tag(:a, options)
19
+ block.nil? ? result : concat_content(result)
20
+ end
21
+
22
+ # Creates a mail link element with given name and caption
23
+ # mail_to "me@demo.com" => <a href="mailto:me@demo.com">me@demo.com</a>
24
+ # mail_to "me@demo.com", "My Email" => <a href="mailto:me@demo.com">My Email</a>
25
+ def mail_to(email, caption=nil, options={})
26
+ mail_options, options = options.partition{|k,v| MAIL_ATTRIBUTES.include?(k)}
27
+ mail_options, options = Hash[mail_options], Hash[options]
28
+ mail_query = Rack::Utils.build_query(mail_options).gsub(/\+/, '%20').gsub('%40', '@')
29
+ mail_href = "mailto:#{email}"; mail_href << "?#{mail_query}" if mail_query.present?
30
+ link_to (caption || email), mail_href, options
31
+ end
32
+
33
+ # Creates an image element with given url and options
34
+ # image_tag('icons/avatar.png')
35
+ def image_tag(url, options={})
36
+ options.reverse_merge!(:src => image_path(url))
37
+ tag(:img, options)
38
+ end
39
+
40
+ # Returns a stylesheet link tag for the sources specified as arguments
41
+ # stylesheet_link_tag 'style', 'application', 'layout'
42
+ def stylesheet_link_tag(*sources)
43
+ options = sources.extract_options!.symbolize_keys
44
+ sources.collect { |sheet| stylesheet_tag(sheet, options) }.join("\n")
45
+ end
46
+
47
+ # javascript_include_tag 'application', 'special'
48
+ def javascript_include_tag(*sources)
49
+ options = sources.extract_options!.symbolize_keys
50
+ sources.collect { |script| javascript_tag(script, options) }.join("\n")
51
+ end
52
+
53
+ # Returns the path to the image, either relative or absolute
54
+ def image_path(src)
55
+ src.gsub!(/\s/, '')
56
+ src =~ %r{^\s*(/|http)} ? src : uri_root_path('images', src)
57
+ end
58
+
59
+ protected
60
+
61
+ # stylesheet_tag('style', :media => 'screen')
62
+ def stylesheet_tag(source, options={})
63
+ options = options.dup.reverse_merge!(:href => stylesheet_path(source), :media => 'screen', :rel => 'stylesheet', :type => 'text/css')
64
+ tag(:link, options)
65
+ end
66
+
67
+ # javascript_tag 'application', :src => '/javascripts/base/application.js'
68
+ def javascript_tag(source, options={})
69
+ options = options.dup.reverse_merge!(:src => javascript_path(source), :type => 'text/javascript', :content => "")
70
+ tag(:script, options)
71
+ end
72
+
73
+ # Returns the javascript_path appending the default javascripts path if necessary
74
+ def javascript_path(source)
75
+ return source if source =~ /^http/
76
+ source.gsub!(/\.js$/, '')
77
+ source_name = source; source_name << ".js" unless source =~ /\.js\w{2,4}$/
78
+ result_path = source_name if source =~ %r{^/} # absolute path
79
+ result_path ||= uri_root_path("javascripts", source_name)
80
+ stamp = File.exist?(result_path) ? File.mtime(result_path) : Time.now.to_i
81
+ "#{result_path}?#{stamp}"
82
+ end
83
+
84
+ # Returns the stylesheet_path appending the default stylesheets path if necessary
85
+ def stylesheet_path(source)
86
+ return source if source =~ /^http/
87
+ source.gsub!(/\.css$/, '')
88
+ source_name = source; source_name << ".css" unless source =~ /\.css$/
89
+ result_path = source_name if source =~ %r{^/} # absolute path
90
+ result_path ||= uri_root_path("stylesheets", source_name)
91
+ stamp = File.exist?(result_path) ? File.mtime(result_path) : Time.now.to_i
92
+ "#{result_path}?#{stamp}"
93
+ end
94
+
95
+ # Returns the uri root of the application, defaulting to '/'
96
+ # @example uri_root('javascripts')
97
+ def uri_root_path(*paths)
98
+ root_uri = uri_root if self.respond_to?(:uri_root)
99
+ File.join(root_uri || '/', *paths)
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,7 @@
1
+ unless Array.method_defined?(:extract_options!)
2
+ class Array
3
+ def extract_options!
4
+ last.is_a?(Hash) ? pop : {}
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,41 @@
1
+ class Hash
2
+ unless method_defined?(:reverse_merge!)
3
+ def reverse_merge!(other = {})
4
+ other.each{|k,v| self[k] ||= v}
5
+ self
6
+ end
7
+ end
8
+
9
+ unless method_defined?(:slice!)
10
+ def slice!(*keys)
11
+ keys = keys.flatten
12
+ out = {}
13
+ keys.each{|k| out[k] = self[k]}
14
+ replace out
15
+ self
16
+ end
17
+
18
+ def slice(*keys)
19
+ out = dup
20
+ out.slice!(*keys)
21
+ end
22
+ end
23
+
24
+ unless method_defined?(:symbolize_keys)
25
+ def symbolize_keys
26
+ out = dup
27
+ out.symbolize_keys!
28
+ end
29
+ end
30
+
31
+ unless method_defined?(:symbolize_keys!)
32
+ def symbolize_keys!
33
+ symbolizable_keys = []
34
+ keys.each{|k| symbolizable_keys << k if k.respond_to?(:to_sym) && !k.is_a?(Symbol)}
35
+ symbolizable_keys.each do |k|
36
+ self[k.to_sym] = delete(k)
37
+ end
38
+ self
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,17 @@
1
+ class String
2
+ unless method_defined?(:titleize)
3
+ def titleize
4
+ gsub("_", " ").gsub(/\b('?[a-z])/){$1.upcase}
5
+ end
6
+ end
7
+
8
+ unless method_defined?(:underscore)
9
+ def underscore
10
+ gsub(/::/, '/').
11
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
12
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
13
+ gsub("-", "_").
14
+ downcase
15
+ end
16
+ end
17
+ end