fortitude 0.0.4 → 0.0.5

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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +19 -19
  3. data/CHANGES.md +31 -0
  4. data/Gemfile +1 -0
  5. data/README-erector.md +1 -1
  6. data/lib/fortitude/erector.rb +32 -0
  7. data/lib/fortitude/method_templates/tag_method_template.rb.smpl +6 -6
  8. data/lib/fortitude/method_templates/text_method_template.rb.smpl +3 -3
  9. data/lib/fortitude/rails/railtie.rb +6 -4
  10. data/lib/fortitude/rails/renderer.rb +7 -4
  11. data/lib/fortitude/rails/template_handler.rb +18 -3
  12. data/lib/fortitude/rendering_context.rb +20 -2
  13. data/lib/fortitude/tags/render_widget_placeholder.rb +19 -0
  14. data/lib/fortitude/tags/tag.rb +18 -4
  15. data/lib/fortitude/tags/tag_return_value.rb +1 -1
  16. data/lib/fortitude/tags/tag_store.rb +4 -0
  17. data/lib/fortitude/tilt/fortitude_template.rb +6 -128
  18. data/lib/fortitude/version.rb +1 -1
  19. data/lib/fortitude/widget.rb +2 -0
  20. data/lib/fortitude/widget/files.rb +162 -0
  21. data/lib/fortitude/widget/integration.rb +5 -3
  22. data/lib/fortitude/widget/modules_and_subclasses.rb +17 -0
  23. data/lib/fortitude/widget/rendering.rb +12 -5
  24. data/lib/fortitude/widget/start_and_end_comments.rb +4 -2
  25. data/lib/fortitude/widget/tags.rb +6 -1
  26. data/lib/fortitude/widget/widget_class_inheritable_attributes.rb +7 -0
  27. data/spec/helpers/rails_server.rb +4 -0
  28. data/spec/rails/basic_rails_system_spec.rb +4 -0
  29. data/spec/rails/erector_coexistence_system_spec.rb +33 -0
  30. data/spec/rails/rendering_context_system_spec.rb +19 -3
  31. data/spec/rails/rendering_system_spec.rb +6 -0
  32. data/spec/rails/templates/basic_rails_system_spec/app/controllers/basic_rails_system_spec_controller.rb +5 -0
  33. data/spec/rails/templates/basic_rails_system_spec/app/views/basic_rails_system_spec/double_render_one.rb +5 -0
  34. data/spec/rails/templates/basic_rails_system_spec/app/views/basic_rails_system_spec/double_render_three.rb +5 -0
  35. data/spec/rails/templates/basic_rails_system_spec/app/views/basic_rails_system_spec/double_render_two.rb +9 -0
  36. data/spec/rails/templates/erector_coexistence_system_spec/app/controllers/erector_coexistence_system_spec_controller.rb +19 -0
  37. data/spec/rails/templates/erector_coexistence_system_spec/app/v/views/erector_coexistence_system_spec/erector_widget_in_app_v_views.rb +7 -0
  38. data/spec/rails/templates/erector_coexistence_system_spec/app/v/views/erector_coexistence_system_spec/fortitude_widget_in_app_v_views.rb +7 -0
  39. data/spec/rails/templates/erector_coexistence_system_spec/app/views/erector_coexistence_system_spec/erector_widget_in_app_views.rb +7 -0
  40. data/spec/rails/templates/erector_coexistence_system_spec/app/views/erector_coexistence_system_spec/fortitude_widget_in_app_views.rb +7 -0
  41. data/spec/rails/templates/erector_coexistence_system_spec/config/application.rb +25 -0
  42. data/spec/rails/templates/rendering_context_system_spec/app/controllers/rendering_context_system_spec_controller.rb +2 -2
  43. data/spec/rails/templates/rendering_context_system_spec/app/views/rendering_context_system_spec/_current_element_nesting_intermediate.html.erb +3 -0
  44. data/spec/rails/templates/rendering_context_system_spec/app/views/rendering_context_system_spec/current_element_nesting_child.rb +13 -0
  45. data/spec/rails/templates/rendering_context_system_spec/app/views/rendering_context_system_spec/current_element_nesting_toplevel.rb +9 -0
  46. data/spec/rails/templates/rendering_context_system_spec/app/views/rendering_context_system_spec/start_end_widget_through_partials.rb +2 -2
  47. data/spec/system/convenience_methods_system_spec.rb +22 -0
  48. data/spec/system/inline_system_spec.rb +2 -2
  49. data/spec/system/record_tag_emission_system_spec.rb +71 -0
  50. data/spec/system/rendering_context_system_spec.rb +21 -0
  51. data/spec/system/setting_inheritance_system_spec.rb +52 -0
  52. data/spec/system/tag_return_value_system_spec.rb +7 -0
  53. data/spec/system/tilt_system_spec.rb +13 -18
  54. data/spec/system/widget_class_from_spec.rb +240 -0
  55. data/spec/system/widget_method_system_spec.rb +52 -0
  56. metadata +37 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 25c2a3082f9eea925e6db1ad349f3d9ec45a9760
