fortitude 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +26 -2
  3. data/CHANGES.md +29 -0
  4. data/lib/fortitude.rb +6 -92
  5. data/lib/fortitude/doctypes.rb +6 -4
  6. data/lib/fortitude/doctypes/base.rb +6 -2
  7. data/lib/fortitude/doctypes/html4.rb +2 -1
  8. data/lib/fortitude/doctypes/html4_frameset.rb +2 -0
  9. data/lib/fortitude/doctypes/html4_strict.rb +1 -0
  10. data/lib/fortitude/doctypes/html4_tags_frameset.rb +3 -2
  11. data/lib/fortitude/doctypes/html4_tags_strict.rb +3 -2
  12. data/lib/fortitude/doctypes/html4_tags_transitional.rb +3 -2
  13. data/lib/fortitude/doctypes/html4_transitional.rb +1 -0
  14. data/lib/fortitude/doctypes/html5.rb +3 -2
  15. data/lib/fortitude/doctypes/unknown_doctype.rb +1 -0
  16. data/lib/fortitude/doctypes/xhtml10.rb +2 -1
  17. data/lib/fortitude/doctypes/xhtml10_frameset.rb +1 -0
  18. data/lib/fortitude/doctypes/xhtml10_strict.rb +1 -0
  19. data/lib/fortitude/doctypes/xhtml10_transitional.rb +1 -0
  20. data/lib/fortitude/doctypes/xhtml11.rb +2 -1
  21. data/lib/fortitude/{fortitude_ruby_ext.rb → extensions/fortitude_ruby_ext.rb} +16 -11
  22. data/lib/fortitude/extensions/native_extensions.rb +33 -0
  23. data/lib/fortitude/{assign_locals_from_template.rb.smpl → method_templates/assign_locals_from_template.rb.smpl} +0 -0
  24. data/lib/fortitude/{need_assignment_template.rb.smpl → method_templates/need_assignment_template.rb.smpl} +0 -0
  25. data/lib/fortitude/{need_method_template.rb.smpl → method_templates/need_method_template.rb.smpl} +0 -0
  26. data/lib/fortitude/method_templates/simple_template.rb +50 -0
  27. data/lib/fortitude/{tag_method_template.rb.smpl → method_templates/tag_method_template.rb.smpl} +0 -0
  28. data/lib/fortitude/{text_method_template.rb.smpl → method_templates/text_method_template.rb.smpl} +0 -0
  29. data/lib/fortitude/rails.rb +26 -0
  30. data/lib/fortitude/rails/railtie.rb +256 -0
  31. data/lib/fortitude/rails/widget_methods.rb +0 -4
  32. data/lib/fortitude/rendering_context.rb +2 -2
  33. data/lib/fortitude/support/assigns_proxy.rb +77 -0
  34. data/lib/fortitude/support/class_inheritable_attributes.rb +98 -0
  35. data/lib/fortitude/support/instance_variable_set.rb +76 -0
  36. data/lib/fortitude/support/staticized_method.rb +87 -0
  37. data/lib/fortitude/tags/partial_tag_placeholder.rb +19 -0
  38. data/lib/fortitude/tags/tag.rb +189 -0
  39. data/lib/fortitude/tags/tag_return_value.rb +13 -0
  40. data/lib/fortitude/tags/tag_store.rb +53 -0
  41. data/lib/fortitude/tags/tag_support.rb +51 -0
  42. data/lib/fortitude/tags/tags_module.rb +16 -0
  43. data/lib/fortitude/tilt.rb +17 -0
  44. data/lib/fortitude/tilt/fortitude_template.rb +13 -13
  45. data/lib/fortitude/version.rb +1 -1
  46. data/lib/fortitude/widget.rb +36 -886
  47. data/lib/fortitude/widget/around_content.rb +53 -0
  48. data/lib/fortitude/widget/capturing.rb +37 -0
  49. data/lib/fortitude/widget/content.rb +51 -0
  50. data/lib/fortitude/widget/doctypes.rb +53 -0
  51. data/lib/fortitude/widget/helpers.rb +62 -0
  52. data/lib/fortitude/widget/integration.rb +76 -0
  53. data/lib/fortitude/widget/localization.rb +63 -0
  54. data/lib/fortitude/widget/modules_and_subclasses.rb +58 -0
  55. data/lib/fortitude/widget/needs.rb +164 -0
  56. data/lib/fortitude/widget/non_rails_widget_methods.rb +13 -0
  57. data/lib/fortitude/widget/rendering.rb +93 -0
  58. data/lib/fortitude/widget/start_and_end_comments.rb +69 -0
  59. data/lib/fortitude/widget/staticization.rb +50 -0
  60. data/lib/fortitude/widget/tag_like_methods.rb +102 -0
  61. data/lib/fortitude/widget/tags.rb +55 -0
  62. data/lib/fortitude/widget/temporary_overrides.rb +28 -0
  63. data/lib/fortitude/widget/widget_class_inheritable_attributes.rb +35 -0
  64. data/lib/fortitude/widgets.rb +12 -0
  65. data/lib/fortitude_jruby_native_ext.jar +0 -0
  66. data/spec/helpers/system_helpers.rb +3 -3
  67. data/spec/system/attribute_rules_system_spec.rb +9 -9
  68. data/spec/system/doctypes_system_spec.rb +15 -0
  69. data/spec/system/escaping_system_spec.rb +2 -2
  70. data/spec/system/formatting_system_spec.rb +2 -2
  71. data/spec/system/id_uniqueness_system_spec.rb +5 -5
  72. data/spec/system/method_precedence_system_spec.rb +1 -1
  73. data/spec/system/needs_system_spec.rb +13 -0
  74. data/spec/system/setting_inheritance_system_spec.rb +20 -20
  75. data/spec/system/tag_rendering_system_spec.rb +27 -20
  76. data/spec/system/tag_rules_system_spec.rb +1 -1
  77. data/spec/system/tag_updating_system_spec.rb +3 -3
  78. data/spec/system/tilt_system_spec.rb +4 -0
  79. data/spec/system/void_tags_system_spec.rb +44 -5
  80. metadata +42 -21
  81. data/lib/fortitude/assigns_proxy.rb +0 -75
  82. data/lib/fortitude/class_inheritable_attributes.rb +0 -96
  83. data/lib/fortitude/instance_variable_set.rb +0 -74
  84. data/lib/fortitude/non_rails_widget_methods.rb +0 -15
  85. data/lib/fortitude/partial_tag_placeholder.rb +0 -17
  86. data/lib/fortitude/railtie.rb +0 -254
  87. data/lib/fortitude/simple_template.rb +0 -45
  88. data/lib/fortitude/staticized_method.rb +0 -85
  89. data/lib/fortitude/tag.rb +0 -162
  90. data/lib/fortitude/tag_return_value.rb +0 -11
  91. data/lib/fortitude/tag_store.rb +0 -48
  92. data/lib/fortitude/tag_support.rb +0 -48
  93. data/lib/fortitude/tags_module.rb +0 -14
