reactrb 0.7.42

Sign up to get free protection for your applications and to get access to all the features.
Files changed (173) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +6 -0
  3. data/.gitignore +33 -0
  4. data/.travis.yml +9 -0
  5. data/Gemfile +2 -0
  6. data/LICENSE +19 -0
  7. data/README.md +117 -0
  8. data/Rakefile +28 -0
  9. data/config.ru +16 -0
  10. data/example/examples/Gemfile +7 -0
  11. data/example/examples/app/basics.js.rb +42 -0
  12. data/example/examples/app/items.rb +11 -0
  13. data/example/examples/app/jquery.js +5 -0
  14. data/example/examples/app/nodes.rb +61 -0
  15. data/example/examples/app/react-router.js +6 -0
  16. data/example/examples/app/react_api_demo.rb +29 -0
  17. data/example/examples/app/rerendering.rb +72 -0
  18. data/example/examples/app/reuse.rb +59 -0
  19. data/example/examples/app/show.rb +52 -0
  20. data/example/examples/config.ru +38 -0
  21. data/example/rails-tutorial/.gitignore +17 -0
  22. data/example/rails-tutorial/Gemfile +51 -0
  23. data/example/rails-tutorial/README.rdoc +28 -0
  24. data/example/rails-tutorial/Rakefile +6 -0
  25. data/example/rails-tutorial/app/assets/images/.keep +0 -0
  26. data/example/rails-tutorial/app/assets/javascripts/application.rb +15 -0
  27. data/example/rails-tutorial/app/assets/stylesheets/application.css +15 -0
  28. data/example/rails-tutorial/app/controllers/application_controller.rb +6 -0
  29. data/example/rails-tutorial/app/controllers/concerns/.keep +0 -0
  30. data/example/rails-tutorial/app/controllers/home_controller.rb +6 -0
  31. data/example/rails-tutorial/app/helpers/application_helper.rb +2 -0
  32. data/example/rails-tutorial/app/mailers/.keep +0 -0
  33. data/example/rails-tutorial/app/models/.keep +0 -0
  34. data/example/rails-tutorial/app/models/concerns/.keep +0 -0
  35. data/example/rails-tutorial/app/views/components.rb +3 -0
  36. data/example/rails-tutorial/app/views/components/home/show.rb +47 -0
  37. data/example/rails-tutorial/app/views/layouts/application.html.erb +14 -0
  38. data/example/rails-tutorial/bin/bundle +3 -0
  39. data/example/rails-tutorial/bin/rails +8 -0
  40. data/example/rails-tutorial/bin/rake +8 -0
  41. data/example/rails-tutorial/bin/setup +29 -0
  42. data/example/rails-tutorial/bin/spring +15 -0
  43. data/example/rails-tutorial/config.ru +4 -0
  44. data/example/rails-tutorial/config/application.rb +26 -0
  45. data/example/rails-tutorial/config/boot.rb +3 -0
  46. data/example/rails-tutorial/config/database.yml +25 -0
  47. data/example/rails-tutorial/config/environment.rb +5 -0
  48. data/example/rails-tutorial/config/environments/development.rb +41 -0
  49. data/example/rails-tutorial/config/environments/production.rb +79 -0
  50. data/example/rails-tutorial/config/environments/test.rb +42 -0
  51. data/example/rails-tutorial/config/initializers/assets.rb +11 -0
  52. data/example/rails-tutorial/config/initializers/backtrace_silencers.rb +7 -0
  53. data/example/rails-tutorial/config/initializers/cookies_serializer.rb +3 -0
  54. data/example/rails-tutorial/config/initializers/filter_parameter_logging.rb +4 -0
  55. data/example/rails-tutorial/config/initializers/inflections.rb +16 -0
  56. data/example/rails-tutorial/config/initializers/mime_types.rb +4 -0
  57. data/example/rails-tutorial/config/initializers/session_store.rb +3 -0
  58. data/example/rails-tutorial/config/initializers/wrap_parameters.rb +14 -0
  59. data/example/rails-tutorial/config/locales/en.yml +23 -0
  60. data/example/rails-tutorial/config/routes.rb +59 -0
  61. data/example/rails-tutorial/config/secrets.yml +22 -0
  62. data/example/rails-tutorial/db/seeds.rb +7 -0
  63. data/example/rails-tutorial/lib/assets/.keep +0 -0
  64. data/example/rails-tutorial/lib/tasks/.keep +0 -0
  65. data/example/rails-tutorial/log/.keep +0 -0
  66. data/example/rails-tutorial/public/404.html +67 -0
  67. data/example/rails-tutorial/public/422.html +67 -0
  68. data/example/rails-tutorial/public/500.html +66 -0
  69. data/example/rails-tutorial/public/favicon.ico +0 -0
  70. data/example/rails-tutorial/public/robots.txt +5 -0
  71. data/example/rails-tutorial/test/controllers/.keep +0 -0
  72. data/example/rails-tutorial/test/fixtures/.keep +0 -0
  73. data/example/rails-tutorial/test/helpers/.keep +0 -0
  74. data/example/rails-tutorial/test/integration/.keep +0 -0
  75. data/example/rails-tutorial/test/mailers/.keep +0 -0
  76. data/example/rails-tutorial/test/models/.keep +0 -0
  77. data/example/rails-tutorial/test/test_helper.rb +10 -0
  78. data/example/rails-tutorial/vendor/assets/javascripts/.keep +0 -0
  79. data/example/rails-tutorial/vendor/assets/stylesheets/.keep +0 -0
  80. data/example/sinatra-tutorial/.DS_Store +0 -0
  81. data/example/sinatra-tutorial/Gemfile +5 -0
  82. data/example/sinatra-tutorial/README.md +8 -0
  83. data/example/sinatra-tutorial/_comments.json +42 -0
  84. data/example/sinatra-tutorial/app/example.rb +290 -0
  85. data/example/sinatra-tutorial/app/jquery.js +5 -0
  86. data/example/sinatra-tutorial/config.ru +58 -0
  87. data/example/sinatra-tutorial/public/base.css +62 -0
  88. data/example/todos/Gemfile +11 -0
  89. data/example/todos/README.md +37 -0
  90. data/example/todos/Rakefile +8 -0
  91. data/example/todos/app/application.rb +22 -0
  92. data/example/todos/app/components/app.react.rb +61 -0
  93. data/example/todos/app/components/footer.react.rb +31 -0
  94. data/example/todos/app/components/todo_item.react.rb +46 -0
  95. data/example/todos/app/components/todo_list.react.rb +25 -0
  96. data/example/todos/app/models/todo.rb +19 -0
  97. data/example/todos/config.ru +14 -0
  98. data/example/todos/index.html.haml +16 -0
  99. data/example/todos/spec/todo_spec.rb +28 -0
  100. data/example/todos/vendor/base.css +410 -0
  101. data/example/todos/vendor/bg.png +0 -0
  102. data/example/todos/vendor/jquery.js +4 -0
  103. data/lib/generators/reactive_ruby/test_app/templates/assets/javascripts/components.rb +4 -0
  104. data/lib/generators/reactive_ruby/test_app/templates/assets/javascripts/test_application.rb +2 -0
  105. data/lib/generators/reactive_ruby/test_app/templates/boot.rb.erb +6 -0
  106. data/lib/generators/reactive_ruby/test_app/templates/script/rails +5 -0
  107. data/lib/generators/reactive_ruby/test_app/templates/test_application.rb.erb +13 -0
  108. data/lib/generators/reactive_ruby/test_app/templates/views/components/hello_world.rb +11 -0
  109. data/lib/generators/reactive_ruby/test_app/templates/views/components/todo.rb +14 -0
  110. data/lib/generators/reactive_ruby/test_app/test_app_generator.rb +105 -0
  111. data/lib/rails-helpers/top_level_rails_component.rb +54 -0
  112. data/lib/react/api.rb +127 -0
  113. data/lib/react/callbacks.rb +42 -0
  114. data/lib/react/component.rb +269 -0
  115. data/lib/react/component/api.rb +50 -0
  116. data/lib/react/component/base.rb +9 -0
  117. data/lib/react/component/class_methods.rb +190 -0
  118. data/lib/react/component/props_wrapper.rb +82 -0
  119. data/lib/react/element.rb +77 -0
  120. data/lib/react/event.rb +76 -0
  121. data/lib/react/ext/hash.rb +9 -0
  122. data/lib/react/ext/string.rb +8 -0
  123. data/lib/react/native_library.rb +53 -0
  124. data/lib/react/observable.rb +29 -0
  125. data/lib/react/rendering_context.rb +109 -0
  126. data/lib/react/state.rb +140 -0
  127. data/lib/react/top_level.rb +97 -0
  128. data/lib/react/validator.rb +136 -0
  129. data/lib/reactive-ruby/component_loader.rb +45 -0
  130. data/lib/reactive-ruby/isomorphic_helpers.rb +196 -0
  131. data/lib/reactive-ruby/rails.rb +7 -0
  132. data/lib/reactive-ruby/rails/component_mount.rb +44 -0
  133. data/lib/reactive-ruby/rails/controller_helper.rb +13 -0
  134. data/lib/reactive-ruby/rails/railtie.rb +14 -0
  135. data/lib/reactive-ruby/serializers.rb +15 -0
  136. data/lib/reactive-ruby/server_rendering/contextual_renderer.rb +42 -0
  137. data/lib/reactive-ruby/version.rb +3 -0
  138. data/lib/reactrb.rb +50 -0
  139. data/lib/sources/react-latest.js +21167 -0
  140. data/lib/sources/react-v13.js +21642 -0
  141. data/lib/sources/react-v14.js +20818 -0
  142. data/lib/sources/react-v15.js +21167 -0
  143. data/logo1.png +0 -0
  144. data/logo2.png +0 -0
  145. data/logo3.png +0 -0
  146. data/path_release_steps.md +9 -0
  147. data/reactrb.gemspec +43 -0
  148. data/spec/controller_helper_spec.rb +22 -0
  149. data/spec/index.html.erb +12 -0
  150. data/spec/react/callbacks_spec.rb +106 -0
  151. data/spec/react/component/base_spec.rb +36 -0
  152. data/spec/react/component_spec.rb +721 -0
  153. data/spec/react/dsl_spec.rb +161 -0
  154. data/spec/react/element_spec.rb +47 -0
  155. data/spec/react/event_spec.rb +24 -0
  156. data/spec/react/native_library_spec.rb +10 -0
  157. data/spec/react/observable_spec.rb +7 -0
  158. data/spec/react/param_declaration_spec.rb +286 -0
  159. data/spec/react/react_spec.rb +211 -0
  160. data/spec/react/state_spec.rb +26 -0
  161. data/spec/react/top_level_component_spec.rb +68 -0
  162. data/spec/react/tutorial/tutorial_spec.rb +35 -0
  163. data/spec/react/validator_spec.rb +128 -0
  164. data/spec/reactive-ruby/component_loader_spec.rb +68 -0
  165. data/spec/reactive-ruby/isomorphic_helpers_spec.rb +155 -0
  166. data/spec/reactive-ruby/rails/asset_pipeline_spec.rb +9 -0
  167. data/spec/reactive-ruby/rails/component_mount_spec.rb +66 -0
  168. data/spec/reactive-ruby/server_rendering/contextual_renderer_spec.rb +35 -0
  169. data/spec/spec_helper.rb +109 -0
  170. data/spec/support/react/spec_helpers.rb +57 -0
  171. data/spec/vendor/es5-shim.min.js +6 -0
  172. data/spec/vendor/jquery-2.2.4.min.js +4 -0
  173. metadata +441 -0