4
- data.tar.gz: 4a95b0676e6b63b98ca69148bedc517b98b4955f
3
+ metadata.gz: b8fe2be7aaffdb2b3e57d0b26fdacbc2c1124a57
4
+ data.tar.gz: 01ada85328794df979d33ccff7a2ea41f88425f3
5
5
  SHA512:
6
- metadata.gz: 88825dbca457537fb59373f3d345e119cd4b26d099befb5b56cea5885bf912161ff589775504657423e6b82b4852d7fead44df625af14bd226089dd644944ca2
7
- data.tar.gz: 8bca6d9fa509fa98cc8abe0c630a790f9ff2f7b98544096e147aa986367332a08408b6d252533f7894552d24963f76b8d4e83898bf42f91d098035ef4653c28a
6
+ metadata.gz: 7394aeae5282f4109dbbe772a882ae066043a253813fc63b6b4e0d1ebdabb31de3e998a66969c347b37262c3a3365af2d6a1bf084e15ed9a8f9a6afa9c672ff5
7
+ data.tar.gz: 58b2ad3cdddd71f0120f9039ab9112ecaa4fc542c2104e98565341898e36c6b247dd7c60c07f39cee47d4fb5c47f95f11b0d27bbb75a605050c41fe47d38bd51
@@ -3,14 +3,14 @@ rvm:
3
3
  - "1.9.3"
4
4
  - "2.0.0"
5
5
  - "2.1.2"
6
- - "jruby-1.7.12"
6
+ - "jruby-1.7.15"
7
7
  env:
8
- - FORTITUDE_SPECS_RAILS_VERSION=4.1.1
9
- - FORTITUDE_SPECS_RAILS_VERSION=4.0.5
10
- - FORTITUDE_SPECS_RAILS_VERSION=3.2.18
8
+ - FORTITUDE_SPECS_RAILS_VERSION=4.1.6
9
+ - FORTITUDE_SPECS_RAILS_VERSION=4.0.10
10
+ - FORTITUDE_SPECS_RAILS_VERSION=3.2.19
11
11
  - FORTITUDE_SPECS_RAILS_VERSION=3.1.12
12
12
  - FORTITUDE_SPECS_RAILS_VERSION=3.0.20
13
- - FORTITUDE_NATIVE_EXTENSIONS=false FORTITUDE_SPECS_RAILS_VERSION=4.1.1
13
+ - FORTITUDE_NATIVE_EXTENSIONS=false FORTITUDE_SPECS_RAILS_VERSION=4.1.6
14
14
  - FORTITUDE_NATIVE_EXTENSIONS=false FORTITUDE_SPECS_RAILS_VERSION=3.0.20
15
15
  before_script:
16
16
  - export JRUBY_OPTS="$JRUBY_OPTS -J-Xmx128m -J-Xms128m -J-Xss2048k"
