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,98 @@
1
+ require 'active_support'
2
+ require 'active_support/concern'
3
+
4
+ module Fortitude
5
+ module Support
6
+ module ClassInheritableAttributes
7
+ extend ActiveSupport::Concern
8
+
9
+ module ClassMethods
10
+ def _fortitude_invoke_class_inheritable_attribute(attribute_name, allowable_values, *args)
11
+ raise ArgumentError, "Invalid arguments: #{args.inspect}" if args.length > 1
12
+ instance_variable_name = "@_fortitude_#{attribute_name}"
13
+ if args.length == 0
14
+ _fortitude_read_class_inheritable_attribute(attribute_name, instance_variable_name, false)
15
+ else
16
+ _fortitude_write_class_inheritable_attribute(attribute_name, instance_variable_name, allowable_values, args[0])
17
+ end
18
+ end
19
+
20
+ def _fortitude_read_class_inheritable_attribute(attribute_name, instance_variable_name, allow_not_present)
21
+ return instance_variable_get(instance_variable_name) if instance_variable_defined?(instance_variable_name)
22
+ return superclass.send(attribute_name) if superclass.respond_to?(attribute_name)
23
+
24
+ if allow_not_present
25
+ :_fortitude_class_inheritable_attribute_not_present
26
+ else
27
+ raise "Fortitude class-inheritable attribute error: there should always be a declared value for #{attribute_name} at the top of the inheritance hierarchy somewhere"
28
+ end
29
+ end
30
+
31
+ def _fortitude_write_class_inheritable_attribute(attribute_name, instance_variable_name, allowable_values, new_value)
32
+ allowed = if allowable_values.respond_to?(:call)
33
+ allowable_values.call(new_value, self)
34
+ else
35
+ allowable_values.include?(new_value)
36
+ end
37
+
38
+ if (! allowed)
39
+ error = "#{attribute_name} cannot be set to #{new_value.inspect}"
40
+ error << "; valid values are: #{allowable_values.inspect}" unless allowable_values.respond_to?(:call)
41
+ raise ArgumentError, error
42
+ end
43
+
44
+ old_value = _fortitude_read_class_inheritable_attribute(attribute_name, instance_variable_name, true)
45
+
46
+ instance_variable_set(instance_variable_name, new_value)
47
+
48
+ if (old_value != :_fortitude_class_inheritable_attribute_not_present) && (new_value != old_value)
49
+ _fortitude_class_inheritable_attribute_changed!(attribute_name, old_value, new_value)
50
+ end
51
+
52
+ new_value
53
+ end
54
+
55
+ def _fortitude_class_inheritable_attribute(attribute_name, default_value, allowable_values)
56
+ metaclass = (class << self; self; end)
57
+
58
+ metaclass.send(:define_method, attribute_name) do |*args|
59
+ _fortitude_invoke_class_inheritable_attribute(attribute_name, allowable_values, *args)
60
+ end
61
+
62
+ send(attribute_name, default_value)
63
+ end
64
+
65
+ def _fortitude_on_class_inheritable_attribute_change(*attribute_names, &block)
66
+ if attribute_names.length == 0
67
+ raise ArgumentError, "You must pass at least one attribute name, not: #{attribute_names.inspect}"
68
+ end
69
+
70
+ @_fortitude_class_inheritable_attribute_change_callbacks ||= { }
71
+ attribute_names.each do |attribute_name|
72
+ @_fortitude_class_inheritable_attribute_change_callbacks[attribute_name] ||= [ ]
73
+ @_fortitude_class_inheritable_attribute_change_callbacks[attribute_name] |= [ block ]
74
+ end
75
+ end
76
+
77
+ def _fortitude_class_inheritable_attribute_callbacks_for(attribute_name)
78
+ out = if superclass.respond_to?(:_fortitude_class_inheritable_attribute_callbacks_for)
79
+ superclass._fortitude_class_inheritable_attribute_callbacks_for(attribute_name)
80
+ else
81
+ [ ]
82
+ end
83
+
84
+ @_fortitude_class_inheritable_attribute_change_callbacks ||= { }
85
+ out += @_fortitude_class_inheritable_attribute_change_callbacks[attribute_name] || [ ]
86
+
87
+ out
88
+ end
89
+
90
+ def _fortitude_class_inheritable_attribute_changed!(attribute_name, old_value, new_value)
91
+ callbacks = _fortitude_class_inheritable_attribute_callbacks_for(attribute_name)
92
+ # klass = self
93
+ callbacks.each { |cb| instance_exec(attribute_name, old_value, new_value, &cb) }
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,76 @@
1
+ module Fortitude
2
+ module Support
3
+ class InstanceVariableSet
4
+ def initialize(target_object)
5
+ @target_object = target_object
6
+ end
7
+
8
+ def [](name)
9
+ target_object.instance_variable_get("@#{name}")
10
+ end
11
+
12
+ def []=(name, value)
13
+ target_object.instance_variable_set("@#{name}", value)
14
+ end
15
+
16
+ def keys
17
+ target_object.instance_variables.map do |instance_variable_name|
18
+ $1.to_sym if instance_variable_name.to_s =~ /^@(.*)$/
19
+ end.compact
20
+ end
21
+
22
+ def each
23
+ keys.each { |k| yield k, self[k] }
24
+ end
25
+
26
+ def with_instance_variable_copying(widget)
27
+ before_copy = widget.instance_variables
28
+ skip_copy = before_copy - target_object.instance_variables
29
+
30
+ copy_to_widget(widget)
31
+ begin
32
+ yield
33
+ ensure
34
+ copy_from_widget(widget, skip_copy)
35
+ end
36
+ end
37
+
38
+ private
39
+ def copy_to_widget(widget)
40
+ needs = widget.needs_as_hash
41
+ extras = widget.widget_extra_assigns
42
+
43
+ target_object.instance_variables.each do |instance_variable_name|
44
+ if instance_variable_name =~ /^@(.*)$/
45
+ without_at = $1.to_sym
46
+ next if needs.has_key?(without_at)
47
+ next if extras.has_key?(without_at)
48
+
49
+ value = target_object.instance_variable_get(instance_variable_name)
50
+ widget.instance_variable_set(instance_variable_name, value)
51
+ end
52
+ end
53
+ end
54
+
55
+ def copy_from_widget(widget, exclude_variables = [ ])
56
+ needs = widget.needs_as_hash
57
+ extras = widget.widget_extra_assigns
58
+
59
+ (widget.instance_variables - exclude_variables).each do |instance_variable_name|
60
+ next if instance_variable_name =~ /^@_fortitude_/
61
+
62
+ if instance_variable_name =~ /^@(.*)$/i
63
+ without_at = $1.to_sym
64
+ next if needs.has_key?(without_at)
65
+ next if extras.has_key?(without_at)
66
+
67
+ value = widget.instance_variable_get(instance_variable_name)
68
+ target_object.instance_variable_set(instance_variable_name, value)
69
+ end
70
+ end
71
+ end
72
+
73
+ attr_reader :target_object
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,87 @@
1
+ module Fortitude
2
+ module Support
3
+ class StaticizedMethod
4
+ def initialize(widget_class, method_name, options = { })
5
+ @widget_class = widget_class
6
+ @method_name = method_name
7
+
8
+ @output_by_locale = { }
9
+ @has_yield = false
10
+
11
+ @options = options
12
+ @options.assert_valid_keys(:locale_support)
13
+
14
+ set_constant!
15
+ end
16
+
17
+ def run!(widget)
18
+ locale = locale_support? ? widget.widget_locale : nil
19
+ output = (@output_by_locale[locale] ||= generate_content!(widget))
20
+
21
+ if output.kind_of?(Array)
22
+ widget.rawtext(output[0])
23
+ yield
24
+ widget.rawtext(output[1])
25
+ else
26
+ widget.rawtext(output)
27
+ end
28
+ end
29
+
30
+ def create_method!
31
+ unless widget_class.instance_methods.map(&:to_s).include?(dynamic_method_name.to_s)
32
+ widget_class.send(:alias_method, dynamic_method_name, method_name)
33
+ end
34
+
35
+ widget_class.class_eval <<-EOS
36
+ def #{method_name}
37
+ #{constant_name}.run!(self) { yield }
38
+ end
39
+ EOS
40
+ end
41
+
42
+ private
43
+ attr_reader :widget_class, :method_name, :output_by_locale, :has_yield, :options
44
+
45
+ def locale_support?
46
+ ! (options.has_key?(:locale_support) && (! options[:locale_support]))
47
+ end
48
+
49
+ def generate_content!(widget)
50
+ yielded = false
51
+ pre_yield = nil
52
+
53
+ result = widget.capture do
54
+ widget.with_staticness_enforced(method_name) do
55
+ widget.send(dynamic_method_name) do
56
+ raise "This method yields more than once; you can't make it static" if yielded
57
+ pre_yield = widget.output_buffer.dup
58
+ yielded = true
59
+ widget.output_buffer.replace('')
60
+ end
61
+ end
62
+ end
63
+
64
+ @has_yield = yielded
65
+
66
+ if yielded
67
+ [ pre_yield, result ]
68
+ else
69
+ result
70
+ end
71
+ end
72
+
73
+ def set_constant!
74
+ widget_class.send(:remove_const, constant_name) if widget_class.const_defined?(constant_name)
75
+ widget_class.const_set(constant_name, self)
76
+ end
77
+
78
+ def constant_name
79
+ "FORTITUDE_STATICIZED_METHOD_#{method_name.to_s.upcase}"
80
+ end
81
+
82
+ def dynamic_method_name
83
+ "_#{method_name}_dynamic".to_sym
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,19 @@
1
+ module Fortitude
2
+ module Tags
3
+ class PartialTagPlaceholder
4
+ class << self
5
+ def instance
6
+ @instance ||= new
7
+ end
8
+ end
9
+
10
+ def name
11
+ :_fortitude_partial_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
@@ -0,0 +1,189 @@
1
+ require 'fortitude/tags/tag_support'
2
+ require 'fortitude/method_templates/simple_template'
3
+
4
+ # Note on handling tags that have no content inside them:
5
+ #
6
+ # - If the tag cannot ever have content inside it -- a "void tag" as denoted by HTML, specified here by
7
+ # :content_allowed => false -- then we can either render it as "<tag>" (if :close_void_tags is set to false,
8
+ # the default, on the widget class), or "<tag/>" (if :close_void_tags is set to true on the widget class).
9
+ # - If the tag can have content inside it, but this instance of it does not, then we always render it as
10
+ # <tag></tag> (or <tag attr="value"...></tag>).
11
+ #
12
+ # Further, doctypes restrict the values you can set close_void_tags to on a widget: HTML5 allows either, HTML4
13
+ # requires it to be false, and XHTML requires it to be true.
14
+ #
15
+ # This is all per the information at:
16
+ #
17
+ # http://stackoverflow.com/questions/3558119/are-self-closing-tags-valid-in-html5
18
+ # http://www.w3.org/TR/xhtml-media-types/#C_2
19
+ # http://www.colorglare.com/2014/02/03/to-close-or-not-to-close.html
20
+ module Fortitude
21
+ module Tags
22
+ class Tag
23
+ attr_reader :name, :spec
24
+ attr_accessor :newline_before, :content_allowed, :allow_data_attributes, :allow_aria_attributes, :escape_direct_content
25
+
26
+ class << self
27
+ def normalize_tag_name(name)
28
+ name.to_s.strip.downcase.to_sym
29
+ end
30
+ end
31
+
32
+ def initialize(name, options = { })
33
+ options.assert_valid_keys(:valid_attributes, :newline_before, :content_allowed, :can_enclose,
34
+ :allow_data_attributes, :allow_aria_attributes, :spec, :escape_direct_content)
35
+
36
+ @name = self.class.normalize_tag_name(name)
37
+
38
+ self.valid_attributes = options[:valid_attributes]
39
+ self.can_enclose = options[:can_enclose]
40
+ @newline_before = !! options[:newline_before]
41
+ @content_allowed = true unless options.has_key?(:content_allowed) && (! options[:content_allowed])
42
+ @allow_data_attributes = true unless options.has_key?(:allow_data_attributes) && (! options[:allow_data_attributes])
43
+ @allow_aria_attributes = true unless options.has_key?(:allow_aria_attributes) && (! options[:allow_aria_attributes])
44
+ @escape_direct_content = true unless options.has_key?(:escape_direct_content) && (! options[:escape_direct_content])
45
+ @spec = options[:spec]
46
+ end
47
+
48
+ def valid_attributes
49
+ @allowable_attributes.keys if @allowable_attributes
50
+ end
51
+
52
+ def valid_attributes=(attributes)
53
+ @allowable_attributes = to_symbol_hash(attributes)
54
+ end
55
+
56
+ def can_enclose
57
+ @allowable_enclosed_elements.keys if @allowable_enclosed_elements
58
+ end
59
+
60
+ def can_enclose=(tags)
61
+ @allowable_enclosed_elements = to_symbol_hash(tags)
62
+ @allowable_enclosed_elements[:_fortitude_partial_placeholder] = true if @allowable_enclosed_elements
63
+ end
64
+
65
+ def dup
66
+ self.class.new(name, {
67
+ :valid_attributes => valid_attributes,
68
+ :can_enclose => can_enclose,
69
+ :content_allowed => content_allowed,
70
+ :allow_data_attributes => allow_data_attributes,
71
+ :allow_aria_attributes => allow_aria_attributes,
72
+ :escape_direct_content => escape_direct_content,
73
+ :spec => spec
74
+ })
75
+ end
76
+
77
+ CONCAT_METHOD = "original_concat"
78
+
79
+ def validate_can_enclose!(widget, tag_object)
80
+ return unless @allowable_enclosed_elements
81
+ unless @allowable_enclosed_elements[tag_object.name]
82
+ raise Fortitude::Errors::InvalidElementNesting.new(widget, self, tag_object)
83
+ end
84
+ end
85
+
86
+ def validate_attributes(widget, attributes_hash)
87
+ return unless @allowable_attributes
88
+ disabled_sym = attributes_hash.delete(:_fortitude_skip_attribute_rule_enforcement)
89
+ disabled_string = attributes_hash.delete('_fortitude_skip_attribute_rule_enforcement')
90
+ return if disabled_sym || disabled_string
91
+ return if widget.rendering_context.attribute_validation_disabled?
92
+ bad = { }
93
+ attributes_hash.each do |k, v|
94
+ bad[k] = v unless is_valid_attribute?(k, v)
95
+ end
96
+ raise Fortitude::Errors::InvalidElementAttributes.new(widget, self, bad, @allowable_attributes.keys) if bad.size > 0
97
+ end
98
+
99
+ def is_valid_attribute?(k, v)
100
+ return true if @allowable_attributes.include?(k.to_sym)
101
+
102
+ if @allow_data_attributes
103
+ return true if k.to_s =~ /^data-\S/i || (k.to_s =~ /^data$/i && v.kind_of?(Hash))
104
+ end
105
+
106
+ if @allow_aria_attributes
107
+ return true if k.to_s =~ /^aria-\S/i || (k.to_s =~ /^aria$/i && v.kind_of?(Hash))
108
+ end
109
+
110
+ return false
111
+ end
112
+
113
+ def validate_id_uniqueness(widget, attributes_hash)
114
+ id = attributes_hash[:id] || attributes_hash['id']
115
+ widget.rendering_context.validate_id_uniqueness(widget, name, id) if id
116
+ end
117
+
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)
120
+
121
+ unless mod.respond_to?(:fortitude_tag_support_included?) && mod.fortitude_tag_support_included?
122
+ mod.send(:include, ::Fortitude::Tags::TagSupport)
123
+ end
124
+
125
+ if @content_allowed
126
+ alone_tag = "<#{name}></#{name}>"
127
+ partial_open_alone_end = "></#{name}>"
128
+ elsif options[:close_void_tags]
129
+ alone_tag = "<#{name}/>"
130
+ partial_open_alone_end = "/>"
131
+ else
132
+ alone_tag = "<#{name}>"
133
+ partial_open_alone_end = ">"
134
+ end
135
+
136
+ ensure_constants(mod, :ALONE => alone_tag, :OPEN => "<#{name}>", :CLOSE => "</#{name}>",
137
+ :PARTIAL_OPEN => "<#{name}", :TAG_OBJECT => self, :PARTIAL_OPEN_ALONE_END => partial_open_alone_end)
138
+
139
+ needs_formatting = !! options[:enable_formatting]
140
+
141
+ if needs_formatting && @newline_before
142
+ yield_call = "_fortitude_formatted_output_tag_yield(:#{name}) { yield }"
143
+ elsif needs_formatting
144
+ yield_call = "yield; rc.about_to_output_non_whitespace!"
145
+ else
146
+ yield_call = "yield"
147
+ end
148
+
149
+ 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
+ :needs_attribute_rules => !! options[:enforce_attribute_rules],
153
+ :needs_id_uniqueness => !! options[:enforce_id_uniqueness],
154
+ :needs_formatting => needs_formatting, :content_allowed => @content_allowed,
155
+ :newline_before => @newline_before,
156
+ :escape_direct_content => @escape_direct_content,
157
+ :alone_const => tag_constant_name(:ALONE), :open_const => tag_constant_name(:OPEN),
158
+ :close_const => tag_constant_name(:CLOSE), :partial_open_const => tag_constant_name(:PARTIAL_OPEN),
159
+ :tag_object_const => tag_constant_name(:TAG_OBJECT), :partial_open_end_const => :FORTITUDE_TAG_PARTIAL_OPEN_END,
160
+ :partial_open_alone_end_const => tag_constant_name(:PARTIAL_OPEN_ALONE_END))
161
+
162
+ mod.module_eval(text)
163
+ mod.alias_method(name, "tag_#{name}")
164
+ end
165
+
166
+ private
167
+ def tag_constant_name(key)
168
+ "FORTITUDE_TAG_#{name.to_s.upcase}_#{key}".to_sym
169
+ end
170
+
171
+ def ensure_constants(target, map)
172
+ map.each { |name, value| ensure_constant(target, tag_constant_name(name), value.freeze) }
173
+ end
174
+
175
+ def ensure_constant(target, const_name, const_value)
176
+ target.send(:remove_const, const_name) if target.const_defined?(const_name)
177
+ target.const_set(const_name, const_value.freeze)
178
+ end
179
+
180
+ def to_symbol_hash(array)
181
+ if array
182
+ out = { }
183
+ array.each { |a| out[a.to_s.strip.to_sym] = true }
184
+ out
185
+ end
186
+ end
187
+ end
188
+ end
189
+ end