ovto 0.5.0 → 0.6.2
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 +4 -4
- data/.gitmodules +3 -0
- data/CHANGELOG.md +14 -2
- data/Gemfile +2 -3
- data/Gemfile.lock +23 -27
- data/book/SUMMARY.md +2 -0
- data/book/api/actions.md +1 -1
- data/book/api/middleware.md +99 -0
- data/book/api/pure_component.md +3 -0
- data/docs/api/Array.html +190 -0
- data/docs/api/Hash.html +196 -0
- data/docs/api/Ovto/Actions.html +128 -40
- data/docs/api/Ovto/App.html +254 -40
- data/docs/api/Ovto/Component/MoreThanOneNode.html +6 -6
- data/docs/api/Ovto/Component.html +96 -29
- data/docs/api/Ovto/Middleware/Actions.html +428 -0
- data/docs/api/Ovto/Middleware/Base.html +605 -0
- data/docs/api/Ovto/Middleware/Component.html +354 -0
- data/docs/api/Ovto/Middleware.html +286 -0
- data/docs/api/Ovto/PureComponent/StateIsNotAvailable.html +6 -6
- data/docs/api/Ovto/PureComponent.html +11 -11
- data/docs/api/Ovto/Runtime.html +7 -7
- data/docs/api/Ovto/State/MissingValue.html +6 -6
- data/docs/api/Ovto/State/{UnknownKey.html → UnknownStateKey.html} +11 -11
- data/docs/api/Ovto/State.html +59 -43
- data/docs/api/Ovto/WiredActionSet.html +636 -0
- data/docs/api/Ovto/WiredActions.html +78 -35
- data/docs/api/Ovto.html +223 -30
- data/docs/api/_index.html +77 -11
- data/docs/api/actions.html +29 -3
- data/docs/api/app.html +28 -2
- data/docs/api/class_list.html +3 -3
- data/docs/api/component.html +30 -4
- data/docs/api/css/style.css +3 -2
- data/docs/api/fetch.html +30 -4
- data/docs/api/file.README.html +76 -78
- data/docs/api/file_list.html +2 -2
- data/docs/api/frames.html +2 -2
- data/docs/api/index.html +76 -78
- data/docs/api/js/app.js +14 -3
- data/docs/api/method_list.html +303 -31
- data/docs/api/middleware.html +498 -0
- data/docs/api/pure_component.html +428 -0
- data/docs/api/state.html +28 -2
- data/docs/api/top-level-namespace.html +11 -9
- data/docs/guides/debugging.html +28 -2
- data/docs/guides/development.html +28 -2
- data/docs/guides/install.html +28 -2
- data/docs/guides/tutorial.html +28 -2
- data/docs/index.html +28 -2
- data/docs/search_index.json +1 -1
- data/examples/sinatra/Gemfile +2 -0
- data/examples/sinatra/Gemfile.lock +32 -30
- data/examples/sinatra/app.rb +1 -4
- data/examples/sinatra/config.ru +6 -6
- data/examples/static/Gemfile.lock +9 -9
- data/lib/ovto/actions.rb +11 -0
- data/lib/ovto/app.rb +37 -13
- data/lib/ovto/component.rb +130 -67
- data/lib/ovto/middleware.rb +121 -0
- data/lib/ovto/pure_component.rb +1 -1
- data/lib/ovto/state.rb +13 -5
- data/lib/ovto/version.rb +1 -1
- data/lib/ovto/wired_action_set.rb +40 -0
- data/lib/ovto/wired_actions.rb +49 -11
- data/lib/ovto.rb +26 -0
- data/ovto.gemspec +1 -1
- metadata +21 -11
- data/docs/api/pure_component.md +0 -27
data/examples/sinatra/Gemfile
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ../..
|
3
3
|
specs:
|
4
|
-
ovto (0.
|
4
|
+
ovto (0.6.0)
|
5
5
|
opal (>= 0.11, < 2)
|
6
6
|
rack (~> 2.0)
|
7
7
|
thor (~> 0.20)
|
@@ -9,44 +9,44 @@ PATH
|
|
9
9
|
GEM
|
10
10
|
remote: https://rubygems.org/
|
11
11
|
specs:
|
12
|
-
ast (2.4.
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
opal (
|
12
|
+
ast (2.4.2)
|
13
|
+
concurrent-ruby (1.1.9)
|
14
|
+
multi_json (1.15.0)
|
15
|
+
mustermann (1.1.1)
|
16
|
+
ruby2_keywords (~> 0.0.1)
|
17
|
+
nio4r (2.5.8)
|
18
|
+
opal (1.2.0)
|
19
19
|
ast (>= 2.3.0)
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
opal (~> 0.11.0)
|
25
|
-
sprockets (~> 3.7)
|
20
|
+
parser (~> 3.0)
|
21
|
+
opal-sprockets (1.0.2)
|
22
|
+
opal (>= 1.0, < 2.0)
|
23
|
+
sprockets (~> 4.0)
|
26
24
|
tilt (>= 1.4)
|
27
|
-
parser (
|
28
|
-
ast (~> 2.
|
29
|
-
|
30
|
-
|
25
|
+
parser (3.0.2.0)
|
26
|
+
ast (~> 2.4.1)
|
27
|
+
puma (5.5.2)
|
28
|
+
nio4r (~> 2.0)
|
29
|
+
rack (2.2.3)
|
30
|
+
rack-protection (2.1.0)
|
31
31
|
rack
|
32
|
-
|
32
|
+
rake (13.0.6)
|
33
|
+
ruby2_keywords (0.0.5)
|
34
|
+
sinatra (2.1.0)
|
33
35
|
mustermann (~> 1.0)
|
34
|
-
rack (~> 2.
|
35
|
-
rack-protection (= 2.0
|
36
|
+
rack (~> 2.2)
|
37
|
+
rack-protection (= 2.1.0)
|
36
38
|
tilt (~> 2.0)
|
37
|
-
sinatra-contrib (2.0
|
38
|
-
backports (>= 2.8.2)
|
39
|
+
sinatra-contrib (2.1.0)
|
39
40
|
multi_json
|
40
41
|
mustermann (~> 1.0)
|
41
|
-
rack-protection (= 2.0
|
42
|
-
sinatra (= 2.0
|
43
|
-
tilt (
|
44
|
-
|
45
|
-
sprockets (3.7.2)
|
42
|
+
rack-protection (= 2.1.0)
|
43
|
+
sinatra (= 2.1.0)
|
44
|
+
tilt (~> 2.0)
|
45
|
+
sprockets (4.0.2)
|
46
46
|
concurrent-ruby (~> 1.0)
|
47
47
|
rack (> 1, < 3)
|
48
48
|
thor (0.20.3)
|
49
|
-
tilt (2.0.
|
49
|
+
tilt (2.0.10)
|
50
50
|
|
51
51
|
PLATFORMS
|
52
52
|
ruby
|
@@ -54,9 +54,11 @@ PLATFORMS
|
|
54
54
|
DEPENDENCIES
|
55
55
|
opal-sprockets
|
56
56
|
ovto!
|
57
|
+
puma
|
57
58
|
rack
|
59
|
+
rake
|
58
60
|
sinatra
|
59
61
|
sinatra-contrib
|
60
62
|
|
61
63
|
BUNDLED WITH
|
62
|
-
2.
|
64
|
+
2.2.22
|
data/examples/sinatra/app.rb
CHANGED
@@ -3,16 +3,13 @@ require 'sinatra/reloader'
|
|
3
3
|
require 'opal'
|
4
4
|
|
5
5
|
class SinatraApp < Sinatra::Base
|
6
|
-
# Proc to generate javascript include tag (see config.ru)
|
7
|
-
set :generate_javascript_include_tag, nil
|
8
|
-
|
9
6
|
configure(:development) do
|
10
7
|
register Sinatra::Reloader
|
11
8
|
also_reload "#{__dir__}/**/*.rb"
|
12
9
|
end
|
13
10
|
|
14
11
|
get '/' do
|
15
|
-
@js_tag =
|
12
|
+
@js_tag = $GENERATE_JAVASCRIPT_INCLUDE_TAG.call # Defined in config.ru
|
16
13
|
erb :index # Render views/index.erb
|
17
14
|
end
|
18
15
|
end
|
data/examples/sinatra/config.ru
CHANGED
@@ -2,20 +2,20 @@ require 'opal/sprockets'
|
|
2
2
|
require_relative './app.rb'
|
3
3
|
|
4
4
|
Opal.use_gem 'ovto'
|
5
|
-
|
5
|
+
opal_server = Opal::Sprockets::Server.new {|s|
|
6
6
|
s.append_path './ovto/'
|
7
7
|
s.main = 'app'
|
8
8
|
}
|
9
9
|
|
10
|
-
sprockets =
|
10
|
+
sprockets = opal_server.sprockets
|
11
11
|
prefix = '/assets'
|
12
12
|
|
13
13
|
map prefix do
|
14
14
|
run sprockets
|
15
15
|
end
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
::Opal::Sprockets.javascript_include_tag('app', sprockets: sprockets, prefix: prefix, debug: true)
|
20
|
-
}
|
17
|
+
$GENERATE_JAVASCRIPT_INCLUDE_TAG = ->{
|
18
|
+
::Opal::Sprockets.javascript_include_tag('app', sprockets: sprockets, prefix: prefix, debug: true)
|
21
19
|
}
|
20
|
+
|
21
|
+
run SinatraApp
|
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ../..
|
3
3
|
specs:
|
4
|
-
ovto (0.
|
4
|
+
ovto (0.6.0)
|
5
5
|
opal (>= 0.11, < 2)
|
6
6
|
rack (~> 2.0)
|
7
7
|
thor (~> 0.20)
|
@@ -9,15 +9,15 @@ PATH
|
|
9
9
|
GEM
|
10
10
|
remote: https://rubygems.org/
|
11
11
|
specs:
|
12
|
-
ast (2.4.
|
12
|
+
ast (2.4.2)
|
13
13
|
ifchanged (1.0.1)
|
14
|
-
opal (1.0
|
14
|
+
opal (1.2.0)
|
15
15
|
ast (>= 2.3.0)
|
16
|
-
parser (~>
|
17
|
-
parser (
|
18
|
-
ast (~> 2.4.
|
19
|
-
rack (2.
|
20
|
-
rake (
|
16
|
+
parser (~> 3.0)
|
17
|
+
parser (3.0.2.0)
|
18
|
+
ast (~> 2.4.1)
|
19
|
+
rack (2.2.3)
|
20
|
+
rake (13.0.6)
|
21
21
|
thor (0.20.3)
|
22
22
|
|
23
23
|
PLATFORMS
|
@@ -29,4 +29,4 @@ DEPENDENCIES
|
|
29
29
|
rake
|
30
30
|
|
31
31
|
BUNDLED WITH
|
32
|
-
2.
|
32
|
+
2.2.22
|
data/lib/ovto/actions.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
module Ovto
|
2
2
|
# Base class for ovto actions.
|
3
3
|
class Actions
|
4
|
+
# WiredActions must be set after initialization
|
5
|
+
# (this cannot be an argument of #initialize because Actions and
|
6
|
+
# WiredActions have references to each other)
|
4
7
|
attr_writer :wired_actions
|
5
8
|
|
6
9
|
def actions
|
@@ -10,5 +13,13 @@ module Ovto
|
|
10
13
|
def state
|
11
14
|
@wired_actions._app.state
|
12
15
|
end
|
16
|
+
|
17
|
+
def middleware_name
|
18
|
+
WiredActionSet::I_AM_APP_NOT_A_MIDDLEWARE
|
19
|
+
end
|
20
|
+
|
21
|
+
def middleware_path
|
22
|
+
[]
|
23
|
+
end
|
13
24
|
end
|
14
25
|
end
|
data/lib/ovto/app.rb
CHANGED
@@ -1,18 +1,37 @@
|
|
1
1
|
module Ovto
|
2
2
|
class App
|
3
|
+
# List of installed middleware classes
|
4
|
+
def self.middlewares
|
5
|
+
@middlewares ||= []
|
6
|
+
end
|
7
|
+
|
3
8
|
# Create an App and start it
|
4
9
|
def self.run(*args)
|
5
10
|
new.run(*args)
|
6
11
|
end
|
7
12
|
|
13
|
+
# Install a middleware
|
14
|
+
def self.use(middleware_class)
|
15
|
+
self.middlewares.push(middleware_class)
|
16
|
+
end
|
17
|
+
|
8
18
|
def initialize
|
9
|
-
|
10
|
-
|
19
|
+
app_state_class = self.class.const_get('State')
|
20
|
+
# Inject middleware states
|
21
|
+
app_state_class.item :_middlewares, default_proc: ->{
|
22
|
+
Ovto::Middleware.create_middleware_states_class(self.class.middlewares).new
|
23
|
+
}
|
24
|
+
@state = app_state_class.new
|
25
|
+
@wired_action_set = nil
|
26
|
+
@main_component = nil
|
11
27
|
end
|
12
28
|
attr_reader :state
|
13
29
|
|
30
|
+
# An instance of YourApp::MainComponent (mainly for testing)
|
31
|
+
attr_reader :main_component
|
32
|
+
|
14
33
|
def actions
|
15
|
-
@
|
34
|
+
@wired_action_set.app_wired_actions
|
16
35
|
end
|
17
36
|
|
18
37
|
# Internal use only
|
@@ -36,9 +55,9 @@ module Ovto
|
|
36
55
|
def _run(id: nil)
|
37
56
|
runtime = Ovto::Runtime.new(self)
|
38
57
|
actions = self.class.const_get('Actions').new
|
39
|
-
@
|
40
|
-
actions.wired_actions = @
|
41
|
-
|
58
|
+
@wired_action_set = WiredActionSet.new(self, actions, [], self.class.middlewares, runtime)
|
59
|
+
actions.wired_actions = @wired_action_set.app_wired_actions
|
60
|
+
@main_component = create_view(@wired_action_set)
|
42
61
|
if id
|
43
62
|
%x{
|
44
63
|
document.addEventListener('DOMContentLoaded', function(){
|
@@ -46,16 +65,16 @@ module Ovto
|
|
46
65
|
if (!container) {
|
47
66
|
throw "Ovto::App#run: tag with id='" + id + "' was not found";
|
48
67
|
}
|
49
|
-
#{start_application(runtime,
|
68
|
+
#{start_application(runtime, `container`)}
|
50
69
|
});
|
51
70
|
}
|
52
71
|
else
|
53
|
-
start_application(runtime,
|
72
|
+
start_application(runtime, nil)
|
54
73
|
end
|
55
74
|
end
|
56
75
|
|
57
76
|
# Instantiate MyApp::MainComponent
|
58
|
-
def create_view
|
77
|
+
def create_view(wired_action_set)
|
59
78
|
begin
|
60
79
|
main_component_class = self.class.const_get('MainComponent')
|
61
80
|
rescue NameError => orig_ex
|
@@ -68,12 +87,17 @@ module Ovto
|
|
68
87
|
"#{self.class}::View to #{self.class}::MainComponent"
|
69
88
|
end
|
70
89
|
end
|
71
|
-
return main_component_class.new(
|
90
|
+
return main_component_class.new(wired_action_set)
|
72
91
|
end
|
73
92
|
|
74
|
-
def start_application(runtime,
|
75
|
-
|
76
|
-
|
93
|
+
def start_application(runtime, container)
|
94
|
+
Ovto.log_error {
|
95
|
+
runtime.run(@main_component, container)
|
96
|
+
setup
|
97
|
+
self.class.middlewares.each do |m|
|
98
|
+
m._run_setup(@wired_action_set[m.name])
|
99
|
+
end
|
100
|
+
}
|
77
101
|
end
|
78
102
|
end
|
79
103
|
end
|
data/lib/ovto/component.rb
CHANGED
@@ -13,10 +13,16 @@ module Ovto
|
|
13
13
|
ret
|
14
14
|
end
|
15
15
|
|
16
|
-
|
17
|
-
|
16
|
+
# (internal) Defined for convenience
|
17
|
+
def self.middleware_name
|
18
|
+
WiredActionSet::I_AM_APP_NOT_A_MIDDLEWARE
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize(wired_action_set, middleware_path=[])
|
22
|
+
@wired_action_set = wired_action_set || WiredActionSet.dummy
|
23
|
+
@middleware_path = middleware_path
|
18
24
|
# Initialize here for the unit tests
|
19
|
-
@
|
25
|
+
@vdom_stack = [[]]
|
20
26
|
@components = []
|
21
27
|
@components_index = 0
|
22
28
|
end
|
@@ -26,7 +32,7 @@ module Ovto
|
|
26
32
|
end
|
27
33
|
|
28
34
|
def state
|
29
|
-
@
|
35
|
+
@wired_action_set.app.state
|
30
36
|
end
|
31
37
|
|
32
38
|
private
|
@@ -37,35 +43,35 @@ module Ovto
|
|
37
43
|
do_render({}, state)
|
38
44
|
end
|
39
45
|
|
40
|
-
|
46
|
+
# Call #render to generate VDom
|
47
|
+
def do_render(args, state, &block)
|
41
48
|
Ovto.debug_trace_log("rendering #{self}")
|
42
|
-
@
|
49
|
+
@vdom_stack = [[]]
|
43
50
|
@components_index = 0
|
44
51
|
@done_render = false
|
45
52
|
@current_state = state
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
53
|
+
rendered = Ovto.log_error {
|
54
|
+
Ovto.send_args_with_state(self, :render, args, state, &block)
|
55
|
+
}
|
56
|
+
case rendered
|
57
|
+
when String
|
58
|
+
return rendered
|
59
|
+
when Array
|
60
|
+
if rendered.length > 1
|
61
|
+
raise MoreThanOneNode
|
62
|
+
end
|
63
|
+
raise "rendered is empty" if rendered.length == 0
|
64
|
+
return rendered[0]
|
51
65
|
else
|
52
|
-
#
|
53
|
-
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
# Return true if the method accepts `state:` keyword
|
58
|
-
def accepts_state?(parameters)
|
59
|
-
parameters.each do |item|
|
60
|
-
return true if item == [:key, :state] ||
|
61
|
-
item == [:keyreq, :state] ||
|
62
|
-
item[0] == :keyrest
|
66
|
+
console.error("#render returned unknown value", rendered)
|
67
|
+
raise "#render returned unknown value"
|
63
68
|
end
|
64
|
-
return false
|
65
69
|
end
|
66
70
|
|
67
71
|
def actions
|
68
|
-
@
|
72
|
+
return @middleware_path.inject(@wired_action_set){|wa_set, middleware_name|
|
73
|
+
wa_set[middleware_name]
|
74
|
+
}[WiredActionSet::THE_MIDDLEWARE_ITSELF]
|
69
75
|
end
|
70
76
|
|
71
77
|
# o 'div', 'Hello.'
|
@@ -78,31 +84,39 @@ module Ovto
|
|
78
84
|
# o 'h1', 'Hello.'
|
79
85
|
# end
|
80
86
|
# o 'div', `{nodeName: ....}` # Inject VDom spec directly
|
87
|
+
# o SubComponentClass
|
88
|
+
# o SubComponentClass do ... end # Ovto passes the block to SubComponent#render
|
81
89
|
def o(_tag_name, arg1=nil, arg2=nil, &block)
|
82
|
-
if native?(arg1)
|
90
|
+
if native?(arg1) # Embed VDom directly
|
83
91
|
attributes = {}
|
84
92
|
content = arg1
|
85
|
-
elsif arg1.is_a?(Hash)
|
93
|
+
elsif arg1.is_a?(Hash) # Has attributes
|
86
94
|
attributes = arg1
|
87
95
|
content = arg2
|
88
|
-
elsif arg2 == nil
|
96
|
+
elsif arg2 == nil # Has content instead of attributes, or both are nil
|
89
97
|
attributes = {}
|
90
98
|
content = arg1
|
91
99
|
else
|
92
100
|
raise ArgumentError
|
93
101
|
end
|
94
102
|
|
95
|
-
children = render_children(content, block)
|
96
103
|
case _tag_name
|
97
104
|
when Class
|
98
|
-
|
105
|
+
if content
|
106
|
+
raise ArgumentError, "use a block to pass content to sub component"
|
107
|
+
end
|
108
|
+
result = render_component(_tag_name, attributes, &block)
|
99
109
|
when 'text'
|
100
110
|
unless attributes.empty?
|
101
111
|
raise ArgumentError, "text cannot take attributes"
|
102
112
|
end
|
103
113
|
result = content
|
104
114
|
when String
|
115
|
+
children = render_children(content, block)
|
105
116
|
tag_name, base_attributes = *extract_attrs(_tag_name)
|
117
|
+
if tag_name == "textarea" && (content || block)
|
118
|
+
raise ArgumentError, "Use `value:` to specify content of a textarea"
|
119
|
+
end
|
106
120
|
# Ignore nil/false
|
107
121
|
more_attributes = attributes.reject{|k, v| !v}
|
108
122
|
result = render_tag(tag_name, merge_attrs(base_attributes, more_attributes), children)
|
@@ -110,16 +124,8 @@ module Ovto
|
|
110
124
|
raise TypeError, "tag_name must be a String or Component but got "+
|
111
125
|
Ovto.inspect(tag_name)
|
112
126
|
end
|
113
|
-
|
114
|
-
|
115
|
-
raise MoreThanOneNode, "#{self.class}#render must generate a single DOM node. Please wrap the tags with a 'div' or something."
|
116
|
-
end
|
117
|
-
@done_render = true
|
118
|
-
return result
|
119
|
-
else
|
120
|
-
@vdom_tree.last.push(result)
|
121
|
-
return @vdom_tree.last
|
122
|
-
end
|
127
|
+
@vdom_stack.last.push(result)
|
128
|
+
return @vdom_stack.last
|
123
129
|
end
|
124
130
|
|
125
131
|
def extract_attrs(tag_name)
|
@@ -164,37 +170,52 @@ module Ovto
|
|
164
170
|
[content.to_s]
|
165
171
|
end
|
166
172
|
when block
|
167
|
-
|
168
|
-
block_value = block.call
|
169
|
-
results = @vdom_tree.pop
|
170
|
-
if results.length > 0 # 'o' was called at least once
|
171
|
-
results
|
172
|
-
elsif native?(block_value)
|
173
|
-
# Inject VDom tree written in JS object
|
174
|
-
# eg. Embed markdown
|
175
|
-
[block_value]
|
176
|
-
elsif block_value.is_a?(String)
|
177
|
-
# When 'o' is never called in the child block, use the last value
|
178
|
-
# eg.
|
179
|
-
# o 'span' do
|
180
|
-
# 'Hello' #=> This will be the content of the span tag
|
181
|
-
# end
|
182
|
-
[block_value]
|
183
|
-
else
|
184
|
-
# o 'div' do
|
185
|
-
# # When items is `[]`, 'o' is never called and `block_value` will be `[]`
|
186
|
-
# items.each{ o 'div', '...' }
|
187
|
-
# end
|
188
|
-
[]
|
189
|
-
end
|
173
|
+
render_block(block)
|
190
174
|
else
|
191
175
|
[]
|
192
176
|
end
|
193
177
|
end
|
194
178
|
|
195
|
-
def
|
179
|
+
def render_block(block)
|
180
|
+
@vdom_stack.push []
|
181
|
+
orig_depth = @vdom_stack.length
|
182
|
+
block_value = block.call
|
183
|
+
@vdom_stack = @vdom_stack.first(orig_depth)
|
184
|
+
results = @vdom_stack.pop
|
185
|
+
|
186
|
+
if results.length > 0 # 'o' was called at least once
|
187
|
+
results
|
188
|
+
elsif native?(block_value)
|
189
|
+
# Inject VDom tree written in JS object
|
190
|
+
# eg. Embed markdown
|
191
|
+
[block_value]
|
192
|
+
elsif block_value.is_a?(String)
|
193
|
+
# When 'o' is never called in the child block, use the last value
|
194
|
+
# eg.
|
195
|
+
# o 'span' do
|
196
|
+
# 'Hello' #=> This will be the content of the span tag
|
197
|
+
# end
|
198
|
+
[block_value]
|
199
|
+
elsif block_value.is_a?(Array)
|
200
|
+
# Case 1
|
201
|
+
# o "div", &block
|
202
|
+
# Case 2
|
203
|
+
# items = []
|
204
|
+
# o 'div' do items.each{ o ... } end # == o 'div' do [] end
|
205
|
+
block_value
|
206
|
+
else
|
207
|
+
console.error("Invalid block_value:", Ovto.inspect(block_value))
|
208
|
+
raise "Invalid block value"
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
# Instantiate component and call its #render to get VDom
|
213
|
+
def render_component(comp_class, args, &block)
|
196
214
|
comp = new_component(comp_class)
|
197
|
-
|
215
|
+
orig_stack, @vdom_stack = @vdom_stack, [[]]
|
216
|
+
ret = comp.do_render(args, @current_state, &block)
|
217
|
+
@vdom_stack = orig_stack
|
218
|
+
ret
|
198
219
|
end
|
199
220
|
|
200
221
|
def new_component(comp_class)
|
@@ -204,14 +225,56 @@ module Ovto
|
|
204
225
|
return comp
|
205
226
|
end
|
206
227
|
|
207
|
-
|
228
|
+
middleware_path = new_middleware_path(comp_class)
|
229
|
+
comp = @components[@components_index] = comp_class.new(@wired_action_set, middleware_path)
|
208
230
|
@components_index += 1
|
209
231
|
comp
|
210
232
|
end
|
211
233
|
|
234
|
+
# Make new middleware_path by adding comp_class
|
235
|
+
def new_middleware_path(comp_class)
|
236
|
+
mw_name = comp_class.middleware_name
|
237
|
+
if (idx = @middleware_path.index(mw_name))
|
238
|
+
# eg. suppose OvtoIde uses OvtoWindow
|
239
|
+
# class CompI < OvtoIde::Component
|
240
|
+
# def render
|
241
|
+
# o Window do
|
242
|
+
# o AnotherComponentOfOvtoIde
|
243
|
+
# end
|
244
|
+
# end
|
245
|
+
# end
|
246
|
+
# class Window < OvtoWindow::Component
|
247
|
+
# def render(&block)
|
248
|
+
# o ".window", &block
|
249
|
+
# end
|
250
|
+
# end
|
251
|
+
# Rendering order:
|
252
|
+
# 1. CompI (ovto_ide)
|
253
|
+
# 2. Window (ovto_window)
|
254
|
+
# 3. AnotherComponentOfOvtoIde (ovto_ide again)
|
255
|
+
@middleware_path[0..idx]
|
256
|
+
else
|
257
|
+
if comp_class.middleware_name == WiredActionSet::I_AM_APP_NOT_A_MIDDLEWARE
|
258
|
+
@middleware_path
|
259
|
+
else
|
260
|
+
@middleware_path + [comp_class.middleware_name]
|
261
|
+
end
|
262
|
+
end
|
263
|
+
# TODO: it would be nice if we could raise an error when comp_class
|
264
|
+
# is invalid middleware (i.e. not use'd)
|
265
|
+
end
|
266
|
+
|
212
267
|
def render_tag(tag_name, attributes, children)
|
213
|
-
|
214
|
-
|
268
|
+
attributes_ = attributes.map{|k, v|
|
269
|
+
if k.start_with?("on")
|
270
|
+
# Inject log_error to event handlers
|
271
|
+
[k, ->(e){ Ovto.log_error{ v.call(e) }}]
|
272
|
+
else
|
273
|
+
[k, v]
|
274
|
+
end
|
275
|
+
}.to_h
|
276
|
+
js_attributes = Component.hash_to_js_obj(attributes_ || {})
|
277
|
+
if (style = attributes_['style'])
|
215
278
|
`js_attributes.style = #{Component.hash_to_js_obj(style)}`
|
216
279
|
end
|
217
280
|
children ||= `null`
|