@@ -0,0 +1,9 @@
1
+ class Hash
2
+ def shallow_to_n
3
+ hash = `{}`
4
+ self.map do |key, value|
5
+ `hash[#{key}] = #{value}`
6
+ end
7
+ hash
8
+ end
9
+ end
@@ -0,0 +1,8 @@
1
+ class String
2
+ def event_camelize
3
+ `#{self}.replace(/(^|_)([^_]+)/g, function(match, pre, word, index) {
4
+ var capitalize = true;
5
+ return capitalize ? word.substr(0,1).toUpperCase()+word.substr(1) : word;
6
+ })`
7
+ end
8
+ end
@@ -0,0 +1,53 @@
1
+ module React
2
+ class NativeLibrary
3
+ def self.renames_and_exclusions
4
+ @renames_and_exclusions ||= {}
5
+ end
6
+
7
+ def self.libraries
8
+ @libraries ||= []
9
+ end
10
+
11
+ def self.const_missing(name)
12
+ if renames_and_exclusions.has_key? name
13
+ if native_name = renames_and_exclusions[name]
14
+ native_name
15
+ else
16
+ super
17
+ end
18
+ else
19
+ libraries.each do |library|
20
+ native_name = "#{library}.#{name}"
21
+ native_component = `eval(#{native_name})` rescue nil
22
+ React::API.import_native_component(name, native_component) and return name if native_component and `native_component != undefined`
23
+ end
24
+ name
25
+ end
26
+ end
27
+
28
+ def self.method_missing(n, *args, &block)
29
+ name = n
30
+ if name =~ /_as_node$/
31
+ node_only = true
32
+ name = name.gsub(/_as_node$/, "")
33
+ end
34
+ unless name = const_get(name)
35
+ return super
36
+ end
37
+ React::RenderingContext.build_or_render(node_only, name, *args, &block)
38
+ rescue
39
+ end
40
+
41
+ def self.imports(library)
42
+ libraries << library
43
+ end
44
+
45
+ def self.rename(rename_list={})
46
+ renames_and_exclusions.merge!(rename_list.invert)
47
+ end
48
+
49
+ def self.exclude(*exclude_list)
50
+ renames_and_exclusions.merge(Hash[exclude_list.map {|k| [k, nil]}])
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,29 @@
1
+ module React
2
+ class Observable
3
+ def initialize(value, on_change = nil, &block)
4
+ @value = value
5
+ @on_change = on_change || block
6
+ end
7
+
8
+ def method_missing(method_sym, *args, &block)
9
+ @value.send(method_sym, *args, &block).tap { |result| @on_change.call @value }
10
+ end
11
+
12
+ def respond_to?(method, *args)
13
+ if [:call, :to_proc].include? method
14
+ true
15
+ else
16
+ @value.respond_to? method, *args
17
+ end
18
+ end
19
+
20
+ def call(new_value)
21
+ @on_change.call new_value
22
+ @value = new_value
23
+ end
24
+
25
+ def to_proc
26
+ lambda { |arg = @value| @on_change.call arg }
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,109 @@
1
+ module React
2
+ class RenderingContext
3
+ class << self
4
+ attr_accessor :waiting_on_resources
5
+ end
6
+
7
+ def self.build_or_render(node_only, name, *args, &block)
8
+ if node_only
9
+ React::RenderingContext.build { React::RenderingContext.render(name, *args, &block) }.to_n
10
+ else
11
+ React::RenderingContext.render(name, *args, &block)
12
+ end
13
+ end
14
+
15
+ def self.render(name, *args, &block)
16
+ remove_nodes_from_args(args)
17
+ @buffer = [] unless @buffer
18
+ if block
19
+ element = build do
20
+ saved_waiting_on_resources = waiting_on_resources
21
+ self.waiting_on_resources = nil
22
+ result = block.call
23
+ # Todo figure out how children rendering should happen, probably should have special method that pushes children into the buffer
24
+ # i.e. render_child/render_children that takes Element/Array[Element] and does the push into the buffer
25
+ if !name && ( # !name means called from outer render so we check that it has rendered correctly
26
+ (@buffer.count > 1) || # should only render one element
27
+ (@buffer.count == 1 && @buffer.last != result) || # it should return that element
28
+ (@buffer.count == 0 && !(result.is_a?(String) || (result.respond_to?(:acts_as_string?) && result.acts_as_string?) || result.is_a?(Element))) #for convience we will also convert the return value to a span if its a string
29
+ )
30
+ raise "a components render method must generate and return exactly 1 element or a string"
31
+ end
32
+
33
+ @buffer << result.to_s if result.is_a? String || (result.respond_to?(:acts_as_string?) && result.acts_as_string?) # For convience we push the last return value on if its a string
34
+ @buffer << result if result.is_a?(Element) && @buffer.count == 0
35
+ if name
36
+ buffer = @buffer.dup
37
+ React.create_element(name, *args) { buffer }.tap do |element|
38
+ element.waiting_on_resources = saved_waiting_on_resources || !!buffer.detect { |e| e.waiting_on_resources if e.respond_to?(:waiting_on_resources) }
39
+ end
40
+ elsif @buffer.last.is_a? React::Element
41
+ @buffer.last.tap { |element| element.waiting_on_resources ||= saved_waiting_on_resources }
42
+ else
43
+ @buffer.last.to_s.span.tap { |element| element.waiting_on_resources = saved_waiting_on_resources }
44
+ end
45
+ end
46
+ elsif name.is_a? React::Element
47
+ element = name
48
+ # I BELIEVE WAITING ON RESOURCES SHOULD ALREADY BE SET
49
+ else
50
+ element = React.create_element(name, *args)
51
+ element.waiting_on_resources = waiting_on_resources
52
+ end
53
+ @buffer << element
54
+ self.waiting_on_resources = nil
55
+ element
56
+ end
57
+
58
+ def self.build(&block)
59
+ current = @buffer
60
+ @buffer = []
61
+ return_val = yield @buffer
62
+ @buffer = current
63
+ return_val
64
+ #ensure
65
+ # @buffer = current
66
+ # return_val
67
+ end
68
+
69
+ def self.as_node(element)
70
+ @buffer.delete(element)
71
+ element
72
+ end
73
+
74
+ class << self; alias_method :delete, :as_node; end
75
+
76
+ def self.replace(e1, e2)
77
+ @buffer[@buffer.index(e1)] = e2
78
+ end
79
+
80
+ def self.remove_nodes_from_args(args)
81
+ args[0].each do |key, value|
82
+ value.as_node if value.is_a?(Element) rescue nil
83
+ end if args[0] && args[0].is_a?(Hash)
84
+ end
85
+ end
86
+
87
+ class ::Object
88
+ alias_method :old_method_missing, :method_missing
89
+
90
+ ["span", "para", "td", "th", "while_loading"].each do |tag|
91
+ define_method(tag) do | *args, &block |
92
+ args.unshift(tag)
93
+ return self.method_missing(*args, &block) if self.is_a? React::Component
94
+ React::RenderingContext.render(*args) { self.to_s }
95
+ end
96
+ end
97
+
98
+ def para(*args, &block)
99
+ args.unshift("p")
100
+ return self.method_missing(*args, &block) if self.is_a? React::Component
101
+ React::RenderingContext.render(*args) { self.to_s }
102
+ end
103
+
104
+ def br
105
+ return self.method_missing(*["br"]) if self.is_a? React::Component
106
+ React::RenderingContext.render("span") { React::RenderingContext.render(self.to_s); React::RenderingContext.render("br") }
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,140 @@
1
+ module React
2
+ class StateWrapper < BasicObject
3
+ def initialize(native, from)
4
+ @state_hash = Hash.new(`#{native}.state`)
5
+ @from = from
6
+ end
7
+
8
+ def [](state)
9
+ @state_hash[state]
10
+ end
11
+
12
+ def []=(state, new_value)
13
+ @state_hash[state] = new_value
14
+ end
15
+
16
+ def method_missing(method, *args)
17
+ if match = method.match(/^(.+)\!$/)
18
+ if args.count > 0
19
+ current_value = State.get_state(@from, match[1])
20
+ State.set_state(@from, $1, args[0])
21
+ current_value
22
+ else
23
+ current_state = State.get_state(@from, match[1])
24
+ State.set_state(@from, $1, current_state)
25
+ Observable.new(current_state) do |update|
26
+ State.set_state(@from, $1, update)
27
+ end
28
+ end
29
+ else
30
+ State.get_state(@from, method)
31
+ end
32
+ end
33
+ end
34
+
35
+ class State
36
+ class << self
37
+ attr_reader :current_observer
38
+
39
+ def initialize_states(object, initial_values) # initialize objects' name/value pairs
40
+ states[object].merge!(initial_values || {})
41
+ end
42
+
43
+ def get_state(object, name, current_observer = @current_observer)
44
+ # get current value of name for object, remember that the current object depends on this state, current observer can be overriden with last param
45
+ new_observers[current_observer][object] << name if current_observer && !new_observers[current_observer][object].include?(name)
46
+ states[object][name]
47
+ end
48
+
49
+ def set_state2(object, name, value) # set object's name state to value, tell all observers it has changed. Observers must implement update_react_js_state
50
+ object_needs_notification = object.respond_to? :update_react_js_state
51
+ observers_by_name[object][name].dup.each do |observer|
52
+ observer.update_react_js_state(object, name, value)
53
+ object_needs_notification = false if object == observer
54
+ end
55
+ object.update_react_js_state(nil, name, value) if object_needs_notification
56
+ end
57
+
58
+ def set_state(object, name, value, delay=nil)
59
+ states[object][name] = value
60
+ if delay
61
+ @delayed_updates ||= []
62
+ @delayed_updates << [object, name, value]
63
+ @delayed_updater ||= after(0.001) do
64
+ delayed_updates = @delayed_updates
65
+ @delayed_updates = []
66
+ @delayed_updater = nil
67
+ delayed_updates.each do |object, name, value|
68
+ set_state2(object, name, value)
69
+ end
70
+ end
71
+ else
72
+ set_state2(object, name, value)
73
+ end
74
+ value
75
+ end
76
+
77
+ def will_be_observing?(object, name, current_observer)
78
+ current_observer && new_observers[current_observer][object].include?(name)
79
+ end
80
+
81
+ def is_observing?(object, name, current_observer)
82
+ current_observer && observers_by_name[object][name].include?(current_observer)
83
+ end
84
+
85
+ def update_states_to_observe(current_observer = @current_observer) # should be called after the last after_render callback, currently called after components render method
86
+ raise "update_states_to_observer called outside of watch block" unless current_observer
87
+ current_observers[current_observer].each do |object, names|
88
+ names.each do |name|
89
+ observers_by_name[object][name].delete(current_observer)
90
+ end
91
+ end
92
+ observers = current_observers[current_observer] = new_observers[current_observer]
93
+ new_observers.delete(current_observer)
94
+ observers.each do |object, names|
95
+ names.each do |name|
96
+ observers_by_name[object][name] << current_observer
97
+ end
98
+ end
99
+ end
100
+
101
+ def remove # call after component is unmounted
102
+ raise "remove called outside of watch block" unless @current_observer
103
+ current_observers[@current_observer].each do |object, names|
104
+ names.each do |name|
105
+ observers_by_name[object][name].delete(@current_observer)
106
+ end
107
+ end
108
+ current_observers.delete(@current_observer)
109
+ end
110
+
111
+ def set_state_context_to(observer) # wrap all execution that may set or get states in a block so we know which observer is executing
112
+ if `typeof window.reactive_ruby_timing !== 'undefined'`
113
+ @nesting_level = (@nesting_level || 0) + 1
114
+ start_time = Time.now.to_f
115
+ observer_name = (observer.class.respond_to?(:name) ? observer.class.name : observer.to_s) rescue "object:#{observer.object_id}"
116
+ end
117
+ saved_current_observer = @current_observer
118
+ @current_observer = observer
119
+ return_value = yield
120
+ return_value
121
+ ensure
122
+ @current_observer = saved_current_observer
123
+ @nesting_level = [0, @nesting_level - 1].max if `typeof window.reactive_ruby_timing !== 'undefined'`
124
+ return_value
125
+ end
126
+
127
+ def states
128
+ @states ||= Hash.new { |h, k| h[k] = {} }
129
+ end
130
+
131
+ [:new_observers, :current_observers, :observers_by_name].each do |method_name|
132
+ define_method(method_name) do
133
+ instance_variable_get("@#{method_name}") or
134
+ instance_variable_set("@#{method_name}", Hash.new { |h, k| h[k] = Hash.new { |h, k| h[k] = [] } })
135
+ end
136
+ end
137
+
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,97 @@
1
+ require "native"
2
+ require 'active_support'
3
+ require 'react/component/base'
4
+
5
+ module React
6
+ HTML_TAGS = %w(a abbr address area article aside audio b base bdi bdo big blockquote body br
7
+ button canvas caption cite code col colgroup data datalist dd del details dfn
8
+ dialog div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5
9
+ h6 head header hr html i iframe img input ins kbd keygen label legend li link
10
+ main map mark menu menuitem meta meter nav noscript object ol optgroup option
11
+ output p param picture pre progress q rp rt ruby s samp script section select
12
+ small source span strong style sub summary sup table tbody td textarea tfoot th
13
+ thead time title tr track u ul var video wbr)
14
+ ATTRIBUTES = %w(accept acceptCharset accessKey action allowFullScreen allowTransparency alt
15
+ async autoComplete autoPlay cellPadding cellSpacing charSet checked classID
16
+ className cols colSpan content contentEditable contextMenu controls coords
17
+ crossOrigin data dateTime defer dir disabled download draggable encType form
18
+ formAction formEncType formMethod formNoValidate formTarget frameBorder height
19
+ hidden href hrefLang htmlFor httpEquiv icon id label lang list loop manifest
20
+ marginHeight marginWidth max maxLength media mediaGroup method min multiple
21
+ muted name noValidate open pattern placeholder poster preload radioGroup
22
+ readOnly rel required role rows rowSpan sandbox scope scrolling seamless
23
+ selected shape size sizes span spellCheck src srcDoc srcSet start step style
24
+ tabIndex target title type useMap value width wmode dangerouslySetInnerHTML)
25
+
26
+ def self.create_element(type, properties = {}, &block)
27
+ React::API.create_element(type, properties, &block)
28
+ end
29
+
30
+ def self.render(element, container)
31
+ container = `container.$$class ? container[0] : container`
32
+ if !(`typeof ReactDOM === 'undefined'`)
33
+ component = Native(`ReactDOM.render(#{element.to_n}, container, function(){#{yield if block_given?}})`) # v0.15+
34
+ elsif !(`typeof React.renderToString === 'undefined'`)
35
+ component = Native(`React.render(#{element.to_n}, container, function(){#{yield if block_given?}})`)
36
+ else
37
+ raise "render is not defined. In React >= v15 you must import it with ReactDOM"
38
+ end
39
+
40
+ component.class.include(React::Component::API)
41
+ component
42
+ end
43
+
44
+ def self.is_valid_element(element)
45
+ element.kind_of?(React::Element) && `React.isValidElement(#{element.to_n})`
46
+ end
47
+
48
+ def self.render_to_string(element)
49
+ if !(`typeof ReactDOMServer === 'undefined'`)
50
+ React::RenderingContext.build { `ReactDOMServer.renderToString(#{element.to_n})` } # v0.15+
51
+ elsif !(`typeof React.renderToString === 'undefined'`)
52
+ React::RenderingContext.build { `React.renderToString(#{element.to_n})` }
53
+ else
54
+ raise "renderToString is not defined. In React >= v15 you must import it with ReactDOMServer"
55
+ end
56
+ end
57
+
58
+ def self.render_to_static_markup(element)
59
+ if !(`typeof ReactDOMServer === 'undefined'`)
60
+ React::RenderingContext.build { `ReactDOMServer.renderToStaticMarkup(#{element.to_n})` } # v0.15+
61
+ elsif !(`typeof React.renderToString === 'undefined'`)
62
+ React::RenderingContext.build { `React.renderToStaticMarkup(#{element.to_n})` }
63
+ else
64
+ raise "renderToStaticMarkup is not defined. In React >= v15 you must import it with ReactDOMServer"
65
+ end
66
+ end
67
+
68
+ def self.unmount_component_at_node(node)
69
+ if !(`typeof ReactDOM === 'undefined'`)
70
+ `ReactDOM.unmountComponentAtNode(node.$$class ? node[0] : node)` # v0.15+
71
+ elsif !(`typeof React.renderToString === 'undefined'`)
72
+ `React.unmountComponentAtNode(node.$$class ? node[0] : node)`
73
+ else
74
+ raise "unmountComponentAtNode is not defined. In React >= v15 you must import it with ReactDOM"
75
+ end
76
+ end
77
+
78
+ end
79
+
80
+ Element.instance_eval do
81
+
82
+ class ::Element::DummyContext < React::Component::Base
83
+ end
84
+
85
+ def self.find(selector)
86
+ selector = selector.dom_node if selector.respond_to? :dom_node rescue selector
87
+ `$(#{selector})`
88
+ end
89
+
90
+ def self.[](selector)
91
+ find(selector)
92
+ end
93
+
94
+ def render(&block)
95
+ React.render(React::RenderingContext.render(nil) {::Element::DummyContext.new.instance_eval &block}, self)
96
+ end
97
+ end if Object.const_defined?("Element")