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
@@ -1,45 +0,0 @@
1
- module Fortitude
2
- class SimpleTemplate
3
- class << self
4
- def template(name)
5
- @templates ||= { }
6
- @templates[name] ||= new(File.join(File.dirname(__FILE__), "#{name}.rb.smpl"))
7
- end
8
- end
9
-
10
- def initialize(source_file)
11
- @lines = File.read(source_file).split(/\r\n|\r|\n/)
12
- end
13
-
14
- def result(bindings)
15
- bindings = bindings.stringify_keys
16
- bindings_target = Object.new
17
- bindings.each do |key, value|
18
- (class << bindings_target; self; end).send(:define_method, key) { value }
19
- end
20
-
21
- result_lines = [ ]
22
- @lines.each do |l|
23
- if l =~ /^(.*)\#\s*\:if\s*(.*?)\s*$/i
24
- l, condition = $1, $2
25
- next unless bindings_target.instance_eval(condition)
26
- end
27
-
28
- while l =~ /[^\\]\#\{([^}]+)\}/ || l =~ /^\#\{([^}]+)\}/
29
- name = $1
30
- begin
31
- value = bindings_target.send($1)
32
- rescue => e
33
- raise "Failed when processing #{l.inspect}: #{e.inspect}"
34
- end
35
- l = l.gsub("\#\{#{$1}\}", value.to_s)
36
- end
37
- l = l.gsub(/\\\#\{/, "\#\{")
38
-
39
- result_lines << l
40
- end
41
-
42
- result_lines.join("\n")
43
- end
44
- end
45
- end
@@ -1,85 +0,0 @@
1
- module Fortitude
2
- class StaticizedMethod
3
- def initialize(widget_class, method_name, options = { })
4
- @widget_class = widget_class
5
- @method_name = method_name
6
-
7
- @output_by_locale = { }
8
- @has_yield = false
9
-
10
- @options = options
11
- @options.assert_valid_keys(:locale_support)
12
-
13
- set_constant!
14
- end
15
-
16
- def run!(widget)
17
- locale = locale_support? ? widget.widget_locale : nil
18
- output = (@output_by_locale[locale] ||= generate_content!(widget))
19
-
20
- if output.kind_of?(Array)
21
- widget.rawtext(output[0])
22
- yield
23
- widget.rawtext(output[1])
24
- else
25
- widget.rawtext(output)
26
- end
27
- end
28
-
29
- def create_method!
30
- unless widget_class.instance_methods.map(&:to_s).include?(dynamic_method_name.to_s)
31
- widget_class.send(:alias_method, dynamic_method_name, method_name)
32
- end
33
-
34
- widget_class.class_eval <<-EOS
35
- def #{method_name}
36
- #{constant_name}.run!(self) { yield }
37
- end
38
- EOS
39
- end
40
-
41
- private
42
- attr_reader :widget_class, :method_name, :output_by_locale, :has_yield, :options
43
-
44
- def locale_support?
45
- ! (options.has_key?(:locale_support) && (! options[:locale_support]))
46
- end
47
-
48
- def generate_content!(widget)
49
- yielded = false
50
- pre_yield = nil
51
-
52
- result = widget.capture do
53
- widget.with_staticness_enforced(method_name) do
54
- widget.send(dynamic_method_name) do
55
- raise "This method yields more than once; you can't make it static" if yielded
56
- pre_yield = widget.output_buffer.dup
57
- yielded = true
58
- widget.output_buffer.replace('')
59
- end
60
- end
61
- end
62
-
63
- @has_yield = yielded
64
-
65
- if yielded
66
- [ pre_yield, result ]
67
- else
68
- result
69
- end
70
- end
71
-
72
- def set_constant!
73
- widget_class.send(:remove_const, constant_name) if widget_class.const_defined?(constant_name)
74
- widget_class.const_set(constant_name, self)
75
- end
76
-
77
- def constant_name
78
- "FORTITUDE_STATICIZED_METHOD_#{method_name.to_s.upcase}"
79
- end
80
-
81
- def dynamic_method_name
82
- "_#{method_name}_dynamic".to_sym
83
- end
84
- end
85
- end
data/lib/fortitude/tag.rb DELETED
@@ -1,162 +0,0 @@
1
- require 'fortitude/tag_support'
2
- require 'fortitude/simple_template'
3
-
4
- module Fortitude
5
- class Tag
6
- attr_reader :name, :spec
7
- attr_accessor :newline_before, :content_allowed, :allow_data_attributes, :allow_aria_attributes, :escape_direct_content
8
-
9
- class << self
10
- def normalize_tag_name(name)
11
- name.to_s.strip.downcase.to_sym
12
- end
13
- end
14
-
15
- def initialize(name, options = { })
16
- options.assert_valid_keys(:valid_attributes, :newline_before, :content_allowed, :can_enclose,
17
- :allow_data_attributes, :allow_aria_attributes, :spec, :escape_direct_content)
18
-
19
- @name = self.class.normalize_tag_name(name)
20
-
21
- self.valid_attributes = options[:valid_attributes]
22
- self.can_enclose = options[:can_enclose]
23
- @newline_before = !! options[:newline_before]
24
- @content_allowed = true unless options.has_key?(:content_allowed) && (! options[:content_allowed])
25
- @allow_data_attributes = true unless options.has_key?(:allow_data_attributes) && (! options[:allow_data_attributes])
26
- @allow_aria_attributes = true unless options.has_key?(:allow_aria_attributes) && (! options[:allow_aria_attributes])
27
- @escape_direct_content = true unless options.has_key?(:escape_direct_content) && (! options[:escape_direct_content])
28
- @spec = options[:spec]
29
- end
30
-
31
- def valid_attributes
32
- @allowable_attributes.keys if @allowable_attributes
33
- end
34
-
35
- def valid_attributes=(attributes)
36
- @allowable_attributes = to_symbol_hash(attributes)
37
- end
38
-
39
- def can_enclose
40
- @allowable_enclosed_elements.keys if @allowable_enclosed_elements
41
- end
42
-
43
- def can_enclose=(tags)
44
- @allowable_enclosed_elements = to_symbol_hash(tags)
45
- @allowable_enclosed_elements[:_fortitude_partial_placeholder] = true if @allowable_enclosed_elements
46
- end
47
-
48
- def dup
49
- self.class.new(name, {
50
- :valid_attributes => valid_attributes,
51
- :can_enclose => can_enclose,
52
- :content_allowed => content_allowed,
53
- :allow_data_attributes => allow_data_attributes,
54
- :allow_aria_attributes => allow_aria_attributes,
55
- :escape_direct_content => escape_direct_content,
56
- :spec => spec
57
- })
58
- end
59
-
60
- CONCAT_METHOD = "original_concat"
61
-
62
- def validate_can_enclose!(widget, tag_object)
63
- return unless @allowable_enclosed_elements
64
- unless @allowable_enclosed_elements[tag_object.name]
65
- raise Fortitude::Errors::InvalidElementNesting.new(widget, self, tag_object)
66
- end
67
- end
68
-
69
- def validate_attributes(widget, attributes_hash)
70
- return unless @allowable_attributes
71
- disabled_sym = attributes_hash.delete(:_fortitude_skip_attribute_rule_enforcement)
72
- disabled_string = attributes_hash.delete('_fortitude_skip_attribute_rule_enforcement')
73
- return if disabled_sym || disabled_string
74
- return if widget.rendering_context.attribute_validation_disabled?
75
- bad = { }
76
- attributes_hash.each do |k, v|
77
- bad[k] = v unless is_valid_attribute?(k, v)
78
- end
79
- raise Fortitude::Errors::InvalidElementAttributes.new(widget, self, bad, @allowable_attributes.keys) if bad.size > 0
80
- end
81
-
82
- def is_valid_attribute?(k, v)
83
- return true if @allowable_attributes.include?(k.to_sym)
84
-
85
- if @allow_data_attributes
86
- return true if k.to_s =~ /^data-\S/i || (k.to_s =~ /^data$/i && v.kind_of?(Hash))
87
- end
88
-
89
- if @allow_aria_attributes
90
- return true if k.to_s =~ /^aria-\S/i || (k.to_s =~ /^aria$/i && v.kind_of?(Hash))
91
- end
92
-
93
- return false
94
- end
95
-
96
- def validate_id_uniqueness(widget, attributes_hash)
97
- id = attributes_hash[:id] || attributes_hash['id']
98
- widget.rendering_context.validate_id_uniqueness(widget, name, id) if id
99
- end
100
-
101
- def define_method_on!(mod, options = {})
102
- options.assert_valid_keys(:enforce_element_nesting_rules, :enforce_attribute_rules, :enable_formatting, :enforce_id_uniqueness, :close_void_tags)
103
-
104
- unless mod.respond_to?(:fortitude_tag_support_included?) && mod.fortitude_tag_support_included?
105
- mod.send(:include, ::Fortitude::TagSupport)
106
- end
107
-
108
- alone_tag = if @content_allowed || options[:close_void_tags] then "<#{name}/>" else "<#{name}>" end
109
-
110
- ensure_constants(mod, :ALONE => alone_tag, :OPEN => "<#{name}>", :CLOSE => "</#{name}>",
111
- :PARTIAL_OPEN => "<#{name}", :TAG_OBJECT => self)
112
-
113
- needs_formatting = !! options[:enable_formatting]
114
-
115
- if needs_formatting && @newline_before
116
- yield_call = "_fortitude_formatted_output_tag_yield(:#{name}) { yield }"
117
- elsif needs_formatting
118
- yield_call = "yield; rc.about_to_output_non_whitespace!"
119
- else
120
- yield_call = "yield"
121
- end
122
-
123
- text = Fortitude::SimpleTemplate.template('tag_method_template').result(
124
- :name => name.to_s, :method_name => "tag_#{name}".to_s, :yield_call => yield_call, :concat_method => CONCAT_METHOD,
125
- :needs_element_rules => !! options[:enforce_element_nesting_rules],
126
- :needs_attribute_rules => !! options[:enforce_attribute_rules],
127
- :needs_id_uniqueness => !! options[:enforce_id_uniqueness],
128
- :needs_formatting => needs_formatting, :content_allowed => @content_allowed,
129
- :newline_before => @newline_before,
130
- :escape_direct_content => @escape_direct_content,
131
- :alone_const => tag_constant_name(:ALONE), :open_const => tag_constant_name(:OPEN),
132
- :close_const => tag_constant_name(:CLOSE), :partial_open_const => tag_constant_name(:PARTIAL_OPEN),
133
- :tag_object_const => tag_constant_name(:TAG_OBJECT), :partial_open_end_const => :FORTITUDE_TAG_PARTIAL_OPEN_END,
134
- :partial_open_alone_end_const => :FORTITUDE_TAG_PARTIAL_OPEN_ALONE_END)
135
-
136
- mod.module_eval(text)
137
- mod.alias_method(name, "tag_#{name}")
138
- end
139
-
140
- private
141
- def tag_constant_name(key)
142
- "FORTITUDE_TAG_#{name.to_s.upcase}_#{key}".to_sym
143
- end
144
-
145
- def ensure_constants(target, map)
146
- map.each { |name, value| ensure_constant(target, tag_constant_name(name), value.freeze) }
147
- end
148
-
149
- def ensure_constant(target, const_name, const_value)
150
- target.send(:remove_const, const_name) if target.const_defined?(const_name)
151
- target.const_set(const_name, const_value.freeze)
152
- end
153
-
154
- def to_symbol_hash(array)
155
- if array
156
- out = { }
157
- array.each { |a| out[a.to_s.strip.to_sym] = true }
158
- out
159
- end
160
- end
161
- end
162
- end
@@ -1,11 +0,0 @@
1
- require 'fortitude/errors'
2
-
3
- module Fortitude
4
- TAG_RETURN_VALUE_SUPERCLASS = if defined?(::BasicObject) then ::BasicObject else ::Object end
5
-
6
- class TagReturnValue < TAG_RETURN_VALUE_SUPERCLASS
7
- def method_missing(name, *args)
8
- ::Kernel.raise ::Fortitude::Errors::NoReturnValueFromTag.new(name)
9
- end
10
- end
11
- end
@@ -1,48 +0,0 @@
1
- module Fortitude
2
- module TagStore
3
- def tag(name, options = nil)
4
- @_tags_by_name ||= { }
5
-
6
- name = Fortitude::Tag.normalize_tag_name(name)
7
- tag_object = Fortitude::Tag.new(name, options || { })
8
- @_tags_by_name[name] = tag_object
9
-
10
- tags_added!([ tag_object ])
11
- end
12
-
13
- def modify_tag(name)
14
- name = Fortitude::Tag.normalize_tag_name(name)
15
- existing_tag = tags[name]
16
-
17
- unless existing_tag
18
- raise Fortitude::Errors::TagNotFound.new(self, name)
19
- end
20
-
21
- new_tag = existing_tag.dup
22
- yield new_tag
23
- @_tags_by_name ||= { }
24
- @_tags_by_name[name] = new_tag
25
-
26
- tags_changed!([ new_tag ])
27
- end
28
-
29
- def tags
30
- out = { }
31
- (delegate_tag_stores || [ ]).each { |d| out.merge!(d.tags) }
32
- out.merge!(@_tags_by_name || { })
33
- out
34
- end
35
-
36
- def tags_added!(tags)
37
- tags_changed!(tags)
38
- end
39
-
40
- def tags_changed!(tags)
41
- # nothing here
42
- end
43
-
44
- def delegate_tag_stores
45
- [ ]
46
- end
47
- end
48
- end
@@ -1,48 +0,0 @@
1
- require 'fortitude/tag_return_value'
2
- require 'active_support/concern'
3
-
4
- module Fortitude
5
- module TagSupport
6
- extend ActiveSupport::Concern
7
-
8
- class TextPseudotag
9
- def name
10
- :_text
11
- end
12
- end
13
-
14
- FORTITUDE_TEXT_PSEUDOTAG = TextPseudotag.new
15
-
16
- FORTITUDE_TAG_PARTIAL_OPEN_END = ">".freeze
17
- FORTITUDE_TAG_PARTIAL_OPEN_ALONE_END = "/>".freeze
18
-
19
- def _fortitude_formatted_output_tag_yield(tag_name)
20
- rc = @_fortitude_rendering_context
21
- if rc.format_output?
22
- rc.needs_newline!
23
- rc.increase_indent!
24
- begin
25
- yield
26
- ensure
27
- rc.decrease_indent!
28
- rc.needs_newline!
29
- rc.about_to_output_non_whitespace!
30
- end
31
- else
32
- yield
33
- end
34
- end
35
-
36
- def _fortitude_raise_no_content_allowed_error(tag_name)
37
- raise Fortitude::Errors::NoContentAllowed.new(self, tag_name)
38
- end
39
-
40
- FORTITUDE_NO_RETURN_VALUE_FROM_TAGS = Fortitude::TagReturnValue.new
41
-
42
- module ClassMethods
43
- def fortitude_tag_support_included?
44
- true
45
- end
46
- end
47
- end
48
- end
@@ -1,14 +0,0 @@
1
- require 'fortitude/tag_support'
2
-
3
- module Fortitude
4
- class TagsModule < Module
5
- def initialize(widget_class)
6
- include Fortitude::TagSupport
7
-
8
- @widget_class = widget_class
9
- @widget_class.send(:include, self)
10
- end
11
-
12
- public :alias_method
13
- end
14
- end