@@ -18,11 +18,11 @@ matrix:
18
18
  exclude:
19
19
  # Rails 4.x doesn't support Ruby 1.8.7
20
20
  - rvm: 1.8.7
21
- env: FORTITUDE_SPECS_RAILS_VERSION=4.1.1
21
+ env: FORTITUDE_SPECS_RAILS_VERSION=4.1.6
22
22
  - rvm: 1.8.7
23
- env: FORTITUDE_NATIVE_EXTENSIONS=false FORTITUDE_SPECS_RAILS_VERSION=4.1.1
23
+ env: FORTITUDE_NATIVE_EXTENSIONS=false FORTITUDE_SPECS_RAILS_VERSION=4.1.6
24
24
  - rvm: 1.8.7
25
- env: FORTITUDE_SPECS_RAILS_VERSION=4.0.5
25
+ env: FORTITUDE_SPECS_RAILS_VERSION=4.0.10
26
26
  # 2014-06-19 ageweke -- ARGH. After trying about seventeen different things, no matter what I do,
27
27
  # Travis fails JRuby builds about 20% of the time with "Killed". Their documentation indicates that this
28
28
  # is likely an out-of-memory issue (i.e., entire VM's memory is consumed). However, I'm running JRuby with
@@ -34,17 +34,17 @@ matrix:
34
34
  # one manually to make sure there aren't other failures, too. This is very frustrating, but I can't seem to
35
35
  # find a way around it. If there's a fix out there somewhere, I'm all ears!
36
36
  allow_failures:
37
- - rvm: jruby-1.7.12
38
- env: FORTITUDE_SPECS_RAILS_VERSION=4.1.1
39
- - rvm: jruby-1.7.12
40
- env: FORTITUDE_SPECS_RAILS_VERSION=4.0.5
41
- - rvm: jruby-1.7.12
42
- env: FORTITUDE_SPECS_RAILS_VERSION=3.2.18
43
- - rvm: jruby-1.7.12
37
+ - rvm: jruby-1.7.15
38
+ env: FORTITUDE_SPECS_RAILS_VERSION=4.1.6
39
+ - rvm: jruby-1.7.15
40
+ env: FORTITUDE_SPECS_RAILS_VERSION=4.0.10
41
+ - rvm: jruby-1.7.15
42
+ env: FORTITUDE_SPECS_RAILS_VERSION=3.2.19
43
+ - rvm: jruby-1.7.15
44
44
  env: FORTITUDE_SPECS_RAILS_VERSION=3.1.12
45
- - rvm: jruby-1.7.12
45
+ - rvm: jruby-1.7.15
46
46
  env: FORTITUDE_SPECS_RAILS_VERSION=3.0.20
47
- - rvm: jruby-1.7.12
48
- env: FORTITUDE_NATIVE_EXTENSIONS=false FORTITUDE_SPECS_RAILS_VERSION=4.1.1
49
- - rvm: jruby-1.7.12
47
+ - rvm: jruby-1.7.15
48
+ env: FORTITUDE_NATIVE_EXTENSIONS=false FORTITUDE_SPECS_RAILS_VERSION=4.1.6
49
+ - rvm: jruby-1.7.15
50
50
  env: FORTITUDE_NATIVE_EXTENSIONS=false FORTITUDE_SPECS_RAILS_VERSION=3.0.20
data/CHANGES.md CHANGED
@@ -1,5 +1,36 @@
1
1
  # Fortitude Releases
2
2
 
