padrino-helpers-cj 0.12.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (145) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/.gitignore +21 -0
  4. data/.yardopts +1 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.rdoc +239 -0
  7. data/Rakefile +5 -0
  8. data/lib/padrino-helpers.rb +62 -0
  9. data/lib/padrino-helpers/asset_tag_helpers.rb +390 -0
  10. data/lib/padrino-helpers/form_builder/abstract_form_builder.rb +283 -0
  11. data/lib/padrino-helpers/form_builder/deprecated_builder_methods.rb +92 -0
  12. data/lib/padrino-helpers/form_builder/standard_form_builder.rb +40 -0
  13. data/lib/padrino-helpers/form_helpers.rb +633 -0
  14. data/lib/padrino-helpers/form_helpers/errors.rb +138 -0
  15. data/lib/padrino-helpers/form_helpers/options.rb +97 -0
  16. data/lib/padrino-helpers/form_helpers/security.rb +70 -0
  17. data/lib/padrino-helpers/format_helpers.rb +372 -0
  18. data/lib/padrino-helpers/locale/cs.yml +103 -0
  19. data/lib/padrino-helpers/locale/da.yml +91 -0
  20. data/lib/padrino-helpers/locale/de.yml +81 -0
  21. data/lib/padrino-helpers/locale/en.yml +103 -0
  22. data/lib/padrino-helpers/locale/es.yml +103 -0
  23. data/lib/padrino-helpers/locale/fr.yml +79 -0
  24. data/lib/padrino-helpers/locale/hu.yml +103 -0
  25. data/lib/padrino-helpers/locale/it.yml +89 -0
  26. data/lib/padrino-helpers/locale/ja.yml +103 -0
  27. data/lib/padrino-helpers/locale/lv.yml +103 -0
  28. data/lib/padrino-helpers/locale/nl.yml +82 -0
  29. data/lib/padrino-helpers/locale/no.yml +91 -0
  30. data/lib/padrino-helpers/locale/pl.yml +95 -0
  31. data/lib/padrino-helpers/locale/pt_br.yml +103 -0
  32. data/lib/padrino-helpers/locale/ro.yml +103 -0
  33. data/lib/padrino-helpers/locale/ru.yml +103 -0
  34. data/lib/padrino-helpers/locale/sv.yml +103 -0
  35. data/lib/padrino-helpers/locale/tr.yml +103 -0
  36. data/lib/padrino-helpers/locale/uk.yml +103 -0
  37. data/lib/padrino-helpers/locale/zh_cn.yml +103 -0
  38. data/lib/padrino-helpers/locale/zh_tw.yml +103 -0
  39. data/lib/padrino-helpers/number_helpers.rb +283 -0
  40. data/lib/padrino-helpers/output_helpers.rb +226 -0
  41. data/lib/padrino-helpers/output_helpers/abstract_handler.rb +61 -0
  42. data/lib/padrino-helpers/output_helpers/erb_handler.rb +27 -0
  43. data/lib/padrino-helpers/output_helpers/haml_handler.rb +25 -0
  44. data/lib/padrino-helpers/output_helpers/slim_handler.rb +18 -0
  45. data/lib/padrino-helpers/render_helpers.rb +63 -0
  46. data/lib/padrino-helpers/tag_helpers.rb +294 -0
  47. data/lib/padrino-helpers/translation_helpers.rb +36 -0
  48. data/lib/padrino/rendering.rb +397 -0
  49. data/lib/padrino/rendering/erubis_template.rb +66 -0
  50. data/lib/padrino/rendering/haml_template.rb +26 -0
  51. data/lib/padrino/rendering/slim_template.rb +20 -0
  52. data/padrino-helpers.gemspec +29 -0
  53. data/test/fixtures/apps/.components +6 -0
  54. data/test/fixtures/apps/.gitignore +7 -0
  55. data/test/fixtures/apps/render.rb +25 -0
  56. data/test/fixtures/apps/views/article/comment/show.slim +1 -0
  57. data/test/fixtures/apps/views/blog/post.erb +1 -0
  58. data/test/fixtures/apps/views/layouts/specific.erb +1 -0
  59. data/test/fixtures/apps/views/test/post.erb +1 -0
  60. data/test/fixtures/layouts/layout.erb +1 -0
  61. data/test/fixtures/markup_app/app.rb +87 -0
  62. data/test/fixtures/markup_app/views/button_to.erb +8 -0
  63. data/test/fixtures/markup_app/views/button_to.haml +5 -0
  64. data/test/fixtures/markup_app/views/button_to.slim +6 -0
  65. data/test/fixtures/markup_app/views/capture_concat.erb +14 -0
  66. data/test/fixtures/markup_app/views/capture_concat.haml +12 -0
  67. data/test/fixtures/markup_app/views/capture_concat.slim +12 -0
  68. data/test/fixtures/markup_app/views/content_for.erb +23 -0
  69. data/test/fixtures/markup_app/views/content_for.haml +19 -0
  70. data/test/fixtures/markup_app/views/content_for.slim +19 -0
  71. data/test/fixtures/markup_app/views/content_tag.erb +13 -0
  72. data/test/fixtures/markup_app/views/content_tag.haml +11 -0
  73. data/test/fixtures/markup_app/views/content_tag.slim +11 -0
  74. data/test/fixtures/markup_app/views/current_engine.erb +5 -0
  75. data/test/fixtures/markup_app/views/current_engine.haml +5 -0
  76. data/test/fixtures/markup_app/views/current_engine.slim +5 -0
  77. data/test/fixtures/markup_app/views/fields_for.erb +20 -0
  78. data/test/fixtures/markup_app/views/fields_for.haml +15 -0
  79. data/test/fixtures/markup_app/views/fields_for.slim +15 -0
  80. data/test/fixtures/markup_app/views/form_for.erb +72 -0
  81. data/test/fixtures/markup_app/views/form_for.haml +59 -0
  82. data/test/fixtures/markup_app/views/form_for.slim +59 -0
  83. data/test/fixtures/markup_app/views/form_tag.erb +95 -0
  84. data/test/fixtures/markup_app/views/form_tag.haml +78 -0
  85. data/test/fixtures/markup_app/views/form_tag.slim +79 -0
  86. data/test/fixtures/markup_app/views/link_to.erb +5 -0
  87. data/test/fixtures/markup_app/views/link_to.haml +4 -0
  88. data/test/fixtures/markup_app/views/link_to.slim +4 -0
  89. data/test/fixtures/markup_app/views/mail_to.erb +3 -0
  90. data/test/fixtures/markup_app/views/mail_to.haml +3 -0
  91. data/test/fixtures/markup_app/views/mail_to.slim +3 -0
  92. data/test/fixtures/markup_app/views/meta_tag.erb +3 -0
  93. data/test/fixtures/markup_app/views/meta_tag.haml +3 -0
  94. data/test/fixtures/markup_app/views/meta_tag.slim +3 -0
  95. data/test/fixtures/markup_app/views/partials/_erb.erb +1 -0
  96. data/test/fixtures/markup_app/views/partials/_haml.haml +1 -0
  97. data/test/fixtures/markup_app/views/partials/_slim.slim +1 -0
  98. data/test/fixtures/markup_app/views/simple_partial.erb +1 -0
  99. data/test/fixtures/markup_app/views/simple_partial.haml +1 -0
  100. data/test/fixtures/markup_app/views/simple_partial.slim +1 -0
  101. data/test/fixtures/render_app/app.rb +94 -0
  102. data/test/fixtures/render_app/views/_deep.erb +3 -0
  103. data/test/fixtures/render_app/views/_deep.haml +2 -0
  104. data/test/fixtures/render_app/views/_deep.slim +2 -0
  105. data/test/fixtures/render_app/views/_partial_block_erb.erb +10 -0
  106. data/test/fixtures/render_app/views/_partial_block_haml.haml +7 -0
  107. data/test/fixtures/render_app/views/_partial_block_slim.slim +7 -0
  108. data/test/fixtures/render_app/views/_unsafe.html.builder +2 -0
  109. data/test/fixtures/render_app/views/_unsafe_object.html.builder +2 -0
  110. data/test/fixtures/render_app/views/current_engine.haml +5 -0
  111. data/test/fixtures/render_app/views/current_engines/_erb.erb +1 -0
  112. data/test/fixtures/render_app/views/current_engines/_haml.haml +1 -0
  113. data/test/fixtures/render_app/views/current_engines/_slim.slim +1 -0
  114. data/test/fixtures/render_app/views/double_capture_erb.erb +3 -0
  115. data/test/fixtures/render_app/views/double_capture_haml.haml +2 -0
  116. data/test/fixtures/render_app/views/double_capture_slim.slim +2 -0
  117. data/test/fixtures/render_app/views/erb/test.erb +1 -0
  118. data/test/fixtures/render_app/views/explicit_engine.haml +5 -0
  119. data/test/fixtures/render_app/views/haml/test.haml +1 -0
  120. data/test/fixtures/render_app/views/render_block_erb.erb +5 -0
  121. data/test/fixtures/render_app/views/render_block_haml.haml +4 -0
  122. data/test/fixtures/render_app/views/render_block_slim.slim +4 -0
  123. data/test/fixtures/render_app/views/ruby_block_capture_erb.erb +1 -0
  124. data/test/fixtures/render_app/views/ruby_block_capture_haml.haml +1 -0
  125. data/test/fixtures/render_app/views/ruby_block_capture_slim.slim +1 -0
  126. data/test/fixtures/render_app/views/template/_user.haml +7 -0
  127. data/test/fixtures/render_app/views/template/haml_template.haml +1 -0
  128. data/test/fixtures/render_app/views/template/some_template.haml +2 -0
  129. data/test/fixtures/render_app/views/wrong_capture_erb.erb +3 -0
  130. data/test/fixtures/render_app/views/wrong_capture_haml.haml +2 -0
  131. data/test/fixtures/render_app/views/wrong_capture_slim.slim +2 -0
  132. data/test/helper.rb +131 -0
  133. data/test/test_asset_tag_helpers.rb +406 -0
  134. data/test/test_form_builder.rb +1216 -0
  135. data/test/test_form_helpers.rb +1056 -0
  136. data/test/test_format_helpers.rb +251 -0
  137. data/test/test_helpers.rb +10 -0
  138. data/test/test_locale.rb +20 -0
  139. data/test/test_number_helpers.rb +142 -0
  140. data/test/test_output_helpers.rb +157 -0
  141. data/test/test_render_helpers.rb +215 -0
  142. data/test/test_rendering.rb +694 -0
  143. data/test/test_rendering_extensions.rb +14 -0
  144. data/test/test_tag_helpers.rb +131 -0
  145. metadata +241 -0
