padrino-helpers 0.16.2 → 0.17.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.
- checksums.yaml +4 -4
- data/lib/padrino/rendering/erb_template.rb +1 -1
- data/lib/padrino/rendering/erubi_template.rb +1 -1
- data/lib/padrino/rendering/erubis_template.rb +1 -1
- data/lib/padrino/rendering/hamlit_template.rb +1 -1
- data/lib/padrino/rendering/slim_template.rb +1 -1
- data/lib/padrino/rendering.rb +13 -10
- data/lib/padrino/safe_buffer.rb +2 -0
- data/lib/padrino-helpers/asset_tag_helpers.rb +4 -3
- data/lib/padrino-helpers/form_builder/abstract_form_builder.rb +1 -1
- data/lib/padrino-helpers/form_helpers.rb +2 -1
- data/lib/padrino-helpers/format_helpers.rb +2 -2
- data/lib/padrino-helpers/tag_helpers.rb +27 -5
- data/test/fixtures/apps/.components +1 -1
- data/test/test_asset_tag_helpers.rb +67 -0
- data/test/test_form_helpers.rb +10 -0
- data/test/test_format_helpers.rb +29 -0
- data/test/test_rendering.rb +50 -0
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 51a50e7f371f332ea78163dcfb0bbe826f29e9a300731c71b7591dfef4515f16
|
|
4
|
+
data.tar.gz: 2bfcef2d07e371a896c4287e9870d939dd6a7a4d4c3f049ccfb29724e96cfbfe
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 65cdd233db5732c6561f6bd386efad8e3cd798b37e0497c87b79d69d8bf104bb54c0ec4294eddf456eb6fba8fc3dfef97604634ba652415a9d8677f9d3a0e9d9
|
|
7
|
+
data.tar.gz: d6cd233e716c7cbf85e2b76635ed7620c9f2d1a984af95d8b553b995b78c0716e10bc54e363f2feaa396b4abe17fd53f89d58385c2a73667bd199a373a61db94
|
|
@@ -53,7 +53,7 @@ module Padrino
|
|
|
53
53
|
def precompiled_preamble(locals)
|
|
54
54
|
original = super
|
|
55
55
|
return original unless @is_padrino_app
|
|
56
|
-
"__in_erb_template = true\n
|
|
56
|
+
"__in_erb_template = true\n#{original.rpartition("\n").first}#{@outvar} = _buf = SafeBuffer.new\n"
|
|
57
57
|
end
|
|
58
58
|
end
|
|
59
59
|
end
|
data/lib/padrino/rendering.rb
CHANGED
|
@@ -111,7 +111,7 @@ module Padrino
|
|
|
111
111
|
#
|
|
112
112
|
def fetch_layout_path(given_layout, layouts_path = views)
|
|
113
113
|
layout_name = (given_layout || @layout || :application).to_s
|
|
114
|
-
cache_layout_path(layout_name) do
|
|
114
|
+
cache_layout_path([layouts_path.to_s, layout_name]) do
|
|
115
115
|
if Pathname.new(layout_name).absolute? && Dir["#{layout_name}.*"].any? || Dir["#{layouts_path}/#{layout_name}.*"].any?
|
|
116
116
|
layout_name
|
|
117
117
|
else
|
|
@@ -132,12 +132,12 @@ module Padrino
|
|
|
132
132
|
def cache_template_path(options)
|
|
133
133
|
began_at = Time.now
|
|
134
134
|
@_cached_templates ||= {}
|
|
135
|
-
logging = defined?(settings) && settings.logging? && defined?(logger)
|
|
135
|
+
logging = defined?(settings) && settings.logging? && defined?(logger) && logger.respond_to?(:bench) && logger.debug?
|
|
136
136
|
if !reload_templates? && (path = @_cached_templates[options])
|
|
137
|
-
logger.
|
|
137
|
+
logger.bench :cached, began_at, path[0] if logging
|
|
138
138
|
else
|
|
139
|
-
path = @_cached_templates[options] = yield
|
|
140
|
-
logger.
|
|
139
|
+
path = @_cached_templates[options] = yield
|
|
140
|
+
logger.bench :template, began_at, path[0] if path && logging
|
|
141
141
|
end
|
|
142
142
|
path
|
|
143
143
|
end
|
|
@@ -293,11 +293,10 @@ module Padrino
|
|
|
293
293
|
template_path = template_path.to_s
|
|
294
294
|
controller_key = respond_to?(:request) && request.respond_to?(:controller) && request.controller
|
|
295
295
|
rendering_options = [template_path, content_type || :html, locale]
|
|
296
|
+
options = DEFAULT_RENDERING_OPTIONS.merge(options)
|
|
297
|
+
view_path = options[:views] || settings.views || './views'
|
|
296
298
|
|
|
297
|
-
settings.cache_template_path(["#{controller_key}/#{template_path}", rendering_options[1], rendering_options[2]]) do
|
|
298
|
-
options = DEFAULT_RENDERING_OPTIONS.merge(options)
|
|
299
|
-
view_path = options[:views] || settings.views || './views'
|
|
300
|
-
|
|
299
|
+
settings.cache_template_path([view_path.to_s, "#{controller_key}/#{template_path}", rendering_options[1], rendering_options[2]]) do
|
|
301
300
|
template_candidates = glob_templates(view_path, template_path)
|
|
302
301
|
selected_template = select_template(template_candidates, *rendering_options)
|
|
303
302
|
selected_template ||= template_candidates.first unless options[:strict_format]
|
|
@@ -317,9 +316,13 @@ module Padrino
|
|
|
317
316
|
def resolve_layout(layout, options = {})
|
|
318
317
|
layouts_path = options[:layout_options] && options[:layout_options][:views] || options[:views] || settings.views || './views'
|
|
319
318
|
template_path = settings.fetch_layout_path(layout, layouts_path)
|
|
319
|
+
if !layout && Pathname.new(template_path).absolute? && Dir["#{template_path}.*"].any?
|
|
320
|
+
layouts_path, _, template_path = template_path.rpartition('/')
|
|
321
|
+
options[:layout_options] = (options[:layout_options] || {}).merge(views: layouts_path)
|
|
322
|
+
end
|
|
320
323
|
rendering_options = [template_path, content_type || :html, locale]
|
|
321
324
|
|
|
322
|
-
settings.cache_template_path(rendering_options) do
|
|
325
|
+
settings.cache_template_path([layouts_path.to_s, *rendering_options]) do
|
|
323
326
|
template_candidates = glob_templates(layouts_path, template_path)
|
|
324
327
|
selected_template = select_template(template_candidates, *rendering_options)
|
|
325
328
|
|
data/lib/padrino/safe_buffer.rb
CHANGED
|
@@ -5,7 +5,7 @@ module Padrino
|
|
|
5
5
|
#
|
|
6
6
|
module AssetTagHelpers
|
|
7
7
|
APPEND_ASSET_EXTENSIONS = %w[js css]
|
|
8
|
-
ABSOLUTE_URL_PATTERN = %r{
|
|
8
|
+
ABSOLUTE_URL_PATTERN = %r{\A(https?://)}
|
|
9
9
|
ASSET_FOLDERS = {
|
|
10
10
|
js: 'javascripts',
|
|
11
11
|
css: 'stylesheets'
|
|
@@ -86,6 +86,7 @@ module Padrino
|
|
|
86
86
|
name = block_given? ? '' : args.shift
|
|
87
87
|
href = args.first
|
|
88
88
|
options = { href: href ? escape_link(href) : '#' }.update(options)
|
|
89
|
+
options[:href] = escape_link(options[:href]) if options[:href]
|
|
89
90
|
return name unless parse_conditions(href, options)
|
|
90
91
|
block_given? ? content_tag(:a, options, &block) : content_tag(:a, name, options)
|
|
91
92
|
end
|
|
@@ -315,8 +316,8 @@ module Padrino
|
|
|
315
316
|
#
|
|
316
317
|
def asset_path(kind, source = nil)
|
|
317
318
|
kind, source = source, kind if source.nil?
|
|
318
|
-
source = asset_normalize_extension(kind,
|
|
319
|
-
return source if source =~ ABSOLUTE_URL_PATTERN || source =~ %r{
|
|
319
|
+
source = asset_normalize_extension(kind, source.to_s.gsub(' ', '%20'))
|
|
320
|
+
return source if source =~ ABSOLUTE_URL_PATTERN || source =~ %r{\A/}
|
|
320
321
|
source = File.join(asset_folder_name(kind), source)
|
|
321
322
|
timestamp = asset_timestamp(source)
|
|
322
323
|
result_path = uri_root_path(source)
|
|
@@ -210,7 +210,7 @@ module Padrino
|
|
|
210
210
|
# field_name(:number) => "user_telephone_attributes_number"
|
|
211
211
|
# field_name(:street) => "user_addresses_attributes_0_street"
|
|
212
212
|
def field_id(field = nil, value = nil)
|
|
213
|
-
result = namespace && !is_nested ? "#{namespace}_" : ''
|
|
213
|
+
result = namespace && !is_nested ? "#{namespace}_" : +''
|
|
214
214
|
result << field_id_fragment
|
|
215
215
|
result << "_#{field}" if field
|
|
216
216
|
result << "_#{value}" if value
|
|
@@ -94,6 +94,7 @@ module Padrino
|
|
|
94
94
|
protect_from_csrf: is_protected_from_csrf?,
|
|
95
95
|
'accept-charset' => 'UTF-8'
|
|
96
96
|
}.update(options)
|
|
97
|
+
options[:action] = escape_link(options[:action]) if options[:action]
|
|
97
98
|
options[:enctype] = 'multipart/form-data' if options.delete(:multipart)
|
|
98
99
|
|
|
99
100
|
if (desired_method = options[:method]) =~ /get/i
|
|
@@ -847,7 +848,7 @@ module Padrino
|
|
|
847
848
|
def adjust_color(color)
|
|
848
849
|
return '#000000' unless color =~ COLOR_CODE_REGEXP
|
|
849
850
|
return color if (color_size = color.size) == 7
|
|
850
|
-
color.slice(1, color_size - 1).each_char.with_object('#') do |chr, obj|
|
|
851
|
+
color.slice(1, color_size - 1).each_char.with_object(+'#') do |chr, obj|
|
|
851
852
|
obj << chr * 2
|
|
852
853
|
end
|
|
853
854
|
end
|
|
@@ -77,7 +77,7 @@ module Padrino
|
|
|
77
77
|
def simple_format(text, options = {})
|
|
78
78
|
t = options.delete(:tag) || :p
|
|
79
79
|
start_tag = tag(t, options, true)
|
|
80
|
-
text = escape_html(text.to_s.dup)
|
|
80
|
+
text = text.html_safe? ? text.dup : escape_html(text.to_s.dup)
|
|
81
81
|
text.gsub!(/\r\n?/, "\n") # \r\n and \r -> \n
|
|
82
82
|
text.gsub!(/\n\n+/, "</#{t}>\n\n#{start_tag}") # 2+ newline -> paragraph
|
|
83
83
|
text.gsub!(/([^\n]\n)(?=[^\n])/, '\1<br />') # 1 newline -> br
|
|
@@ -103,7 +103,7 @@ module Padrino
|
|
|
103
103
|
# pluralize(2, 'person') => '2 people'
|
|
104
104
|
#
|
|
105
105
|
def pluralize(count, singular, plural = nil)
|
|
106
|
-
"#{count || 0} " + ([1, '1'].include?(count) ? singular : (plural ||
|
|
106
|
+
"#{count || 0} " + ([1, '1'].include?(count) ? singular : (plural || Inflections.pluralize(singular)))
|
|
107
107
|
end
|
|
108
108
|
|
|
109
109
|
##
|
|
@@ -235,17 +235,39 @@ module Padrino
|
|
|
235
235
|
"<#{name}#{attributes}#{open ? '>' : ' />'}".html_safe
|
|
236
236
|
end
|
|
237
237
|
|
|
238
|
+
SAFE_URI_SCHEMES = %w[http https mailto tel ftp].freeze
|
|
239
|
+
|
|
238
240
|
##
|
|
239
241
|
# Returns an escaped document link.
|
|
242
|
+
# Rejects unsafe URI schemes (javascript:, data:, vbscript:, etc.)
|
|
243
|
+
# to prevent XSS via link injection.
|
|
240
244
|
#
|
|
241
245
|
# @example
|
|
242
246
|
# escape_link('http://example.com/spaced link')
|
|
243
247
|
# # => 'http://example.com/spaced%20link'
|
|
244
|
-
# escape_link('
|
|
245
|
-
# # => '
|
|
248
|
+
# escape_link('javascript:alert(1)')
|
|
249
|
+
# # => '#'
|
|
246
250
|
#
|
|
247
251
|
def escape_link(link)
|
|
248
|
-
link.gsub(' ', '%20')
|
|
252
|
+
return link.gsub(' ', '%20') unless unsafe_uri_scheme?(link)
|
|
253
|
+
|
|
254
|
+
'#'
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
##
|
|
258
|
+
# Returns true if the URI uses an unsafe scheme.
|
|
259
|
+
#
|
|
260
|
+
def unsafe_uri_scheme?(uri)
|
|
261
|
+
return false unless uri
|
|
262
|
+
|
|
263
|
+
# Read the scheme the way browsers do: drop tabs and newlines, skip leading
|
|
264
|
+
# control characters and spaces, then take a run of scheme characters
|
|
265
|
+
# followed by a colon. Relative links like 'search?q=a:b' have no scheme.
|
|
266
|
+
# Everything is anchored at the start so long inputs are scanned once.
|
|
267
|
+
scheme = uri.to_s.delete("\t\n\r")[/\A[\x00-\x20]*([a-z][a-z0-9+.-]*):/i, 1]
|
|
268
|
+
return false unless scheme
|
|
269
|
+
|
|
270
|
+
!SAFE_URI_SCHEMES.include?(scheme.downcase)
|
|
249
271
|
end
|
|
250
272
|
|
|
251
273
|
private
|
|
@@ -256,7 +278,7 @@ module Padrino
|
|
|
256
278
|
def tag_attributes(options)
|
|
257
279
|
return '' unless options
|
|
258
280
|
|
|
259
|
-
options.inject('') do |all, (key, value)|
|
|
281
|
+
options.inject(+'') do |all, (key, value)|
|
|
260
282
|
next all unless value
|
|
261
283
|
|
|
262
284
|
all << ' ' if all.empty?
|
|
@@ -283,7 +305,7 @@ module Padrino
|
|
|
283
305
|
# Iterate through nested values.
|
|
284
306
|
#
|
|
285
307
|
def nested_values(attribute, hash)
|
|
286
|
-
hash.inject('') do |all, (key, value)|
|
|
308
|
+
hash.inject(+'') do |all, (key, value)|
|
|
287
309
|
attribute_with_name = "#{attribute}-#{key.to_s.tr('_', '-')}"
|
|
288
310
|
all <<
|
|
289
311
|
if value.is_a?(Hash)
|
|
@@ -76,6 +76,63 @@ describe 'AssetTagHelpers' do
|
|
|
76
76
|
assert_html_has_tag(actual_link, 'a', href: '/register%20new%20user')
|
|
77
77
|
end
|
|
78
78
|
|
|
79
|
+
it 'should reject javascript: URIs' do
|
|
80
|
+
actual_link = link_to('click', 'javascript:alert(1)')
|
|
81
|
+
assert_html_has_tag(actual_link, 'a', href: '#', content: 'click')
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it 'should reject javascript: URIs with mixed case and whitespace' do
|
|
85
|
+
actual_link = link_to('click', "JaVaScRiPt:\nalert(1)")
|
|
86
|
+
assert_html_has_tag(actual_link, 'a', href: '#', content: 'click')
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it 'should reject data: URIs' do
|
|
90
|
+
actual_link = link_to('click', 'data:text/html,<script>alert(1)</script>')
|
|
91
|
+
assert_html_has_tag(actual_link, 'a', href: '#', content: 'click')
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it 'should reject vbscript: URIs' do
|
|
95
|
+
actual_link = link_to('click', 'vbscript:MsgBox("xss")')
|
|
96
|
+
assert_html_has_tag(actual_link, 'a', href: '#', content: 'click')
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it 'should reject unsafe schemes passed via options hash' do
|
|
100
|
+
actual_link = link_to('click', '/safe', href: 'javascript:alert(1)')
|
|
101
|
+
assert_html_has_tag(actual_link, 'a', href: '#', content: 'click')
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it 'should allow http and https URIs' do
|
|
105
|
+
assert_match 'href="http://example.com"', link_to('click', 'http://example.com')
|
|
106
|
+
assert_match 'href="https://example.com"', link_to('click', 'https://example.com')
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
it 'should allow mailto and tel URIs' do
|
|
110
|
+
assert_match 'href="mailto:a@b.com"', link_to('email', 'mailto:a@b.com')
|
|
111
|
+
assert_match 'href="tel:+1234567890"', link_to('call', 'tel:+1234567890')
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it 'should allow relative paths and anchors' do
|
|
115
|
+
assert_html_has_tag(link_to('click', '/path'), 'a', href: '/path')
|
|
116
|
+
assert_match 'href="#anchor"', link_to('click', '#anchor')
|
|
117
|
+
assert_match 'href="?query=1"', link_to('click', '?query=1')
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
it 'should allow relative paths with colons in the query or fragment' do
|
|
121
|
+
assert_match 'href="search?q=a:b"', link_to('click', 'search?q=a:b')
|
|
122
|
+
assert_match 'href="users/1?at=10:30"', link_to('click', 'users/1?at=10:30')
|
|
123
|
+
assert_match 'href="page#x:y"', link_to('click', 'page#x:y')
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
it 'should reject unsafe URIs preceded by control characters' do
|
|
127
|
+
actual_link = link_to('click', "\u0001 javascript:alert(1)")
|
|
128
|
+
assert_html_has_tag(actual_link, 'a', href: '#', content: 'click')
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
it 'should reject unsafe URIs with tabs or newlines inside the scheme' do
|
|
132
|
+
assert_html_has_tag(link_to('click', "java\tscript:alert(1)"), 'a', href: '#', content: 'click')
|
|
133
|
+
assert_html_has_tag(link_to('click', "java\nscript:alert(1)"), 'a', href: '#', content: 'click')
|
|
134
|
+
end
|
|
135
|
+
|
|
79
136
|
it 'should not escape image_tag' do
|
|
80
137
|
actual_link = link_to(image_tag('/my/fancy/image.png'), class: 'first', id: 'binky')
|
|
81
138
|
assert_html_has_tag(actual_link, 'img', src: '/my/fancy/image.png')
|
|
@@ -410,5 +467,15 @@ describe 'AssetTagHelpers' do
|
|
|
410
467
|
it 'should generate proper paths for public folder' do
|
|
411
468
|
assert_match(%r{/files/file.ext\?\d+}, asset_path('files/file.ext'))
|
|
412
469
|
end
|
|
470
|
+
|
|
471
|
+
it 'should keep colons in asset names' do
|
|
472
|
+
assert_match(%r{/images/a:b\.png\?\d+}, asset_path(:images, 'a:b.png'))
|
|
473
|
+
assert_match(%r{/images/photos/10:30\.png\?\d+}, asset_path(:images, 'photos/10:30.png'))
|
|
474
|
+
end
|
|
475
|
+
|
|
476
|
+
it 'should prefix sources whose later lines look absolute' do
|
|
477
|
+
assert_match(%r{\A/javascripts/data:}, asset_path(:js, "data:text/javascript,alert(1)//\n/x"))
|
|
478
|
+
assert_match(%r{\A/images/javascript:}, asset_path(:images, "javascript:alert(1)//\nhttp://x"))
|
|
479
|
+
end
|
|
413
480
|
end
|
|
414
481
|
end
|
data/test/test_form_helpers.rb
CHANGED
|
@@ -19,6 +19,16 @@ describe 'FormHelpers' do
|
|
|
19
19
|
assert_html_has_tag(actual_html, 'form input', type: 'hidden', name: '_method', count: 0)
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
+
it 'should reject unsafe action schemes passed via options hash' do
|
|
23
|
+
actual_html = form_tag('/safe', action: 'javascript:alert(1)') { 'Demo' }
|
|
24
|
+
assert_html_has_tag(actual_html, :form, action: '#')
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'should allow relative actions with colons in the query' do
|
|
28
|
+
actual_html = form_tag('search?q=a:b') { 'Demo' }
|
|
29
|
+
assert_html_has_tag(actual_html, :form, action: 'search?q=a:b')
|
|
30
|
+
end
|
|
31
|
+
|
|
22
32
|
it 'should display correct text inputs within form_tag' do
|
|
23
33
|
actual_html = form_tag('/register', "accept-charset": 'UTF-8', class: 'test') { text_field_tag(:username) }
|
|
24
34
|
assert_html_has_tag(actual_html, 'form input', type: 'text', name: 'username')
|
data/test/test_format_helpers.rb
CHANGED
|
@@ -39,6 +39,13 @@ describe 'FormatHelpers' do
|
|
|
39
39
|
assert_equal "<p>Don't try to escape <b>me</b>!</p>", actual_text
|
|
40
40
|
end
|
|
41
41
|
|
|
42
|
+
it 'should not modify already sanitized text it is given' do
|
|
43
|
+
text = "Keep me\nas I am".html_safe
|
|
44
|
+
simple_format(text)
|
|
45
|
+
assert_equal "Keep me\nas I am", text
|
|
46
|
+
assert_equal "<p>Keep me\n<br />as I am</p>", simple_format(text.freeze)
|
|
47
|
+
end
|
|
48
|
+
|
|
42
49
|
describe 'wrapped in a custom tag' do
|
|
43
50
|
it 'should format simple text into html format' do
|
|
44
51
|
actual_text = simple_format("Here is some basic text...\n...with a line break.", tag: :div)
|
|
@@ -57,6 +64,28 @@ describe 'FormatHelpers' do
|
|
|
57
64
|
end
|
|
58
65
|
end
|
|
59
66
|
|
|
67
|
+
describe 'for #pluralize method' do
|
|
68
|
+
it 'should pluralize with the given count' do
|
|
69
|
+
assert_equal '1 person', pluralize(1, 'person')
|
|
70
|
+
assert_equal '2 people', pluralize(2, 'person')
|
|
71
|
+
assert_equal '2 folks', pluralize(2, 'person', 'folks')
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it 'should pluralize without String#pluralize from ActiveSupport or padrino-gen' do
|
|
75
|
+
hidden = String.method_defined?(:pluralize)
|
|
76
|
+
if hidden
|
|
77
|
+
String.send(:alias_method, :__hidden_pluralize, :pluralize)
|
|
78
|
+
String.send(:remove_method, :pluralize)
|
|
79
|
+
end
|
|
80
|
+
assert_equal '2 items', pluralize(2, 'item')
|
|
81
|
+
ensure
|
|
82
|
+
if hidden
|
|
83
|
+
String.send(:alias_method, :pluralize, :__hidden_pluralize)
|
|
84
|
+
String.send(:remove_method, :__hidden_pluralize)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
60
89
|
describe 'for #word_wrap method' do
|
|
61
90
|
it 'should return proper formatting for 8 max width' do
|
|
62
91
|
actual_text = word_wrap('Once upon a time', line_width: 8)
|
data/test/test_rendering.rb
CHANGED
|
@@ -218,6 +218,38 @@ describe 'Rendering' do
|
|
|
218
218
|
get '/'
|
|
219
219
|
assert_equal 'default layout at application', body
|
|
220
220
|
end
|
|
221
|
+
|
|
222
|
+
it 'should use a class-level layout given as an absolute path' do
|
|
223
|
+
absolute_layout = File.expand_path('fixtures/layouts/layout', __dir__)
|
|
224
|
+
create_view :foo, 'erb file'
|
|
225
|
+
create_view :foo, 'js file', format: :js
|
|
226
|
+
mock_app do
|
|
227
|
+
layout absolute_layout
|
|
228
|
+
get('/layout_test', provides: %i[html js]) { render :foo }
|
|
229
|
+
end
|
|
230
|
+
get '/layout_test'
|
|
231
|
+
assert_equal 'erb file absolute layout', body
|
|
232
|
+
get '/layout_test.js'
|
|
233
|
+
assert_equal 'js file', body
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
it 'should use a class-level absolute layout with cached templates' do
|
|
237
|
+
absolute_layout = File.expand_path('fixtures/layouts/layout', __dir__)
|
|
238
|
+
create_layout :"layouts/layout", 'relative layout <%= yield %>'
|
|
239
|
+
create_view :foo, 'erb file'
|
|
240
|
+
mock_app do
|
|
241
|
+
disable :reload_templates
|
|
242
|
+
layout absolute_layout
|
|
243
|
+
get('/absolute') { render :foo }
|
|
244
|
+
get('/relative') { render :foo, layout: :layout }
|
|
245
|
+
end
|
|
246
|
+
2.times do
|
|
247
|
+
get '/absolute'
|
|
248
|
+
assert_equal 'erb file absolute layout', body
|
|
249
|
+
get '/relative'
|
|
250
|
+
assert_equal 'relative layout erb file', body
|
|
251
|
+
end
|
|
252
|
+
end
|
|
221
253
|
end
|
|
222
254
|
|
|
223
255
|
it 'should solve layout in layouts paths' do
|
|
@@ -314,6 +346,24 @@ describe 'Rendering' do
|
|
|
314
346
|
assert_equal 'bar', body
|
|
315
347
|
end
|
|
316
348
|
|
|
349
|
+
it 'should render with logging and a logger without Padrino::Logger::Extensions' do
|
|
350
|
+
create_template :index, 'plain logger'
|
|
351
|
+
log = StringIO.new
|
|
352
|
+
save_logger = Padrino.logger
|
|
353
|
+
Padrino.logger = Logger.new(log)
|
|
354
|
+
mock_app do
|
|
355
|
+
enable :logging
|
|
356
|
+
get('/') { render(:index, layout: false) }
|
|
357
|
+
end
|
|
358
|
+
get '/'
|
|
359
|
+
assert_equal 200, status
|
|
360
|
+
assert_equal 'plain logger', body
|
|
361
|
+
assert_match(/TEMPLATE \(\d+\.\d+s\) .*index/, log.string)
|
|
362
|
+
ensure
|
|
363
|
+
Padrino.logger = save_logger
|
|
364
|
+
remove_views
|
|
365
|
+
end
|
|
366
|
+
|
|
317
367
|
it 'should work properly with logging and layout' do
|
|
318
368
|
create_layout :application, 'layout <%= yield %>'
|
|
319
369
|
create_view :index, '<%= foo %>'
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: padrino-helpers
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.17.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Padrino Team
|
|
@@ -19,14 +19,14 @@ dependencies:
|
|
|
19
19
|
requirements:
|
|
20
20
|
- - '='
|
|
21
21
|
- !ruby/object:Gem::Version
|
|
22
|
-
version: 0.
|
|
22
|
+
version: 0.17.0
|
|
23
23
|
type: :runtime
|
|
24
24
|
prerelease: false
|
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
|
26
26
|
requirements:
|
|
27
27
|
- - '='
|
|
28
28
|
- !ruby/object:Gem::Version
|
|
29
|
-
version: 0.
|
|
29
|
+
version: 0.17.0
|
|
30
30
|
- !ruby/object:Gem::Dependency
|
|
31
31
|
name: tilt
|
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|