@@ -0,0 +1,53 @@
1
+ require 'active_support'
2
+ require 'active_support/concern'
3
+
4
+ module Fortitude
5
+ class Widget
6
+ module AroundContent
7
+ extend ActiveSupport::Concern
8
+
9
+ module ClassMethods
10
+ # PUBLIC API
11
+ def around_content(*method_names)
12
+ return if method_names.length == 0
13
+ @_fortitude_around_content_methods ||= [ ]
14
+ @_fortitude_around_content_methods += method_names.map { |x| x.to_s.strip.downcase.to_sym }
15
+ rebuild_run_content!(:around_content_added)
16
+ end
17
+
18
+ # PUBLIC API
19
+ def remove_around_content(*method_names)
20
+ options = method_names.extract_options!
21
+ options.assert_valid_keys(:fail_if_not_present)
22
+
23
+ not_found = [ ]
24
+ method_names.each do |method_name|
25
+ not_found << method_name unless (@_fortitude_around_content_methods || [ ]).delete(method_name)
26
+ end
27
+
28
+ rebuild_run_content!(:around_content_removed)
29
+ unless (not_found.length == 0) || (options.has_key?(:fail_if_not_present) && (! options[:fail_if_not_present]))
30
+ raise ArgumentError, "no such methods: #{not_found.inspect}"
31
+ end
32
+ end
33
+
34
+ # INTERNAL USE ONLY
35
+ def around_content_methods
36
+ superclass_methods = if superclass.respond_to?(:around_content_methods)
37
+ superclass.around_content_methods
38
+ else
39
+ [ ]
40
+ end
41
+
42
+ (superclass_methods + this_class_around_content_methods).uniq
43
+ end
44
+
45
+ # INTERNAL USE ONLY
46
+ def this_class_around_content_methods
47
+ @_fortitude_around_content_methods ||= [ ]
48
+ end
49
+ private :this_class_around_content_methods
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,37 @@
1
+ require 'active_support'
2
+ require 'active_support/concern'
3
+
4
+ module Fortitude
5
+ class Widget
6
+ module Capturing
7
+ extend ActiveSupport::Concern
8
+
9
+ # PUBLIC API
10
+ def capture(&block)
11
+ helpers = @_fortitude_rendering_context.helpers_object
12
+ if helpers && helpers.respond_to?(:capture, true) &&
13
+ [ 0, -1 ].include?(helpers.method(:capture).arity)
14
+ helpers.capture(&block)
15
+ else
16
+ _fortitude_builtin_capture(&block)
17
+ end
18
+ end
19
+
20
+ # INTERNAL USE ONLY
21
+ def _fortitude_builtin_capture(&block)
22
+ old_buffer = nil
23
+ new_buffer = nil
24
+ begin
25
+ new_buffer = _fortitude_new_buffer
26
+ old_buffer, @_fortitude_output_buffer_holder.output_buffer = @_fortitude_output_buffer_holder.output_buffer, new_buffer
27
+ _fortitude_new_buffer.force_encoding(old_buffer.encoding) if old_buffer && old_buffer.respond_to?(:encoding)
28
+ block.call
29
+ new_buffer
30
+ ensure
31
+ @_fortitude_output_buffer_holder.output_buffer = old_buffer
32
+ end
33
+ end
34
+ private :_fortitude_builtin_capture
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,51 @@
1
+ require 'active_support'
2
+ require 'active_support/concern'
3
+
4
+ module Fortitude
5
+ class Widget
6
+ module Content
7
+ extend ActiveSupport::Concern
8
+
9
+ module ClassMethods
10
+ # INTERNAL USE ONLY
11
+ def rebuild_run_content!(why, klass = self)
12
+ rebuilding(:run_content, why, klass) do
13
+ acm = around_content_methods
14
+ text = "def run_content(*args, &block)\n"
15
+ text += " out = nil\n"
16
+ acm.each_with_index do |method_name, index|
17
+ text += " " + (" " * index) + "#{method_name}(*args) do\n"
18
+ end
19
+
20
+ if has_localized_content_methods?
21
+ text += " " + (" " * acm.length) + "the_locale = widget_locale\n"
22
+ text += " " + (" " * acm.length) + "locale_method_name = \"localized_content_\#{the_locale}\" if the_locale\n"
23
+ text += " " + (" " * acm.length) + "out = if locale_method_name && respond_to?(locale_method_name)\n"
24
+ text += " " + (" " * acm.length) + " send(locale_method_name, *args, &block)\n"
25
+ text += " " + (" " * acm.length) + "else\n"
26
+ text += " " + (" " * acm.length) + " content(*args, &block)\n"
27
+ text += " " + (" " * acm.length) + "end\n"
28
+ else
29
+ text += " " + (" " * acm.length) + "out = content(*args, &block)\n"
30
+ end
31
+
32
+ (0..(acm.length - 1)).each do |index|
33
+ text += " " + (" " * (acm.length - (index + 1))) + "end\n"
34
+ end
35
+ text += " out\n"
36
+ text += "end"
37
+
38
+ class_eval(text)
39
+
40
+ direct_subclasses.each { |s| s.rebuild_run_content!(why, klass) }
41
+ end
42
+ end
43
+ end
44
+
45
+ # PUBLIC API
46
+ def content
47
+ raise "Must override in #{self.class.name}"
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,53 @@
1
+ require 'active_support'
2
+ require 'active_support/concern'
3
+
4
+ module Fortitude
5
+ class Widget
6
+ module Doctypes
7
+ extend ActiveSupport::Concern
8
+
9
+ # PUBLIC API
10
+ def doctype(s)
11
+ tag_rawtext "<!DOCTYPE #{s}>"
12
+ end
13
+
14
+ # PUBLIC API
15
+ def doctype!
16
+ dt = self.class.doctype
17
+ raise "You must set a doctype at the class level, using something like 'doctype :html5', before you can use this method." unless dt
18
+ dt.declare!(self)
19
+ end
20
+
21
+ module ClassMethods
22
+ # PUBLIC API
23
+ def doctype(new_doctype = nil)
24
+ if new_doctype
25
+ new_doctype = case new_doctype
26
+ when Fortitude::Doctypes::Base then new_doctype
27
+ when Symbol then Fortitude::Doctypes.standard_doctype(new_doctype)
28
+ else raise ArgumentError, "You must supply a Symbol or an instance of Fortitude::Doctypes::Base, not: #{new_doctype.inspect}"
29
+ end
30
+
31
+ current_doctype = doctype
32
+ if current_doctype
33
+ if new_doctype != current_doctype
34
+ raise ArgumentError, "The doctype has already been set to #{current_doctype} on this widget class or a superclass. You can't set it to #{new_doctype}; if you want to use a different doctype, you will need to make a new subclass that has no doctype set yet."
35
+ end
36
+ end
37
+
38
+ if new_doctype.close_void_tags_must_be != nil
39
+ self.close_void_tags(new_doctype.close_void_tags_must_be)
40
+ end
41
+
42
+ @_fortitude_doctype = new_doctype
43
+ tags_added!(new_doctype.tags.values)
44
+ else
45
+ return @_fortitude_doctype if @_fortitude_doctype
46
+ return superclass.doctype if superclass.respond_to?(:doctype)
47
+ nil
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,62 @@
1
+ require 'active_support'
2
+ require 'active_support/concern'
3
+
4
+ require 'fortitude/rails/yielded_object_outputter'
5
+
6
+ module Fortitude
7
+ class Widget
8
+ module Helpers
9
+ extend ActiveSupport::Concern
10
+
11
+ # PUBLIC API
12
+ def invoke_helper(name, *args, &block)
13
+ @_fortitude_rendering_context.helpers_object.send(name, *args, &block)
14
+ end
15
+
16
+ module ClassMethods
17
+ # PUBLIC API
18
+ def helper(*args)
19
+ options = args.extract_options!
20
+ options.assert_valid_keys(:transform, :call, :output_yielded_methods)
21
+
22
+ args.each do |name|
23
+ source_method_name = options[:call] || name
24
+
25
+ prefix = "return"
26
+ suffix = ""
27
+ case (transform = options[:transform])
28
+ when :output_return_value
29
+ prefix = "text"
30
+ suffix = "; nil"
31
+ when :return_output
32
+ prefix = "return capture { "
33
+ suffix = " }"
34
+ when :none, nil, false then nil
35
+ else raise ArgumentError, "Invalid value for :transform: #{transform.inspect}"
36
+ end
37
+
38
+ block_transform = "effective_block = block"
39
+
40
+ yielded_methods = options[:output_yielded_methods]
41
+ if yielded_methods
42
+ block_transform = <<-EOS
43
+ effective_block = lambda do |yielded_object|
44
+ block.call(Fortitude::Rails::YieldedObjectOutputter.new(self, yielded_object, #{yielded_methods.inspect}))
45
+ end
46
+ EOS
47
+ end
48
+
49
+ text = <<-EOS
50
+ def #{name}(*args, &block)
51
+ #{block_transform}
52
+ #{prefix}(@_fortitude_rendering_context.helpers_object.#{source_method_name}(*args, &effective_block))#{suffix}
53
+ end
54
+ EOS
55
+
56
+ helpers_module.module_eval(text)
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,76 @@
1
+ require 'active_support'
2
+ require 'active_support/concern'
3
+
4
+ require 'fortitude/method_templates/simple_template'
5
+
6
+ module Fortitude
7
+ class Widget
8
+ module Integration
9
+ extend ActiveSupport::Concern
10
+
11
+ module ClassMethods
12
+ # INTERNAL USE ONLY
13
+ def rebuilding(what, why, klass, &block)
14
+ ActiveSupport::Notifications.instrument("fortitude.rebuilding", :what => what, :why => why, :originating_class => klass, :class => self, &block)
15
+ end
16
+ private :rebuilding
17
+
18
+ # INTERNAL USE ONLY
19
+ def rebuild_text_methods!(why, klass = self)
20
+ rebuilding(:text_methods, why, klass) do
21
+ class_eval(Fortitude::MethodTemplates::SimpleTemplate.template('text_method_template').result(:format_output => format_output, :needs_element_rules => self.enforce_element_nesting_rules))
22
+ direct_subclasses.each { |s| s.rebuild_text_methods!(why, klass) }
23
+ end
24
+ end
25
+ end
26
+
27
+ # RUBY CALLBACK
28
+ def method_missing(name, *args, &block)
29
+ if self.class.extra_assigns == :use
30
+ ivar_name = self.class.instance_variable_name_for_need(name)
31
+ return instance_variable_get(ivar_name) if instance_variable_defined?(ivar_name)
32
+ end
33
+
34
+ if self.class.automatic_helper_access && @_fortitude_rendering_context && @_fortitude_rendering_context.helpers_object && @_fortitude_rendering_context.helpers_object.respond_to?(name, true)
35
+ @_fortitude_rendering_context.helpers_object.send(name, *args, &block)
36
+ else
37
+ super(name, *args, &block)
38
+ end
39
+ end
40
+
41
+ included do
42
+ _fortitude_on_class_inheritable_attribute_change(
43
+ :format_output, :enforce_element_nesting_rules) do |attribute_name, old_value, new_value|
44
+ rebuild_text_methods!(:"#{attribute_name}_changed")
45
+ end
46
+
47
+ _fortitude_on_class_inheritable_attribute_change(
48
+ :format_output, :close_void_tags, :enforce_element_nesting_rules,
49
+ :enforce_attribute_rules, :enforce_id_uniqueness) do |attribute_name, old_value, new_value|
50
+ rebuild_tag_methods!(:"#{attribute_name}_changed")
51
+ end
52
+
53
+ _fortitude_on_class_inheritable_attribute_change(
54
+ :debug, :extra_assigns, :use_instance_variables_for_assigns) do |attribute_name, old_value, new_value|
55
+ rebuild_needs!(:"#{attribute_name}_changed")
56
+ end
57
+
58
+ _fortitude_on_class_inheritable_attribute_change(:implicit_shared_variable_access) do |attribute_name, old_value, new_value|
59
+ if new_value
60
+ around_content :transfer_shared_variables
61
+ else
62
+ remove_around_content :transfer_shared_variables, :fail_if_not_present => false
63
+ end
64
+ end
65
+
66
+ _fortitude_on_class_inheritable_attribute_change(:start_and_end_comments) do |attribute_name, old_value, new_value|
67
+ if new_value
68
+ around_content :start_and_end_comments
69
+ else
70
+ remove_around_content :start_and_end_comments, :fail_if_not_present => false
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,63 @@
1
+ require 'active_support'
2
+ require 'active_support/concern'
3
+
4
+ module Fortitude
5
+ class Widget
6
+ module Localization
7
+ extend ActiveSupport::Concern
8
+
9
+ module ClassMethods
10
+ # RUBY CALLBACK
11
+ def method_added(method_name)
12
+ super(method_name)
13
+ check_localized_methods!
14
+ end
15
+
16
+ # RUBY CALLBACK
17
+ def method_removed(method_name)
18
+ super(method_name)
19
+ check_localized_methods!
20
+ end
21
+
22
+ # RUBY CALL
23
+ def include(*args)
24
+ super(*args)
25
+ check_localized_methods!
26
+ end
27
+
28
+ LOCALIZED_CONTENT_PREFIX = "localized_content_"
29
+
30
+ # INTERNAL USE ONLY
31
+ def check_localized_methods!(original_class = self)
32
+ currently_has = instance_methods(true).detect { |i| i =~ /^#{LOCALIZED_CONTENT_PREFIX}/i }
33
+ if currently_has != @last_localized_methods_check_has
34
+ @last_localized_methods_check_has = currently_has
35
+ rebuild_run_content!(:localized_methods_presence_changed, original_class)
36
+ end
37
+ direct_subclasses.each { |s| s.check_localized_methods!(original_class) }
38
+ end
39
+
40
+ # INTERNAL USE ONLY
41
+ def has_localized_content_methods?
42
+ !! (instance_methods(true).detect { |i| i =~ /^#{LOCALIZED_CONTENT_PREFIX}/i })
43
+ end
44
+ private :has_localized_content_methods?
45
+ end
46
+
47
+ # PUBLIC API
48
+ def t(key, *args)
49
+ base = self.class.translation_base
50
+ if base && key.to_s =~ /^\./
51
+ super("#{base}#{key}", *args)
52
+ else
53
+ super(key, *args)
54
+ end
55
+ end
56
+
57
+ # PUBLIC API
58
+ def ttext(key, *args)
59
+ tag_text t(".#{key}", *args)
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,58 @@
1
+ require 'active_support'
2
+ require 'active_support/concern'
3
+
4
+ require 'fortitude/tags/tags_module'
5
+
6
+ module Fortitude
7
+ class Widget
8
+ module ModulesAndSubclasses
9
+ extend ActiveSupport::Concern
10
+
11
+ module ClassMethods
12
+ # INTERNAL USE ONLY
13
+ def direct_subclasses
14
+ @direct_subclasses || [ ]
15
+ end
16
+ private :direct_subclasses
17
+
18
+ # INTERNAL USE ONLY -- RUBY CALLBACK
19
+ def inherited(subclass)
20
+ @direct_subclasses ||= [ ]
21
+ @direct_subclasses |= [ subclass ]
22
+ end
23
+
24
+ # INTERNAL USE ONLY
25
+ def create_modules!
26
+ raise "We already seem to have created our modules" if @tags_module || @needs_module || @helpers_module
27
+ @tags_module = Fortitude::Tags::TagsModule.new(self)
28
+ @helpers_module = Module.new
29
+ include @helpers_module
30
+ @needs_module = Module.new
31
+ include @needs_module
32
+ end
33
+ private :create_modules!
34
+
35
+ # INTERNAL USE ONLY
36
+ def tags_module
37
+ create_modules! unless @tags_module
38
+ @tags_module
39
+ end
40
+ private :tags_module
41
+
42
+ # INTERNAL USE ONLY
43
+ def needs_module
44
+ create_modules! unless @needs_module
45
+ @needs_module
46
+ end
47
+ private :needs_module
48
+
49
+ # INTERNAL USE ONLY
50
+ def helpers_module
51
+ create_modules! unless @helpers_module
52
+ @helpers_module
53
+ end
54
+ private :helpers_module
55
+ end
56
+ end
57
+ end
58
+ end