@@ -0,0 +1,36 @@
1
+ module Padrino
2
+ module Helpers
3
+ ##
4
+ # Helpers related to locale i18n translation within templates.
5
+ #
6
+ module TranslationHelpers
7
+ ##
8
+ # Delegates to I18n.translate with no additional functionality.
9
+ #
10
+ # @param [Symbol] *args
11
+ # The keys to retrieve.
12
+ #
13
+ # @return [String]
14
+ # The translation for the specified keys.
15
+ #
16
+ def translate(*args)
17
+ I18n.translate(*args)
18
+ end
19
+ alias :t :translate
20
+
21
+ ##
22
+ # Delegates to I18n.localize with no additional functionality.
23
+ #
24
+ # @param [Symbol] *args
25
+ # The keys to retrieve.
26
+ #
27
+ # @return [String]
28
+ # The translation for the specified keys.
29
+ #
30
+ def localize(*args)
31
+ I18n.localize(*args)
32
+ end
33
+ alias :l :localize
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,397 @@
1
+ require 'padrino-support'
2
+ require 'pathname'
3
+
4
+ module Padrino
5
+ ##
6
+ # Padrino enhances the Sinatra 'render' method to have support for
7
+ # automatic template engine detection, enhanced layout functionality,
8
+ # locale enabled rendering, among other features.
9
+ #
10
+ module Rendering
11
+ ##
12
+ # A SafeTemplate assumes that its output is safe.
13
+ #
14
+ module SafeTemplate
15
+ def render(*)
16
+ super.html_safe
17
+ end
18
+ end
19
+
20
+ ##
21
+ # Exception responsible for when an expected template did not exist.
22
+ #
23
+ class TemplateNotFound < RuntimeError
24
+ end
25
+
26
+ ##
27
+ # This is an array of file patterns to ignore. If your editor add a
28
+ # suffix during editing to your files please add it like:
29
+ #
30
+ # @example
31
+ # Padrino::Rendering::IGNORE_FILE_PATTERN << /~$/
32
+ #
33
+ IGNORE_FILE_PATTERN = [
34
+ /~$/ # This is for Gedit
35
+ ] unless defined?(IGNORE_FILE_PATTERN)
36
+
37
+ ##
38
+ # Default options used in the resolve_template-method.
39
+ #
40
+ DEFAULT_RENDERING_OPTIONS = { :strict_format => false, :raise_exceptions => true } unless defined?(DEFAULT_RENDERING_OPTIONS)
41
+
42
+ class << self
43
+ ##
44
+ # Default engine configurations for Padrino::Rendering.
45
+ #
46
+ # @return {Hash<Symbol,Hash>}
47
+ # The configurations, keyed by engine.
48
+ def engine_configurations
49
+ @engine_configurations ||= {}
50
+ end
51
+
52
+ def registered(app)
53
+ if defined?(Padrino::Application) && app == Padrino::Application
54
+ # this fail can be removed later when jRuby is not bugged and MRI19 is dropped
55
+ fail 'Please, do not use `register` on Padrino::Application object, use `.dup` or subclassing'
56
+ end
57
+ included(app)
58
+ engine_configurations.each do |engine, configs|
59
+ app.set engine, configs
60
+ end
61
+ end
62
+
63
+ def included(base)
64
+ base.send(:include, InstanceMethods)
65
+ base.extend(ClassMethods)
66
+ end
67
+ end
68
+
69
+ ##
70
+ # Class methods responsible for rendering templates as part of a request.
71
+ #
72
+ module ClassMethods
73
+ ##
74
+ # Use layout like rails does or if a block given then like sinatra.
75
+ # If used without a block, sets the current layout for the route.
76
+ #
77
+ # By default, searches in your:
78
+ #
79
+ # +app+/+views+/+layouts+/+application+.(+haml+|+erb+|+xxx+)
80
+ # +app+/+views+/+layout_name+.(+haml+|+erb+|+xxx+)
81
+ #
82
+ # If you define +layout+ :+custom+ then searches for your layouts in
83
+ # +app+/+views+/+layouts+/+custom+.(+haml+|+erb+|+xxx+)
84
+ # +app+/+views+/+custom+.(+haml+|+erb+|+xxx+)
85
+ #
86
+ # @param [Symbol] name (:layout)
87
+ # The layout to use.
88
+ #
89
+ # @yield []
90
+ #
91
+ def layout(name=:layout, &block)
92
+ return super(name, &block) if block_given?
93
+ @layout = name
94
+ end
95
+
96
+ ##
97
+ # Returns the cached template file to render for a given url,
98
+ # content_type and locale. Deprecated since 0.12.1
99
+ #
100
+ # @param [Array<template_path, content_type, locale>] render_options
101
+ #
102
+ def fetch_template_file(render_options)
103
+ logger.warn "##{__method__} is deprecated"
104
+ (@_cached_templates ||= {})[render_options]
105
+ end
106
+
107
+ ##
108
+ # Caches the template file for the given rendering options. Deprecated since 0.12.1
109
+ #
110
+ # @param [String] template_file
111
+ # The path of the template file.
112
+ #
113
+ # @param [Array<template_path, content_type, locale>] render_options
114
+ #
115
+ def cache_template_file!(template_file, render_options)
116
+ logger.warn "##{__method__} is deprecated"
117
+ (@_cached_templates ||= {})[render_options] = template_file || []
118
+ end
119
+
120
+ ##
121
+ # Returns the cached layout path.
122
+ #
123
+ # @param [String, nil] given_layout
124
+ # The requested layout.
125
+ # @param [String, nil] layouts_path
126
+ # The directory where the layouts are located. Defaults to #views.
127
+ #
128
+ def fetch_layout_path(given_layout, layouts_path=views)
129
+ layout_name = (given_layout || @layout || :application).to_s
130
+ cache_layout_path(layout_name) do
131
+ if Pathname.new(layout_name).absolute? && Dir["#{layout_name}.*"].any? || Dir["#{layouts_path}/#{layout_name}.*"].any?
132
+ layout_name
133
+ else
134
+ File.join('layouts', layout_name)
135
+ end
136
+ end
137
+ end
138
+
139
+ def cache_layout_path(name)
140
+ @_cached_layout ||= {}
141
+ if !reload_templates? && path = @_cached_layout[name]
142
+ path
143
+ else
144
+ @_cached_layout[name] = yield(name)
145
+ end
146
+ end
147
+
148
+ def cache_template_path(options)
149
+ began_at = Time.now
150
+ @_cached_templates ||= {}
151
+ logging = defined?(settings) && settings.logging? && defined?(logger)
152
+ if !reload_templates? && path = @_cached_templates[options]
153
+ logger.debug :cached, began_at, path[0] if logging
154
+ else
155
+ path = @_cached_templates[options] = yield(name)
156
+ logger.debug :template, began_at, path[0] if path && logging
157
+ end
158
+ path
159
+ end
160
+ end
161
+
162
+ # Instance methods that allow enhanced rendering to function properly in Padrino.
163
+ module InstanceMethods
164
+ attr_reader :current_engine
165
+
166
+ ##
167
+ # Get/Set the content_type
168
+ #
169
+ # @param [String, nil] type
170
+ # The Content-Type to use.
171
+ #
172
+ # @param [Symbol, nil] type.
173
+ # Look and parse the given symbol to the matched Content-Type.
174
+ #
175
+ # @param [Hash] params
176
+ # Additional params to append to the Content-Type.
177
+ #
178
+ # @example
179
+ # case content_type
180
+ # when :js then do_some
181
+ # when :css then do_another
182
+ # end
183
+ #
184
+ # content_type :js
185
+ # # => set the response with 'application/javascript' Content-Type
186
+ # content_type 'text/html'
187
+ #
188
+ # # => set directly the Content-Type to 'text/html'
189
+ #
190
+ def content_type(type=nil, params={})
191
+ if type
192
+ super(type, params)
193
+ @_content_type = type
194
+ end
195
+ @_content_type
196
+ end
197
+
198
+ private
199
+
200
+ ##
201
+ # Enhancing Sinatra render functionality for:
202
+ #
203
+ # * Using layout similar to rails
204
+ # * Use render 'path/to/my/template' (without symbols)
205
+ # * Use render 'path/to/my/template' (with engine lookup)
206
+ # * Use render 'path/to/template.haml' (with explicit engine lookup)
207
+ # * Use render 'path/to/template', :layout => false
208
+ # * Use render 'path/to/template', :layout => false, :engine => 'haml'
209
+ #
210
+ def render(engine, data=nil, options={}, locals={}, &block)
211
+ # If engine is nil, ignore engine parameter and shift up all arguments
212
+ # render nil, "index", { :layout => true }, { :localvar => "foo" }
213
+ engine, data, options = data, options, locals if engine.nil? && data
214
+
215
+ # Data is a hash of options when no engine isn't explicit
216
+ # render "index", { :layout => true }, { :localvar => "foo" }
217
+ # Data is options, and options is locals in this case
218
+ data, options, locals = nil, data, options if data.is_a?(Hash)
219
+
220
+ # If data is unassigned then this is a likely a template to be resolved
221
+ # This means that no engine was explicitly defined
222
+ data, engine = resolve_template(engine, options) if data.nil?
223
+
224
+ options[:layout] ||= false unless Rendering.engine_configurations.has_key?(engine)
225
+
226
+ # Cleanup the template.
227
+ @current_engine, engine_was = engine, @current_engine
228
+ @_out_buf, buf_was = ActiveSupport::SafeBuffer.new, @_out_buf
229
+
230
+ # Pass arguments to Sinatra render method.
231
+ super(engine, data, with_layout(options), locals, &block)
232
+ ensure
233
+ @current_engine = engine_was
234
+ @_out_buf = buf_was
235
+ end
236
+
237
+ ##
238
+ # Returns the located layout tuple to be used for the rendered template
239
+ # (if available). Deprecated since 0.12.1
240
+ #
241
+ # @example
242
+ # resolve_layout
243
+ # # => ["/layouts/custom", :erb]
244
+ # # => [nil, nil]
245
+ #
246
+ def resolved_layout
247
+ logger.warn "##{__method__} is deprecated"
248
+ resolve_template(settings.fetch_layout_path, :raise_exceptions => false, :strict_format => true) || [nil, nil]
249
+ end
250
+
251
+ ##
252
+ # Returns the template path and engine that match content_type (if present),
253
+ # I18n.locale.
254
+ #
255
+ # @param [String] template_path
256
+ # The path of the template.
257
+ #
258
+ # @param [Hash] options
259
+ # Additional options.
260
+ #
261
+ # @option options [Boolean] :strict_format (false)
262
+ # The resolved template must match the content_type of the request.
263
+ #
264
+ # @option options [Boolean] :raise_exceptions (false)
265
+ # Raises a {TemplateNotFound} exception if the template cannot be located.
266
+ #
267
+ # @return [Array<Symbol, Symbol>]
268
+ # The path and format of the template.
269
+ #
270
+ # @raise [TemplateNotFound]
271
+ # The template could not be found.
272
+ #
273
+ # @example
274
+ # get "/foo", :provides => [:html, :js] do; render 'path/to/foo'; end
275
+ # # If you request "/foo.js" with I18n.locale == :ru => [:"/path/to/foo.ru.js", :erb]
276
+ # # If you request "/foo" with I18n.locale == :de => [:"/path/to/foo.de.haml", :haml]
277
+ #
278
+ def resolve_template(template_path, options={})
279
+ template_path = template_path.to_s
280
+ controller_key = respond_to?(:request) && request.respond_to?(:controller) && request.controller
281
+ rendering_options = [template_path, content_type || :html, locale]
282
+
283
+ settings.cache_template_path(["#{controller_key}/#{template_path}", rendering_options[1], rendering_options[2]]) do
284
+ options = DEFAULT_RENDERING_OPTIONS.merge(options)
285
+ view_path = options[:views] || settings.views || "./views"
286
+
287
+ template_candidates = glob_templates(view_path, template_path)
288
+ selected_template = select_template(template_candidates, *rendering_options)
289
+ selected_template ||= template_candidates.first unless options[:strict_format]
290
+
291
+ fail TemplateNotFound, "Template '#{template_path}' not found in '#{view_path}'" if !selected_template && options[:raise_exceptions]
292
+ selected_template
293
+ end
294
+ end
295
+
296
+ ##
297
+ # Return the I18n.locale if I18n is defined.
298
+ #
299
+ def locale
300
+ I18n.locale if defined?(I18n)
301
+ end
302
+
303
+ def resolve_layout(layout, options={})
304
+ layouts_path = options[:layout_options] && options[:layout_options][:views] || options[:views] || settings.views || "./views"
305
+ template_path = settings.fetch_layout_path(layout, layouts_path)
306
+ rendering_options = [template_path, content_type || :html, locale]
307
+
308
+ settings.cache_template_path(rendering_options) do
309
+ template_candidates = glob_templates(layouts_path, template_path)
310
+ selected_template = select_template(template_candidates, *rendering_options)
311
+
312
+ fail TemplateNotFound, "Layout '#{template_path}' not found in '#{layouts_path}'" if !selected_template && layout.present?
313
+ selected_template
314
+ end
315
+ end
316
+
317
+ def with_layout(options)
318
+ options = options.dup
319
+ layout = options[:layout]
320
+ return options if layout == false
321
+
322
+ layout = @layout if !layout || layout == true
323
+ return options if settings.templates.has_key?(:layout) && layout.blank?
324
+
325
+ if layout.kind_of?(String) && Pathname.new(layout).absolute?
326
+ layout_path, _, layout = layout.rpartition('/')
327
+ options[:layout_options] ||= {}
328
+ options[:layout_options][:views] ||= layout_path
329
+ end
330
+ layout, layout_engine = resolve_layout(layout, options)
331
+ options.update(:layout => layout, :layout_engine => layout_engine)
332
+ end
333
+
334
+ def glob_templates(views_path, template_path)
335
+ parts = []
336
+ parts << views_path if views_path.present?
337
+ if respond_to?(:request) && request.respond_to?(:controller) && request.controller.present? && Pathname.new(template_path).relative?
338
+ parts << "{,#{request.controller}}"
339
+ end
340
+ parts << template_path.chomp(File.extname(template_path)) + '.*'
341
+ Dir.glob(File.join(parts)).inject([]) do |all,file|
342
+ next all if IGNORE_FILE_PATTERN.any?{ |pattern| file.to_s =~ pattern }
343
+ all << path_and_engine(file, views_path)
344
+ end
345
+ end
346
+
347
+ def select_template(templates, template_path, content_type, _locale)
348
+ simple_content_type = [:html, :plain].include?(content_type)
349
+ target_path, target_engine = path_and_engine(template_path)
350
+
351
+ templates.find{ |file,_| file.to_s == "#{target_path}.#{locale}.#{content_type}" } ||
352
+ templates.find{ |file,_| file.to_s == "#{target_path}.#{locale}" && simple_content_type } ||
353
+ templates.find{ |file,engine| engine == target_engine || File.extname(file.to_s) == ".#{target_engine}" } ||
354
+ templates.find{ |file,_| file.to_s == "#{target_path}.#{content_type}" } ||
355
+ templates.find{ |file,_| file.to_s == "#{target_path}" && simple_content_type }
356
+ end
357
+
358
+ def path_and_engine(path, relative=nil)
359
+ extname = File.extname(path)
360
+ engine = (extname[1..-1]||'none').to_sym
361
+ path = path.chomp(extname)
362
+ path.insert(0, '/') unless Pathname.new(path).absolute?
363
+ path = path.squeeze('/').sub(relative, '') if relative
364
+ [path.to_sym, engine]
365
+ end
366
+ end
367
+ end
368
+ end
369
+
370
+ unless defined? Padrino::Rendering::HamlTemplate
371
+ begin
372
+ require 'haml'
373
+ require 'haml/helpers/xss_mods'
374
+ require 'haml/helpers/action_view_extensions'
375
+ rescue LoadError
376
+ else
377
+ require 'padrino/rendering/haml_template'
378
+ end
379
+ end
380
+
381
+ unless defined? Padrino::Rendering::ErubisTemplate
382
+ begin
383
+ require 'erubis'
384
+ rescue LoadError
385
+ else
386
+ require 'padrino/rendering/erubis_template'
387
+ end
388
+ end
389
+
390
+ unless defined? Padrino::Rendering::SlimTemplate
391
+ begin
392
+ require 'slim'
393
+ rescue LoadError
394
+ else
395
+ require 'padrino/rendering/slim_template'
396
+ end
397
+ end
@@ -0,0 +1,66 @@
1
+ module Padrino
2
+ module Rendering
3
+ ##
4
+ # SafeBufferEnhancer is an Erubis Enhancer that compiles templates that
5
+ # are fit for using ActiveSupport::SafeBuffer as a Buffer.
6
+ #
7
+ # @api private
8
+ module SafeBufferEnhancer
9
+ def add_expr_literal(src, code)
10
+ src << " #{@bufvar}.concat((" << code << ').to_s);'
11
+ end
12
+
13
+ def add_stmt(src, code)
14
+ code = code.sub('end', 'nil;end') if code =~ /\A\s*end\s*\Z/
15
+ src << code
16
+ src << ';' unless code[-1] == ?\n
17
+ end
18
+
19
+ def add_expr_escaped(src, code)
20
+ src << " #{@bufvar}.safe_concat " << code << ';'
21
+ end
22
+
23
+ def add_text(src, text)
24
+ src << " #{@bufvar}.safe_concat '" << escape_text(text) << "';" unless text.empty?
25
+ end
26
+ end
27
+
28
+ ##
29
+ # SafeBufferTemplate is the Eruby engine, augmented with SafeBufferEnhancer.
30
+ #
31
+ # @api private
32
+ class SafeEruby < ::Erubis::Eruby
33
+ include SafeBufferEnhancer
34
+ end
35
+
36
+ ##
37
+ # Modded ErubisTemplate that doesn't insist in an String as output
38
+ # buffer.
39
+ #
40
+ # @api private
41
+ class ErubisTemplate < Tilt::ErubisTemplate
42
+ def render(*args)
43
+ app = args.first
44
+ app_class = app.class
45
+ @is_padrino_app = (defined?(Padrino::Application) && app.kind_of?(Padrino::Application)) ||
46
+ (app_class.respond_to?(:erb) && app_class.erb[:engine_class] == Padrino::Rendering::SafeEruby)
47
+ super
48
+ end
49
+
50
+ ##
51
+ # In preamble we need a flag `__in_erb_template` and SafeBuffer for padrino apps.
52
+ #
53
+ def precompiled_preamble(locals)
54
+ original = super
55
+ return original unless @is_padrino_app
56
+ "__in_erb_template = true\n" << original.rpartition("\n").first << "#{@outvar} = _buf = ActiveSupport::SafeBuffer.new\n"
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ Tilt.prefer(Padrino::Rendering::ErubisTemplate, :erb)
63
+
64
+ Padrino::Rendering.engine_configurations[:erb] = {
65
+ :engine_class => Padrino::Rendering::SafeEruby,
66
+ }