3
+ ## 0.0.5, 22 September 2014
4
+
5
+ * You can now load both Fortitude and Erector at the same time into a project, and it will "just work": Erector
6
+ widgets will render using Erector, and Fortitude widgets will render using Fortitude. (Fortitude takes over the
7
+ actual template engine registration for `.rb` files, and uses a trick to keep Erector from displacing it; it then
8
+ looks at the widget class being rendered, and delegates all Erector rendering directly to Erector.)
9
+ * When inside a widget, you can now render a sub-widget using `widget MyWidget.new(...)` — _i.e._, passing an
10
+ actual widget instance — or using `widget MyWidget, { :param1 => value1 }` — _i.e._, passing a widget
11
+ class and a `Hash` of assignments (which can be omitted if the widget doesn't have any `need`s).
12
+ * Fixed an issue where, _e.g._, calling `#render_to_string` on a Fortitude widget within a Rails controller, and then
13
+ also rendering a Fortitude widget as the template for that action, would cause a method to be called on `nil`.
14
+ * Added `Fortitude::RenderingContext#parent_widget`, which returns the parent widget of the current widget during
15
+ rendering at runtime. (In other words, this is not the superclass of the current widget, but the widget that caused
16
+ this widget to get rendered, using either `Fortitude::Widget#widget` or `render :partial => ...`.) This can, of
17
+ course, be `nil` if there is no current parent widget.
18
+ * Added `Fortitude::Widget.all_fortitude_superclasses`, which returns an `Array` of all superclasses of a widget up to,
19
+ but not including, `Fortitude::Widget` itself.
20
+ * Added `Fortitude::Widget.widget_class_from_file`, which accepts the path to a file and an array of "root" directories
21
+ to look under (_i.e._, assuming you're using something like Rails' autoloading mechanism), and returns the `Class`
22
+ object for the widget that's contained in that file. This uses a series of mechansims to try to detect the class
23
+ that's present in the file: a "magic comment" that can be present in the file, an array of class names to try
24
+ that you can pass in, the position of the class in the file hierarchy, and scanning the source text itself.
25
+ * Added a `record_tag_emission` class-level setting that tells a widget to call `#emitting_tag!` on the
26
+ `Fortitude::RenderingContext` when emitting a tag; you can use this to build various systems that need to know where
27
+ in the hierarchy of tags we are at the moment.
28
+ * The object being returned from Fortitude tag methods — which, in general, you should never use — now
29
+ inherits from `Object`, not `BasicObject`, so that some built-in methods like `#is_a?` can be safely called on it.
30
+ This is for use in some users' environments doing funny things with the Ruby runtime that end up calling methods
31
+ like that on the return values of widget `#content` methods, which very often just end up being the tag return
32
+ value object.
33
+
3
34
  ## 0.0.4, 24 June 2014
4
35
 
5
36
  * Added support for building a JRuby-specific gem to the gemspec, so that things work smoothly for JRuby users.
data/Gemfile CHANGED
@@ -3,3 +3,4 @@ source 'https://rubygems.org'
3
3
  # Specify your gem's dependencies in fortitude.gemspec
4
4
  gemspec
5
5
 
6
+ gem 'erector'
@@ -18,7 +18,7 @@ garbage as ERb/Erubis);
18
18
  * Full, complete native HTML5 support (with selectable X/HTML4.01 Strict/Transitional/Frameset doctypes);
19
19
  * Enforces HTML element-nesting and attribute-name rules, and enforce ID uniqueness across a page (configurable, and off by default);
20
20
  * In development, beautiful HTML comments around each widget, showing what class is being rendered, the values of all variables supplied to that class, and the nesting depth of that widget;
21
- * Fully compatible with Ruby 1.8.7-2.1.x, JRuby 1.7.11, and Rails 3.0.x-4.1.x;
21
+ * Fully compatible with Ruby 1.8.7-2.1.x, JRuby 1.7.15, and Rails 3.0.x-4.1.x;
22
22
  * Full Tilt support, and can be used with or without Rails;
23
23
  * Much more thorough Rails support — all known Rails integration points have been resolved, and it should work
24
24
  as smoothly with Rails as does (_e.g._) ERb/Erubis;
