reactive-ruby 0.7.3
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.
- checksums.yaml +7 -0
- data/.gitignore +30 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +53 -0
- data/LICENSE +19 -0
- data/README.md +303 -0
- data/config.ru +15 -0
- data/example/examples/Gemfile +7 -0
- data/example/examples/Gemfile.lock +45 -0
- data/example/examples/config.ru +44 -0
- data/example/examples/hello.js.rb +43 -0
- data/example/react-tutorial/Gemfile +7 -0
- data/example/react-tutorial/Gemfile.lock +49 -0
- data/example/react-tutorial/README.md +8 -0
- data/example/react-tutorial/_comments.json +14 -0
- data/example/react-tutorial/config.ru +63 -0
- data/example/react-tutorial/example.js.rb +290 -0
- data/example/react-tutorial/public/base.css +62 -0
- data/example/todos/Gemfile +11 -0
- data/example/todos/Gemfile.lock +84 -0
- data/example/todos/README.md +37 -0
- data/example/todos/Rakefile +8 -0
- data/example/todos/app/application.rb +22 -0
- data/example/todos/app/components/app.react.rb +61 -0
- data/example/todos/app/components/footer.react.rb +31 -0
- data/example/todos/app/components/todo_item.react.rb +46 -0
- data/example/todos/app/components/todo_list.react.rb +25 -0
- data/example/todos/app/models/todo.rb +19 -0
- data/example/todos/config.ru +14 -0
- data/example/todos/index.html.haml +16 -0
- data/example/todos/spec/todo_spec.rb +28 -0
- data/example/todos/vendor/base.css +410 -0
- data/example/todos/vendor/bg.png +0 -0
- data/example/todos/vendor/jquery.js +4 -0
- data/lib/rails-helpers/react_component.rb +32 -0
- data/lib/reactive-ruby.rb +23 -0
- data/lib/reactive-ruby/api.rb +177 -0
- data/lib/reactive-ruby/callbacks.rb +35 -0
- data/lib/reactive-ruby/component.rb +411 -0
- data/lib/reactive-ruby/element.rb +87 -0
- data/lib/reactive-ruby/event.rb +76 -0
- data/lib/reactive-ruby/ext/hash.rb +9 -0
- data/lib/reactive-ruby/ext/string.rb +8 -0
- data/lib/reactive-ruby/isomorphic_helpers.rb +223 -0
- data/lib/reactive-ruby/observable.rb +33 -0
- data/lib/reactive-ruby/rendering_context.rb +91 -0
- data/lib/reactive-ruby/serializers.rb +15 -0
- data/lib/reactive-ruby/state.rb +90 -0
- data/lib/reactive-ruby/top_level.rb +53 -0
- data/lib/reactive-ruby/validator.rb +83 -0
- data/lib/reactive-ruby/version.rb +3 -0
- data/logo1.png +0 -0
- data/logo2.png +0 -0
- data/logo3.png +0 -0
- data/reactive-ruby.gemspec +25 -0
- data/spec/callbacks_spec.rb +107 -0
- data/spec/component_spec.rb +597 -0
- data/spec/element_spec.rb +60 -0
- data/spec/event_spec.rb +22 -0
- data/spec/react_spec.rb +209 -0
- data/spec/reactjs/index.html.erb +11 -0
- data/spec/spec_helper.rb +29 -0
- data/spec/tutorial/tutorial_spec.rb +37 -0
- data/spec/validator_spec.rb +79 -0
- data/vendor/active_support/core_ext/array/extract_options.rb +29 -0
- data/vendor/active_support/core_ext/class/attribute.rb +127 -0
- data/vendor/active_support/core_ext/kernel/singleton_class.rb +13 -0
- data/vendor/active_support/core_ext/module/remove_method.rb +11 -0
- metadata +205 -0
@@ -0,0 +1,87 @@
|
|
1
|
+
require "reactive-ruby/ext/string"
|
2
|
+
|
3
|
+
module React
|
4
|
+
class Element
|
5
|
+
include Native
|
6
|
+
|
7
|
+
alias_native :element_type, :type
|
8
|
+
alias_native :props, :props
|
9
|
+
|
10
|
+
attr_reader :type
|
11
|
+
attr_reader :properties
|
12
|
+
attr_reader :block
|
13
|
+
|
14
|
+
attr_accessor :waiting_on_resources
|
15
|
+
|
16
|
+
def initialize(native_element, type, properties, block)
|
17
|
+
@type = type
|
18
|
+
@properties = properties
|
19
|
+
@block = block
|
20
|
+
@native = native_element
|
21
|
+
end
|
22
|
+
|
23
|
+
def on(event_name)
|
24
|
+
name = event_name.to_s.event_camelize
|
25
|
+
if React::Event::BUILT_IN_EVENTS.include?("on#{name}")
|
26
|
+
self.props["on#{name}"] = %x{
|
27
|
+
function(event){
|
28
|
+
#{yield React::Event.new(`event`)}
|
29
|
+
}
|
30
|
+
}
|
31
|
+
else
|
32
|
+
self.props["_on#{name}"] = %x{
|
33
|
+
function(){
|
34
|
+
#{yield *Array(`arguments`)}
|
35
|
+
}
|
36
|
+
}
|
37
|
+
end
|
38
|
+
self
|
39
|
+
end
|
40
|
+
|
41
|
+
def method_missing(class_name, args = {}, &new_block)
|
42
|
+
class_name = class_name.split("__").collect { |s| s.gsub("_", "-") }.join("_")
|
43
|
+
new_props = properties.dup
|
44
|
+
new_props["class"] = "#{new_props['class']} #{class_name} #{args.delete("class")} #{args.delete('className')}".split(" ").uniq.join(" ")
|
45
|
+
new_props.merge! args
|
46
|
+
RenderingContext.replace(
|
47
|
+
self,
|
48
|
+
React::RenderingContext.build { React::RenderingContext.render(type, new_props, &new_block) }
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
52
|
+
def delete
|
53
|
+
RenderingContext.delete(self)
|
54
|
+
end
|
55
|
+
|
56
|
+
def children
|
57
|
+
nodes = self.props.children
|
58
|
+
class << nodes
|
59
|
+
include Enumerable
|
60
|
+
|
61
|
+
def to_n
|
62
|
+
self
|
63
|
+
end
|
64
|
+
|
65
|
+
def each(&block)
|
66
|
+
if block_given?
|
67
|
+
%x{
|
68
|
+
React.Children.forEach(#{self.to_n}, function(context){
|
69
|
+
#{block.call(React::Element.new(`context`))}
|
70
|
+
})
|
71
|
+
}
|
72
|
+
else
|
73
|
+
Enumerator.new(`React.Children.count(#{self.to_n})`) do |y|
|
74
|
+
%x{
|
75
|
+
React.Children.forEach(#{self.to_n}, function(context){
|
76
|
+
#{y << React::Element.new(`context`)}
|
77
|
+
})
|
78
|
+
}
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
nodes
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module React
|
2
|
+
class Event
|
3
|
+
include Native
|
4
|
+
alias_native :bubbles, :bubbles
|
5
|
+
alias_native :cancelable, :cancelable
|
6
|
+
alias_native :current_target, :currentTarget
|
7
|
+
alias_native :default_prevented, :defaultPrevented
|
8
|
+
alias_native :event_phase, :eventPhase
|
9
|
+
alias_native :is_trusted?, :isTrusted
|
10
|
+
alias_native :native_event, :nativeEvent
|
11
|
+
alias_native :target, :target
|
12
|
+
alias_native :timestamp, :timeStamp
|
13
|
+
alias_native :event_type, :type
|
14
|
+
alias_native :prevent_default, :preventDefault
|
15
|
+
alias_native :stop_propagation, :stopPropagation
|
16
|
+
# Clipboard
|
17
|
+
alias_native :clipboard_data, :clipboardData
|
18
|
+
# Keyboard
|
19
|
+
alias_native :alt_key, :altKey
|
20
|
+
alias_native :char_code, :charCode
|
21
|
+
alias_native :ctrl_key, :ctrlKey
|
22
|
+
alias_native :get_modifier_state, :getModifierState
|
23
|
+
alias_native :key, :key
|
24
|
+
alias_native :key_code, :keyCode
|
25
|
+
alias_native :locale, :locale
|
26
|
+
alias_native :location, :location
|
27
|
+
alias_native :meta_key, :metaKey
|
28
|
+
alias_native :repeat, :repeat
|
29
|
+
alias_native :shift_key, :shiftKey
|
30
|
+
alias_native :which, :which
|
31
|
+
# Focus
|
32
|
+
alias_native :related_target, :relatedTarget
|
33
|
+
# Mouse
|
34
|
+
alias_native :alt_key, :altKey
|
35
|
+
alias_native :button, :button
|
36
|
+
alias_native :buttons, :buttons
|
37
|
+
alias_native :client_x, :clientX
|
38
|
+
alias_native :client_y, :clientY
|
39
|
+
alias_native :ctrl_key, :ctrlKey
|
40
|
+
alias_native :get_modifier_state, :getModifierState
|
41
|
+
alias_native :meta_key, :metaKey
|
42
|
+
alias_native :page_x, :pageX
|
43
|
+
alias_native :page_y, :pageY
|
44
|
+
alias_native :related_target, :relatedTarget
|
45
|
+
alias_native :screen_x, :screen_x
|
46
|
+
alias_native :screen_y, :screen_y
|
47
|
+
alias_native :shift_key, :shift_key
|
48
|
+
# Touch
|
49
|
+
alias_native :alt_key, :altKey
|
50
|
+
alias_native :changed_touches, :changedTouches
|
51
|
+
alias_native :ctrl_key, :ctrlKey
|
52
|
+
alias_native :get_modifier_state, :getModifierState
|
53
|
+
alias_native :meta_key, :metaKey
|
54
|
+
alias_native :shift_key, :shiftKey
|
55
|
+
alias_native :target_touches, :targetTouches
|
56
|
+
alias_native :touches, :touches
|
57
|
+
# UI
|
58
|
+
alias_native :detail, :detail
|
59
|
+
alias_native :view, :view
|
60
|
+
# Wheel
|
61
|
+
alias_native :delta_mode, :deltaMode
|
62
|
+
alias_native :delta_x, :deltaX
|
63
|
+
alias_native :delta_y, :deltaY
|
64
|
+
alias_native :delta_z, :deltaZ
|
65
|
+
|
66
|
+
BUILT_IN_EVENTS = %w{onCopy onCut onPaste onKeyDown onKeyPress onKeyUp
|
67
|
+
onFocus onBlur onChange onInput onSubmit onClick onDoubleClick onDrag
|
68
|
+
onDragEnd onDragEnter onDragExit onDragLeave onDragOver onDragStart onDrop
|
69
|
+
onMouseDown onMouseEnter onMouseLeave onMouseMove onMouseOut onMouseOver
|
70
|
+
onMouseUp onTouchCancel onTouchEnd onTouchMove onTouchStart onScroll}
|
71
|
+
|
72
|
+
def initialize(native_element)
|
73
|
+
@native = native_element
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,223 @@
|
|
1
|
+
module React
|
2
|
+
|
3
|
+
module IsomorphicHelpers
|
4
|
+
|
5
|
+
def self.included(base)
|
6
|
+
base.extend(ClassMethods)
|
7
|
+
end
|
8
|
+
|
9
|
+
if RUBY_ENGINE != 'opal'
|
10
|
+
|
11
|
+
def self.load_context(ctx, controller)
|
12
|
+
puts "************************** React Server Context Initialized *********************************************"
|
13
|
+
@context = Context.new("#{controller.object_id}-#{Time.now.to_i}", ctx, controller)
|
14
|
+
end
|
15
|
+
|
16
|
+
else
|
17
|
+
|
18
|
+
def self.load_context(unique_id = nil) # can be called on the client to force re-initialization for testing purposes
|
19
|
+
if !unique_id or !@context or @context.unique_id != unique_id
|
20
|
+
if on_opal_server?
|
21
|
+
message = "************************ React Prerendering Context Initialized ***********************"
|
22
|
+
else
|
23
|
+
message = "************************ React Browser Context Initialized ****************************"
|
24
|
+
end
|
25
|
+
log(message)
|
26
|
+
@context = Context.new(unique_id)
|
27
|
+
end
|
28
|
+
@context
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.log(message, message_type = :info)
|
34
|
+
message = [message] unless message.is_a? Array
|
35
|
+
if message_type == :info
|
36
|
+
if on_opal_server?
|
37
|
+
style = 'background: #00FFFF; color: red'
|
38
|
+
else
|
39
|
+
style = 'background: #222; color: #bada55'
|
40
|
+
end
|
41
|
+
message = ["%c" + message[0], style]+message[1..-1]
|
42
|
+
`console.log.apply(console, message)`
|
43
|
+
elsif message_type == :warning
|
44
|
+
`console.warn.apply(console, message)`
|
45
|
+
else
|
46
|
+
`console.error.apply(console, message)`
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
if RUBY_ENGINE != 'opal'
|
51
|
+
|
52
|
+
def self.on_opal_server?
|
53
|
+
false
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.on_opal_client?
|
57
|
+
false
|
58
|
+
end
|
59
|
+
|
60
|
+
else
|
61
|
+
|
62
|
+
def self.on_opal_server?
|
63
|
+
`typeof window.document === 'undefined'`
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.on_opal_client?
|
67
|
+
!on_opal_server?
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
def log(*args)
|
73
|
+
IsomorphicHelpers.log(*args)
|
74
|
+
end
|
75
|
+
|
76
|
+
def on_opal_server?
|
77
|
+
IsomorphicHelpers.on_opal_server?
|
78
|
+
end
|
79
|
+
|
80
|
+
def on_opal_client?
|
81
|
+
IsomorphicHelpers.on_opal_client?
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.prerender_footers
|
85
|
+
footer = Context.prerender_footer_blocks.collect { |block| block.call }.join("\n")
|
86
|
+
if RUBY_ENGINE != 'opal'
|
87
|
+
footer = (footer + "#{@context.send_to_opal(:prerender_footers)}") if @context
|
88
|
+
footer = footer.html_safe
|
89
|
+
end
|
90
|
+
footer
|
91
|
+
end
|
92
|
+
|
93
|
+
class Context
|
94
|
+
|
95
|
+
attr_reader :controller
|
96
|
+
attr_reader :unique_id
|
97
|
+
|
98
|
+
def self.before_first_mount_blocks
|
99
|
+
@before_first_mount_blocks ||= []
|
100
|
+
end
|
101
|
+
|
102
|
+
def self.prerender_footer_blocks
|
103
|
+
@prerender_footer_blocks ||= []
|
104
|
+
end
|
105
|
+
|
106
|
+
def initialize(unique_id, ctx = nil, controller = nil)
|
107
|
+
@unique_id = unique_id
|
108
|
+
if RUBY_ENGINE != 'opal'
|
109
|
+
@controller = controller
|
110
|
+
@ctx = ctx
|
111
|
+
ctx["ServerSideIsomorphicMethods"] = self
|
112
|
+
send_to_opal(:load_context, @unique_id)
|
113
|
+
end
|
114
|
+
self.class.before_first_mount_blocks.each { |block| block.call(self) }
|
115
|
+
end
|
116
|
+
|
117
|
+
def eval(js)
|
118
|
+
@ctx.eval(js) if @ctx
|
119
|
+
end
|
120
|
+
|
121
|
+
def send_to_opal(method, *args)
|
122
|
+
args = [1] if args.length == 0
|
123
|
+
if @ctx
|
124
|
+
unless @ctx.eval('Opal.React')
|
125
|
+
@ctx.eval(Opal::Processor.load_asset_code(::Rails.application.assets, 'components')) rescue nil
|
126
|
+
raise "No opal-react components found in the components.rb file" unless @ctx.eval('Opal.React')
|
127
|
+
end
|
128
|
+
@ctx.eval("Opal.React.IsomorphicHelpers.$#{method}(#{args.join(', ')})")
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def self.register_before_first_mount_block(&block)
|
133
|
+
before_first_mount_blocks << block
|
134
|
+
end
|
135
|
+
|
136
|
+
def self.register_prerender_footer_block(&block)
|
137
|
+
prerender_footer_blocks << block
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
|
142
|
+
class IsomorphicProcCall
|
143
|
+
|
144
|
+
def result
|
145
|
+
@result.first if @result
|
146
|
+
end
|
147
|
+
|
148
|
+
def initialize(name, block, *args)
|
149
|
+
@name = name
|
150
|
+
block.call(self, *args)
|
151
|
+
@result ||= send_to_server(*args) if IsomorphicHelpers.on_opal_server?
|
152
|
+
end
|
153
|
+
|
154
|
+
def when_on_client(&block)
|
155
|
+
@result = [block.call] if IsomorphicHelpers.on_opal_client?
|
156
|
+
end
|
157
|
+
|
158
|
+
def send_to_server(*args)
|
159
|
+
if IsomorphicHelpers.on_opal_server?
|
160
|
+
args_as_json = args.to_json
|
161
|
+
@result = [JSON.parse(`window.ServerSideIsomorphicMethods[#{@name}](#{args_as_json})`)]
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def when_on_server(&block)
|
166
|
+
@result = [block.call.to_json] unless IsomorphicHelpers.on_opal_client? or IsomorphicHelpers.on_opal_server?
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|
170
|
+
|
171
|
+
|
172
|
+
module ClassMethods
|
173
|
+
|
174
|
+
def on_opal_server?
|
175
|
+
IsomorphicHelpers.on_opal_server?
|
176
|
+
end
|
177
|
+
|
178
|
+
def on_opal_client?
|
179
|
+
IsomorphicHelpers.on_opal_client?
|
180
|
+
end
|
181
|
+
|
182
|
+
def log(*args)
|
183
|
+
IsomorphicHelpers.log(*args)
|
184
|
+
end
|
185
|
+
|
186
|
+
def controller
|
187
|
+
IsomorphicHelpers.context.controller
|
188
|
+
end
|
189
|
+
|
190
|
+
def before_first_mount(&block)
|
191
|
+
React::IsomorphicHelpers::Context.register_before_first_mount_block &block
|
192
|
+
end
|
193
|
+
|
194
|
+
def prerender_footer(&block)
|
195
|
+
React::IsomorphicHelpers::Context.register_prerender_footer_block &block
|
196
|
+
end
|
197
|
+
|
198
|
+
if RUBY_ENGINE != 'opal'
|
199
|
+
|
200
|
+
def isomorphic_method(name, &block)
|
201
|
+
React::IsomorphicHelpers::Context.send(:define_method, name) do |args_as_json|
|
202
|
+
React::IsomorphicHelpers::IsomorphicProcCall.new(name, block, *JSON.parse(args_as_json)).result
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
else
|
207
|
+
|
208
|
+
require 'json'
|
209
|
+
|
210
|
+
def isomorphic_method(name, &block)
|
211
|
+
self.class.send(:define_method, name) do | *args |
|
212
|
+
React::IsomorphicHelpers::IsomorphicProcCall.new(name, block, *args).result
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
end
|
217
|
+
|
218
|
+
|
219
|
+
end
|
220
|
+
|
221
|
+
end
|
222
|
+
|
223
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module React
|
2
|
+
|
3
|
+
class Observable
|
4
|
+
|
5
|
+
def initialize(value, on_change = nil, &block)
|
6
|
+
@value = value
|
7
|
+
@on_change = on_change || block
|
8
|
+
end
|
9
|
+
|
10
|
+
def method_missing(method_sym, *args, &block)
|
11
|
+
@value.send(method_sym, *args, &block).tap { |result| @on_change.call result }
|
12
|
+
end
|
13
|
+
|
14
|
+
def respond_to?(method, *args)
|
15
|
+
if [:call, :to_proc].include? method
|
16
|
+
true
|
17
|
+
else
|
18
|
+
@value.respond_to? method, *args
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def call(new_value)
|
23
|
+
@on_change.call new_value
|
24
|
+
@value = new_value
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_proc
|
28
|
+
lambda { |arg = @value| @on_change.call arg }
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module React
|
2
|
+
|
3
|
+
class RenderingContext
|
4
|
+
|
5
|
+
class << self
|
6
|
+
attr_accessor :waiting_on_resources
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.render(name, *args, &block)
|
10
|
+
@buffer = [] unless @buffer
|
11
|
+
if block
|
12
|
+
element = build do
|
13
|
+
saved_waiting_on_resources = waiting_on_resources
|
14
|
+
self.waiting_on_resources = nil
|
15
|
+
result = block.call
|
16
|
+
# Todo figure out how children rendering should happen, probably should have special method that pushes children into the buffer
|
17
|
+
# i.e. render_child/render_children that takes Element/Array[Element] and does the push into the buffer
|
18
|
+
if !name and ( # !name means called from outer render so we check that it has rendered correctly
|
19
|
+
(@buffer.count > 1) or # should only render one element
|
20
|
+
(@buffer.count == 1 and @buffer.last != result) or # it should return that element
|
21
|
+
(@buffer.count == 0 and !(result.is_a? String or (result.respond_to? :acts_as_string? and result.acts_as_string?) or result.is_a? Element)) #for convience we will also convert the return value to a span if its a string
|
22
|
+
)
|
23
|
+
raise "a components render method must generate and return exactly 1 element or a string"
|
24
|
+
end
|
25
|
+
|
26
|
+
@buffer << result.to_s if result.is_a? String or (result.respond_to? :acts_as_string? and result.acts_as_string?) # For convience we push the last return value on if its a string
|
27
|
+
@buffer << result if result.is_a? Element and @buffer.count == 0
|
28
|
+
if name
|
29
|
+
buffer = @buffer.dup
|
30
|
+
React.create_element(name, *args) { buffer }.tap do |element|
|
31
|
+
element.waiting_on_resources = saved_waiting_on_resources || !!buffer.detect { |e| e.waiting_on_resources if e.respond_to? :waiting_on_resources }
|
32
|
+
end
|
33
|
+
elsif @buffer.last.is_a? React::Element
|
34
|
+
@buffer.last.tap { |element| element.waiting_on_resources ||= saved_waiting_on_resources }
|
35
|
+
else
|
36
|
+
@buffer.last.to_s.span.tap { |element| element.waiting_on_resources = saved_waiting_on_resources }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
else
|
40
|
+
element = React.create_element(name, *args)
|
41
|
+
element.waiting_on_resources = waiting_on_resources
|
42
|
+
end
|
43
|
+
@buffer << element
|
44
|
+
self.waiting_on_resources = nil
|
45
|
+
element
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.build(&block)
|
49
|
+
current = @buffer
|
50
|
+
@buffer = []
|
51
|
+
return_val = yield @buffer
|
52
|
+
@buffer = current
|
53
|
+
return_val
|
54
|
+
#ensure
|
55
|
+
# @buffer = current
|
56
|
+
# return_val
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.as_node(element)
|
60
|
+
@buffer.delete(element)
|
61
|
+
element
|
62
|
+
end
|
63
|
+
|
64
|
+
class << self; alias_method :delete, :as_node; end
|
65
|
+
|
66
|
+
def self.replace(e1, e2)
|
67
|
+
@buffer[@buffer.index(e1)] = e2
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
class ::Object
|
73
|
+
|
74
|
+
alias_method :old_method_missing, :method_missing
|
75
|
+
|
76
|
+
["span", "para", "td", "th", "while_loading"].each do |tag|
|
77
|
+
define_method(tag) do | *args, &block |
|
78
|
+
args.unshift(tag)
|
79
|
+
return self.method_missing(*args, &block) if self.is_a? React::Component
|
80
|
+
React::RenderingContext.render(*args) { self.to_s }
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def br
|
85
|
+
return self.method_missing(*["br"]) if self.is_a? React::Component
|
86
|
+
React::RenderingContext.render("span") { React::RenderingContext.render(self.to_s); React::RenderingContext.render("br") }
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|