roda 3.31.0 → 3.32.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2d6d28c0f8b5197ab3d2a74726150921a435ccdcd8f18c6eb2c9bbe4d1cb2a14
4
- data.tar.gz: f1464284c0cb20638bc7575769271c6ea39642ff3b1842fad33b92759db915cd
3
+ metadata.gz: 2a342192f0ab697bea9c4e5b55669644f06fe16e161539b1efc3d10f3c6b9947
4
+ data.tar.gz: cf01944fe14494efd606cd892cbbbae5b5128f5a1d83c5e411bd4c64cc6e4321
5
5
  SHA512:
6
- metadata.gz: 4fca0abe3d0072e0a3e7201a089fd708610933ce4d461496bb0c13cbf7d84d2d10010c4007c460953972070d782742dba4d88799fd608f3df1ef7cca58cecef1
7
- data.tar.gz: 189a647f809aa732baebc225ea313c59e543d0d0935c8008a85084694161753e0939a7cac4c1f9d010e03785ec792d49b6c3e5643925066e1cda12d0b7701237
6
+ metadata.gz: e5de72f1385942855bd2c8e1c0f6be5187430d7d83112d7400bc573f045456a445166edfdbb6a7f70779c7b008745e8063bd44274b0111dec95643f87cfe12fe
7
+ data.tar.gz: b69e2fb41045d19c1f9e79dd2d1a87ca691fcd8de975bd34e37456cd6c5183cd2a6ad6bb59a07594527588d2903ef1bceea5f356a809aef03c01e5f64415246b
data/CHANGELOG CHANGED
@@ -1,3 +1,13 @@
1
+ = 3.32.0 (2020-05-15)
2
+
3
+ * Make :dependencies option in assets plugin work correctly with render plugin template caching (jeremyevans) (#191)
4
+
5
+ * Support render method :dependencies option for specifying which files to check for modification (jgarth, jeremyevans) (#192)
6
+
7
+ * Add each_partial to the partials plugin for rendering a partial for each element in an enumerable (jeremyevans)
8
+
9
+ * Make render_each in render_each plugin handle template names with directories and extensions (jeremyevans)
10
+
1
11
  = 3.31.0 (2020-04-15)
2
12
 
3
13
  * Add :relative option to path method in path plugin, for generating a method returning relative paths (jeremyevans)
@@ -418,6 +418,10 @@ You can provide an array to specify multiple request methods and match on any of
418
418
  {method: :post} # matches POST
419
419
  {method: ['post', 'patch']} # matches POST and PATCH
420
420
 
421
+ === true
422
+
423
+ If +true+ is given directly as a matcher, it always matches.
424
+
421
425
  === false, nil
422
426
 
423
427
  If +false+ or +nil+ is given directly as a matcher, it doesn't match anything.
@@ -1,6 +1,6 @@
1
1
  = New Features
2
2
 
3
- * A relative_paths plugin has been added, adding a relative_path
3
+ * A relative_path plugin has been added, adding a relative_path
4
4
  method that will take an absolute path and make it relative to the
5
5
  current request by prepending an appropriate prefix. This is
6
6
  helpful when using Roda as a static site generator to generate a
@@ -0,0 +1,42 @@
1
+ = New Features
2
+
3
+ * render_each in the render_each plugin now automatically handles
4
+ template names with subdirectories and extensions. Previously, these
5
+ caused issues unless the :local option was provided. So now you
6
+ can use:
7
+
8
+ render_each(foos, "items/foo")
9
+
10
+ instead of:
11
+
12
+ render_each(foos, "items/foo", :local=>:foo)
13
+
14
+ * each_partial has been added to the partials plugin. It operates
15
+ similarly to render_each, but uses the convention for partial
16
+ template naming. So this:
17
+
18
+ each_partial(foos, "items/foo")
19
+
20
+ is the same as:
21
+
22
+ render_each(foos, "items/_foo", :local=>:foo)
23
+
24
+ = Other Improvements
25
+
26
+ * The :dependencies option in the assets plugin now works correctly
27
+ with compiled templates in the render plugin in uncached mode
28
+ (the default in development). Previously, modifying a dependency
29
+ file would not result in recompiling the asset template when
30
+ requesting the main file.
31
+
32
+ * Method visibility issues in the following plugins have been fixed:
33
+
34
+ * content_security_policy
35
+ * default_headers
36
+ * indifferent_params
37
+ * placeholder_string_matchers
38
+ * symbol_matchers
39
+
40
+ Previously, these plugins made private methods public by mistake
41
+ when overriding them. Additionally, Roda.freeze no longer changes
42
+ the visibility of the set_default_headers private method.
@@ -197,6 +197,8 @@ class Roda
197
197
  if instance_method(:set_default_headers).owner == ResponseMethods &&
198
198
  instance_method(:default_headers).owner == ResponseMethods
199
199
 
200
+ private
201
+
200
202
  def set_default_headers
201
203
  @headers['Content-Type'] ||= 'text/html'
202
204
  end
@@ -8,6 +8,8 @@ class Roda
8
8
  # using a regexp.
9
9
  module SymbolRegexpMatchers
10
10
  module RequestMethods
11
+ private
12
+
11
13
  # The regular expression to use for matching symbols. By default, any non-empty
12
14
  # segment matches.
13
15
  def _match_symbol_regexp(s)
@@ -405,6 +405,11 @@ class Roda
405
405
  opts[s] ||= {}
406
406
  end
407
407
 
408
+ expanded_deps = opts[:expanded_dependencies] = {}
409
+ opts[:dependencies].each do |file, deps|
410
+ expanded_deps[File.expand_path(file)] = Array(deps)
411
+ end
412
+
408
413
  if headers = opts[:headers]
409
414
  opts[:css_headers] = headers.merge(opts[:css_headers])
410
415
  opts[:js_headers] = headers.merge(opts[:js_headers])
@@ -412,7 +417,7 @@ class Roda
412
417
  opts[:css_headers]['Content-Type'] ||= "text/css; charset=UTF-8".freeze
413
418
  opts[:js_headers]['Content-Type'] ||= "application/javascript; charset=UTF-8".freeze
414
419
 
415
- [:css_headers, :js_headers, :css_opts, :js_opts, :dependencies].each do |s|
420
+ [:css_headers, :js_headers, :css_opts, :js_opts, :dependencies, :expanded_dependencies].each do |s|
416
421
  opts[s].freeze
417
422
  end
418
423
  [:headers, :css, :js].each do |s|
@@ -732,7 +737,7 @@ class Roda
732
737
  content = if file.end_with?(".#{type}")
733
738
  ::File.read(file)
734
739
  else
735
- render_asset_file(file, :template_opts=>o[:"#{type}_opts"])
740
+ render_asset_file(file, :template_opts=>o[:"#{type}_opts"], :dependencies=>o[:expanded_dependencies][file])
736
741
  end
737
742
 
738
743
  o[:postprocessor] ? o[:postprocessor].call(file, type, content) : content
@@ -762,7 +767,7 @@ class Roda
762
767
  # other files, check the modification times of all dependencies and
763
768
  # return the maximum.
764
769
  def asset_last_modified(file)
765
- if deps = self.class.assets_opts[:dependencies][file]
770
+ if deps = self.class.assets_opts[:expanded_dependencies][file]
766
771
  ([file] + Array(deps)).map{|f| ::File.stat(f).mtime}.max
767
772
  else
768
773
  ::File.stat(file).mtime
@@ -304,6 +304,8 @@ class Roda
304
304
  @content_security_policy ||= roda_class.opts[:content_security_policy].dup
305
305
  end
306
306
 
307
+ private
308
+
307
309
  # Set the appropriate content security policy header.
308
310
  def set_default_headers
309
311
  super
@@ -31,6 +31,8 @@ class Roda
31
31
  if owner == Base::ResponseMethods || (owner == response_class && app.opts[:set_default_headers_overridder] == response_class)
32
32
  app.opts[:set_default_headers_overridder] = response_class
33
33
  response_class.class_eval(<<-END, __FILE__, __LINE__+1)
34
+ private
35
+
34
36
  def set_default_headers
35
37
  h = @headers
36
38
  #{headers.map{|k,v| "h[#{k.inspect}] ||= #{v.inspect}"}.join('; ')}
@@ -8,7 +8,7 @@ class Roda
8
8
  #
9
9
  # class App < Roda
10
10
  # hash_matcher(:foo) do |v|
11
- # self['foo'] == v
11
+ # params['foo'] == v
12
12
  # end
13
13
  #
14
14
  # route do
@@ -64,6 +64,8 @@ class Roda
64
64
  module RequestMethods
65
65
  QUERY_PARSER = Rack::Utils.default_query_parser = QueryParser.new(QueryParser::Params, 65536, 100)
66
66
 
67
+ private
68
+
67
69
  def query_parser
68
70
  QUERY_PARSER
69
71
  end
@@ -18,27 +18,54 @@ class Roda
18
18
  # render('_test')
19
19
  # render('dir/_test')
20
20
  #
21
- # Note that this plugin automatically loads the :render plugin.
21
+ # To render the same template once for each object in an enumerable,
22
+ # you can use the +render_partials+ method:
23
+ #
24
+ # each_partial([1,2,3], :foo) # uses _foo.erb
25
+ #
26
+ # This is basically equivalent to:
27
+ #
28
+ # render_each([1,2,3], "_foo", local: :foo)
29
+ #
30
+ # This plugin depends on the render and render_each plugins.
22
31
  module Partials
23
- # Depend on the render plugin, since this overrides
24
- # some of its methods.
32
+ # Depend on the render plugin, passing received options to it.
33
+ # Also depend on the render_each plugin.
25
34
  def self.load_dependencies(app, opts=OPTS)
26
35
  app.plugin :render, opts
36
+ app.plugin :render_each
27
37
  end
28
38
 
29
39
  module InstanceMethods
40
+ # For each object in the given enumerable, render the given
41
+ # template (prefixing the template filename with an underscore).
42
+ def each_partial(enum, template, opts=OPTS)
43
+ unless opts.has_key?(:local)
44
+ opts = Hash[opts]
45
+ opts[:local] = render_each_default_local(template)
46
+ end
47
+ render_each(enum, partial_template_name(template.to_s), opts)
48
+ end
49
+
30
50
  # Renders the given template without a layout, but
31
51
  # prefixes the template filename to use with an
32
52
  # underscore.
33
53
  def partial(template, opts=OPTS)
34
54
  opts = parse_template_opts(template, opts)
35
55
  if opts[:template]
36
- template = opts[:template].split('/')
37
- template[-1] = "_#{template[-1]}"
38
- opts[:template] = template.join('/')
56
+ opts[:template] = partial_template_name(opts[:template])
39
57
  end
40
58
  render_template(opts)
41
59
  end
60
+
61
+ private
62
+
63
+ # Prefix the template base filename with an underscore.
64
+ def partial_template_name(template)
65
+ segments = template.split('/')
66
+ segments[-1] = "_#{segments[-1]}"
67
+ segments.join('/')
68
+ end
42
69
  end
43
70
  end
44
71
 
@@ -27,6 +27,8 @@ class Roda
27
27
  end
28
28
 
29
29
  module RequestMethods
30
+ private
31
+
30
32
  def _match_string(str)
31
33
  if str.index(":")
32
34
  consume(self.class.cached_matcher(str){Regexp.escape(str).gsub(/:(\w+)/){|m| _match_symbol_regexp($1)}})
@@ -241,12 +241,13 @@ class Roda
241
241
  # template file has been modified. This is an internal class and
242
242
  # the API is subject to change at any time.
243
243
  class TemplateMtimeWrapper
244
- def initialize(template_class, path, *template_args)
244
+ def initialize(template_class, path, dependencies, *template_args)
245
245
  @template_class = template_class
246
246
  @path = path
247
247
  @template_args = template_args
248
+ @dependencies = ([path] + Array(dependencies)) if dependencies
248
249
 
249
- @mtime = (File.mtime(path) if File.file?(path))
250
+ @mtime = template_last_modified if File.file?(path)
250
251
  @template = template_class.new(path, *template_args)
251
252
  end
252
253
 
@@ -257,17 +258,28 @@ class Roda
257
258
  @template.render(*args, &block)
258
259
  end
259
260
 
261
+ # Return when the template was last modified. If the template depends on any
262
+ # other files, check the modification times of all dependencies and
263
+ # return the maximum.
264
+ def template_last_modified
265
+ if deps = @dependencies
266
+ deps.map{|f| File.mtime(f)}.max
267
+ else
268
+ File.mtime(@path)
269
+ end
270
+ end
271
+
260
272
  # If the template file has been updated, return true and update
261
273
  # the template object and the modification time. Other return false.
262
274
  def modified?
263
275
  begin
264
- mtime = File.mtime(path = @path)
276
+ mtime = template_last_modified
265
277
  rescue
266
278
  # ignore errors
267
279
  else
268
280
  if mtime != @mtime
269
281
  @mtime = mtime
270
- @template = @template_class.new(path, *@template_args)
282
+ @template = @template_class.new(@path, *@template_args)
271
283
  return true
272
284
  end
273
285
  end
@@ -576,7 +588,7 @@ class Roda
576
588
  !opts[:inline]
577
589
 
578
590
  if render_opts[:check_template_mtime] && !opts[:template_block] && !cache
579
- template = TemplateMtimeWrapper.new(opts[:template_class], opts[:path], 1, template_opts)
591
+ template = TemplateMtimeWrapper.new(opts[:template_class], opts[:path], opts[:dependencies], 1, template_opts)
580
592
 
581
593
  if define_compiled_method
582
594
  method_name = :"_roda_template_#{self.class.object_id}_#{method_cache_key}"
@@ -26,7 +26,9 @@ class Roda
26
26
  #
27
27
  # Will render the +foo+ template, but the local variable used inside
28
28
  # the template will be +bar+. You can use <tt>local: nil</tt> to
29
- # not set a local variable inside the template.
29
+ # not set a local variable inside the template. By default, the
30
+ # local variable name is based on the template name, with any
31
+ # directories and file extensions removed.
30
32
  module RenderEach
31
33
  # Load the render plugin before this plugin, since this plugin
32
34
  # calls the render method.
@@ -45,11 +47,11 @@ class Roda
45
47
  # set a local variable. If not set, uses the template name.
46
48
  def render_each(enum, template, opts=(no_opts = true; optimized_template = _cached_render_each_template_method(template); OPTS))
47
49
  if optimized_template
48
- return _optimized_render_each(enum, optimized_template, template.to_s.to_sym, {})
50
+ return _optimized_render_each(enum, optimized_template, render_each_default_local(template), {})
49
51
  elsif opts.has_key?(:local)
50
52
  as = opts[:local]
51
53
  else
52
- as = template.to_s.to_sym
54
+ as = render_each_default_local(template)
53
55
  if no_opts && optimized_template.nil? && (optimized_template = _optimized_render_method_for_locals(template, (locals = {as=>nil})))
54
56
  return _optimized_render_each(enum, optimized_template, as, locals)
55
57
  end
@@ -77,6 +79,12 @@ class Roda
77
79
 
78
80
  private
79
81
 
82
+ # The default local variable name to use for the template, if the :local option
83
+ # is not used when calling render_each.
84
+ def render_each_default_local(template)
85
+ File.basename(template.to_s).sub(/\..+\z/, '').to_sym
86
+ end
87
+
80
88
  if Render::COMPILED_METHOD_SUPPORT
81
89
  # If compiled method support is enabled in the render plugin, return the
82
90
  # method name to call to render the template. Return false if not given
@@ -6,7 +6,7 @@ class Roda
6
6
  # The symbol_matchers plugin allows you do define custom regexps to use
7
7
  # for specific symbols. For example, if you have a route such as:
8
8
  #
9
- # r.on :username do
9
+ # r.on :username do |username|
10
10
  # # ...
11
11
  # end
12
12
  #
@@ -28,7 +28,7 @@ class Roda
28
28
  # If the placeholder_string_matchers plugin is loaded, this feature also applies to
29
29
  # placeholders in strings, so the following:
30
30
  #
31
- # r.on "users/:username" do
31
+ # r.on "users/:username" do |username|
32
32
  # # ...
33
33
  # end
34
34
  #
@@ -4,7 +4,7 @@ class Roda
4
4
  RodaMajorVersion = 3
5
5
 
6
6
  # The minor version of Roda, updated for new feature releases of Roda.
7
- RodaMinorVersion = 31
7
+ RodaMinorVersion = 32
8
8
 
9
9
  # The patch version of Roda, updated only for bug fixes from the last
10
10
  # feature release.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: roda
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.31.0
4
+ version: 3.32.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Evans
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-15 00:00:00.000000000 Z
11
+ date: 2020-05-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -207,6 +207,7 @@ extra_rdoc_files:
207
207
  - doc/release_notes/3.29.0.txt
208
208
  - doc/release_notes/3.30.0.txt
209
209
  - doc/release_notes/3.31.0.txt
210
+ - doc/release_notes/3.32.0.txt
210
211
  files:
211
212
  - CHANGELOG
212
213
  - MIT-LICENSE
@@ -239,6 +240,7 @@ files:
239
240
  - doc/release_notes/3.3.0.txt
240
241
  - doc/release_notes/3.30.0.txt
241
242
  - doc/release_notes/3.31.0.txt
243
+ - doc/release_notes/3.32.0.txt
242
244
  - doc/release_notes/3.4.0.txt
243
245
  - doc/release_notes/3.5.0.txt
244
246
  - doc/release_notes/3.6.0.txt