@@ -0,0 +1,32 @@
1
+ module Fortitude
2
+ module Erector
3
+ class << self
4
+ def is_erector_available?
5
+ @is_erector_available ||= begin
6
+ begin
7
+ gem 'erector'
8
+ rescue Gem::LoadError => le
9
+ # ok
10
+ end
11
+
12
+ begin
13
+ require 'erector'
14
+ rescue LoadError => le
15
+ # ok
16
+ end
17
+
18
+ if defined?(::Erector::Widget) then :yes else :no end
19
+ end
20
+
21
+ @is_erector_available == :yes
22
+ end
23
+
24
+ def is_erector_widget_class?(widget_class)
25
+ return false unless is_erector_available?
26
+ return true if widget_class == ::Erector::Widget
27
+ return false if widget_class == ::Object
28
+ return is_erector_widget_class?(widget_class.superclass)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -1,9 +1,9 @@
1
1
  def #{method_name}(content_or_attributes = nil, attributes = nil)
2
2
  o = @_fortitude_output_buffer_holder.output_buffer
3
- rc = @_fortitude_rendering_context # :if needs_element_rules || needs_formatting
3
+ rc = @_fortitude_rendering_context # :if record_emitting_tag || needs_formatting
4
4
 
5
- this_tag = #{tag_object_const} # :if needs_element_rules || needs_attribute_rules || needs_id_uniqueness
6
- rc.record_tag(self, this_tag) do # :if needs_element_rules
5
+ this_tag = #{tag_object_const} # :if record_emitting_tag || needs_attribute_rules || needs_id_uniqueness
6
+ rc.emitting_tag!(self, this_tag, content_or_attributes, attributes) do # :if record_emitting_tag
7
7
  format_output = rc.format_output? # :if needs_formatting
8
8
  if format_output # :if needs_formatting
9
9
  rc.needs_newline! # :if needs_formatting && newline_before
@@ -36,7 +36,7 @@ def #{method_name}(content_or_attributes = nil, attributes = nil)
36
36
  elsif (! attributes)
37
37
  _fortitude_raise_no_content_allowed_error(#{tag_object_const}) # :if ! content_allowed
38
38
  o.#{concat_method}(#{open_const})
39
- rc.record_tag(self, FORTITUDE_TEXT_PSEUDOTAG) { } unless content_or_attributes.instance_variable_get("@html_safe") # :if needs_element_rules
39
+ rc.emitting_tag!(self, FORTITUDE_TEXT_PSEUDOTAG, content_or_attributes, nil) { } unless content_or_attributes.instance_variable_get("@html_safe") # :if record_emitting_tag
40
40
  content_or_attributes.to_s.fortitude_append_escaped_string(o) # :if escape_direct_content
41
41
  o.#{concat_method}(content_or_attributes.to_s) # :if ! escape_direct_content
42
42
  if block_given?
@@ -52,7 +52,7 @@ def #{method_name}(content_or_attributes = nil, attributes = nil)
52
52
  attributes.fortitude_append_as_attributes(o, nil)
53
53
  o.#{concat_method}(#{partial_open_end_const})
54
54
 
55
- rc.record_tag(self, FORTITUDE_TEXT_PSEUDOTAG) { } unless content_or_attributes.instance_variable_get("@html_safe") # :if needs_element_rules
55
+ rc.emitting_tag!(self, FORTITUDE_TEXT_PSEUDOTAG, content_or_attributes, nil) { } unless content_or_attributes.instance_variable_get("@html_safe") # :if record_emitting_tag
56
56
  content_or_attributes.to_s.fortitude_append_escaped_string(o) # :if escape_direct_content
57
57
  o.#{concat_method}(content_or_attributes.to_s) # :if ! escape_direct_content
58
58
  if block_given?
@@ -62,7 +62,7 @@ def #{method_name}(content_or_attributes = nil, attributes = nil)
62
62
  o.#{concat_method}(#{close_const})
63
63
  end
64
64
  rc.needs_newline! if format_output # :if needs_formatting && newline_before
65
- end # :if needs_element_rules
65
+ end # :if record_emitting_tag
66
66
 
67
67
  FORTITUDE_NO_RETURN_VALUE_FROM_TAGS
68
68
  end
@@ -1,9 +1,9 @@
1
1
  def tag_text(s)
2
2
  @_fortitude_rendering_context.about_to_output_non_whitespace! # :if format_output
3
3
 
4
- unless s.instance_variable_get("@html_safe") # :if needs_element_rules
5
- @_fortitude_rendering_context.record_tag(self, FORTITUDE_TEXT_PSEUDOTAG) { } # :if needs_element_rules
6
- end # :if needs_element_rules
4
+ unless s.instance_variable_get("@html_safe") # :if record_emitting_tag
5
+ @_fortitude_rendering_context.emitting_tag!(self, FORTITUDE_TEXT_PSEUDOTAG, s, nil) { } # :if record_emitting_tag
6
+ end # :if record_emitting_tag
7
7
 
8
8
  s.to_s.fortitude_append_escaped_string(@_fortitude_output_buffer_holder.output_buffer)
9
9
  end
@@ -197,8 +197,10 @@ module Fortitude
197
197
  # So, instead, we simply transform <tt>render :widget => ...</tt> into a <tt>render :text => ...</tt> of the
198
198
  # widget's output, and let Rails take it away from there.
199
199
  ::ActionController::Base.class_eval do
200
- def fortitude_rendering_context(options)
201
- @_fortitude_rendering_context ||= create_fortitude_rendering_context(options)
200
+ def fortitude_rendering_context_for(delegate_object, yield_block)
201
+ @_fortitude_rendering_contexts ||= { }
202
+ @_fortitude_rendering_contexts[delegate_object.object_id] ||= create_fortitude_rendering_context(
203
+ :delegate_object => delegate_object, :yield_block => yield_block)
202
204
  end
203
205
 
204
206
  def create_fortitude_rendering_context(options)
@@ -208,7 +210,7 @@ module Fortitude
208
210
  def render_with_fortitude(*args, &block)
209
211
  if (options = args[0]).kind_of?(Hash)
210
212
  if (widget = options[:widget])
211
- rendering_context = fortitude_rendering_context(:delegate_object => self)
213
+ rendering_context = fortitude_rendering_context_for(self, nil)
212
214
  widget.render_to(rendering_context)
213
215
 
214
216
  options = options.dup
@@ -220,7 +222,7 @@ module Fortitude
220
222
  elsif (widget_block = options[:inline]) && (options[:type] == :fortitude)
221
223
  options.delete(:inline)
222
224
 
223
- rendering_context = fortitude_rendering_context(:delegate_object => self)
225
+ rendering_context = fortitude_rendering_context_for(self, nil)
224
226
  widget_class = Class.new(Fortitude::Widgets::Html5)
225
227
  widget_class.use_instance_variables_for_assigns(true)
226
228
  widget_class.extra_assigns(:use)
@@ -1,4 +1,5 @@
1
1
  require 'fortitude/rendering_context'
2
+ require 'fortitude/erector'
2
3
 
3
4
  ::ActiveSupport::SafeBuffer.class_eval do
4
5
  alias_method :fortitude_concat, :original_concat
@@ -10,7 +11,11 @@ module Fortitude
10
11
  class Renderer
11
12
  class << self
12
13
  # TODO: Refactor this and render :widget => ... support into one method somewhere.
13
- def render(widget_class, template_handler, local_assigns, &block)
14
+ def render(widget_class, template_handler, local_assigns, is_partial, &block)
15
+ if ::Fortitude::Erector.is_erector_widget_class?(widget_class)
16
+ return ::Erector::Rails.render(widget_class, template_handler, local_assigns, is_partial, &block)
17
+ end
18
+
14
19
  total_assigns = template_handler.assigns.symbolize_keys.merge(local_assigns.symbolize_keys)
15
20
 
16
21
  needed_assigns = if widget_class.extra_assigns == :use
@@ -21,9 +26,7 @@ module Fortitude
21
26
 
22
27
  widget = widget_class.new(needed_assigns)
23
28
  template_handler.with_output_buffer do
24
- rendering_context_options = { :delegate_object => template_handler, :yield_block => block }
25
- controller = template_handler.controller
26
- rendering_context = controller.fortitude_rendering_context(rendering_context_options)
29
+ rendering_context = template_handler.controller.fortitude_rendering_context_for(template_handler, block)
27
30
 
28
31
  # TODO: Refactor this -- both passing it into the constructor and setting yield_block here is gross.
29
32
  #
@@ -6,10 +6,10 @@ module Fortitude
6
6
  def call(template, &block)
7
7
  require_dependency template.identifier
8
8
  widget_class_name = "views/#{template.identifier =~ %r(views/([^.]*)(\..*)?\.rb) && $1}".camelize
9
- is_partial = File.basename(template.identifier) =~ /^_/
9
+ is_partial = !! (File.basename(template.identifier) =~ /^_/)
10
10
 
11
11
  <<-SRC
12
- Fortitude::Rails::Renderer.render(#{widget_class_name}, self, local_assigns) { |*args| yield *args }
12
+ Fortitude::Rails::Renderer.render(#{widget_class_name}, self, local_assigns, #{is_partial.inspect}) { |*args| yield *args }
13
13
  SRC
14
14
  end
15
15
 
@@ -20,4 +20,19 @@ module Fortitude
20
20
  end
21
21
  end
22
22
 
23
- ActionView::Template.register_template_handler :rb, Fortitude::Rails::TemplateHandler.new
23
+ ::ActionView::Template.class_eval do
24
+ class << self
25
+ def _fortitude_register_template_handler!
26
+ register_template_handler_without_fortitude(:rb, Fortitude::Rails::TemplateHandler.new)
27
+ end
28
+
29
+ def register_template_handler_with_fortitude(*args, &block)
30
+ register_template_handler_without_fortitude(*args, &block)
31
+ ActionView::Template._fortitude_register_template_handler!
32
+ end
33
+
34
+ alias_method_chain :register_template_handler, :fortitude
35
+ end
36
+ end
37
+
38
+ ActionView::Template._fortitude_register_template_handler!
@@ -1,4 +1,5 @@
1
1
  require 'fortitude/support/instance_variable_set'
2
+ require 'fortitude/tags/render_widget_placeholder'
2
3
 
3
4
  module Fortitude
4
5
  class RenderingContext
@@ -66,9 +67,14 @@ module Fortitude
66
67
  !! @attribute_validation_disabled
67
68
  end
68
69
 
70
+ def record_render(args, &block)
71
+ record_widget(::Fortitude::Tags::RenderWidgetPlaceholder.new(args), &block)
72
+ end
73
+
69
74
  def record_widget(widget)
70
75
  start_widget!(widget)
71
76
  @current_widget_nesting << widget
77
+ @current_element_nesting << widget
72
78
  begin
73
79
  yield
74
80
  ensure
@@ -76,6 +82,10 @@ module Fortitude
76
82
  unless last.equal?(widget)
77
83
  raise "Something horrible happened -- the last widget we started was #{last}, but now we're ending #{widget}?!?"
78
84
  end
85
+ last = @current_element_nesting.pop
86
+ unless last.equal?(widget)
87
+ raise "Something horrible happened -- the last element we started was #{last}, but now we're ending #{widget}?!?"
88
+ end
79
89
  end_widget!(widget)
80
90
  end
81
91
  end
@@ -92,8 +102,12 @@ module Fortitude
92
102
  @current_widget_nesting.length - 1
93
103
  end
94
104
 
95
- def record_tag(widget, tag_object)
96
- validate_element_for_rules(widget, tag_object)
105
+ def parent_widget
106
+ @current_widget_nesting[-2]
107
+ end
108
+
109
+ def emitting_tag!(widget, tag_object, content_or_attributes, attributes)
110
+ validate_element_for_rules(widget, tag_object) if widget.class.enforce_element_nesting_rules
97
111
  @current_element_nesting << tag_object
98
112
 
99
113
  begin
@@ -106,6 +120,10 @@ module Fortitude
106
120
  end
107
121
  end
108
122
 
123
+ def current_element_nesting
124
+ @current_element_nesting
125
+ end
126
+
109
127
  def format_output?
110
128
  true
111
129
  end
@@ -0,0 +1,19 @@
1
+ module Fortitude
2
+ module Tags
3
+ class RenderWidgetPlaceholder
4
+ attr_reader :render_args
5
+
6
+ def initialize(render_args)
7
+ @render_args = render_args
8
+ end
9
+
10
+ def name
11
+ :_fortitude_render_widget_placeholder
12
+ end
13
+
14
+ def validate_can_enclose!(widget, tag_object)
15
+ # nothing here, always OK
16
+ end
17
+ end
18
+ end
19
+ end
@@ -116,7 +116,9 @@ module Fortitude
116
116
  end
117
117
 
118
118
  def define_method_on!(mod, options = {})
119
- options.assert_valid_keys(:enforce_element_nesting_rules, :enforce_attribute_rules, :enable_formatting, :enforce_id_uniqueness, :close_void_tags)
119
+ options.assert_valid_keys(
120
+ :record_emitting_tag, :enforce_attribute_rules, :enable_formatting,
121
+ :enforce_id_uniqueness, :close_void_tags)
120
122
 
121
123
  unless mod.respond_to?(:fortitude_tag_support_included?) && mod.fortitude_tag_support_included?
122
124
  mod.send(:include, ::Fortitude::Tags::TagSupport)
@@ -147,8 +149,8 @@ module Fortitude
147
149
  end
148
150
 
149
151
  text = Fortitude::MethodTemplates::SimpleTemplate.template('tag_method_template').result(
150
- :name => name.to_s, :method_name => "tag_#{name}".to_s, :yield_call => yield_call, :concat_method => CONCAT_METHOD,
151
- :needs_element_rules => !! options[:enforce_element_nesting_rules],
152
+ :name => name.to_s, :method_name => generated_method_name.to_s, :yield_call => yield_call, :concat_method => CONCAT_METHOD,
153
+ :record_emitting_tag => (!! options[:record_emitting_tag]),
152
154
  :needs_attribute_rules => !! options[:enforce_attribute_rules],
153
155
  :needs_id_uniqueness => !! options[:enforce_id_uniqueness],
154
156
  :needs_formatting => needs_formatting, :content_allowed => @content_allowed,
@@ -160,7 +162,19 @@ module Fortitude
160
162
  :partial_open_alone_end_const => tag_constant_name(:PARTIAL_OPEN_ALONE_END))
161
163
 
162
164
  mod.module_eval(text)
163
- mod.alias_method(name, "tag_#{name}")
165
+ aliased_method_names.each { |an| mod.alias_method(an, generated_method_name) }
166
+ end
167
+
168
+ def generated_method_name
169
+ "tag_#{name}"
170
+ end
171
+
172
+ def aliased_method_names
173
+ [ name ]
174
+ end
175
+
176
+ def all_method_names
177
+ [ generated_method_name ] + aliased_method_names
164
178
  end
165
179
 
166
180
  private
@@ -2,7 +2,7 @@ require 'fortitude/errors'
2
2
 
3
3
  module Fortitude
4
4
  module Tags
5
- TAG_RETURN_VALUE_SUPERCLASS = if defined?(::BasicObject) then ::BasicObject else ::Object end
5
+ TAG_RETURN_VALUE_SUPERCLASS = ::Object
6
6
 
7
7
  class TagReturnValue < TAG_RETURN_VALUE_SUPERCLASS
8
8
  def method_missing(name, *args)
@@ -37,6 +37,10 @@ module Fortitude
37
37
  out
38
38
  end
39
39
 
40
+ def tag_names
41
+ tags.keys
42
+ end
43
+
40
44
  def tags_added!(tags)
41
45
  tags_changed!(tags)
42
46
  end