ovto 0.3.0 → 0.4.0
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 +0 -3
- data/CHANGELOG.md +15 -0
- data/Gemfile.lock +13 -9
- data/README.md +3 -3
- data/Rakefile +2 -2
- data/book/api/actions.md +5 -5
- data/book/api/app.md +3 -3
- data/book/api/component.md +4 -6
- data/book/guides/tutorial.md +8 -8
- data/examples/sinatra/Gemfile.lock +3 -1
- data/examples/sinatra/ovto/app.rb +8 -8
- data/examples/static/Gemfile +1 -0
- data/examples/static/Gemfile.lock +5 -1
- data/examples/static/Rakefile +5 -0
- data/examples/static/app.rb +3 -3
- data/exe/ovto +59 -0
- data/index.html +0 -9
- data/lib/ovto/actions.rb +4 -0
- data/lib/ovto/component.rb +21 -3
- data/lib/ovto/runtime.rb +4 -57
- data/lib/ovto/version.rb +1 -1
- data/lib/ovto/wired_actions.rb +22 -2
- data/ovto.gemspec +1 -0
- metadata +20 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c16fab45131f98235cddc5a78d0128105dea5d60d4b5a2849980af71b21d40bf
|
4
|
+
data.tar.gz: cec1207210d7f94f3791655c0ed2bed8f7d91d0f579997c913a8e95b2afae438
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b142cc06e37df28acfee9f94ad9cb1ce46e2a565878f0078afb584f793e7365bb383c39f4aa38d7406b4681daab7499ce433d14984a5ab27f5417d286563757b
|
7
|
+
data.tar.gz: ef7c8e4d03dfedf31d4052b5c758d33e307f8211b5ef42e648267d1c1c502119dae4b2e0bfa4fc58e83152775e3ff76c6f1811fe3ed628eba4a6a42c7664736b
|
data/.gitmodules
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
## HEAD
|
2
|
+
|
3
|
+
## v0.4.0 (2019-04-19)
|
4
|
+
|
5
|
+
New features
|
6
|
+
|
7
|
+
- `ovto new` command
|
8
|
+
- You can now omit `state:` in `render` method or actions
|
9
|
+
- Support embedding VDom directly (eg. which is compiled form markdown)
|
10
|
+
|
11
|
+
Example:
|
12
|
+
|
13
|
+
o 'div', `{nodeName: ....}`
|
14
|
+
|
15
|
+
|
1
16
|
## v0.3.0 (2018-12-24)
|
2
17
|
|
3
18
|
Breaking change
|
data/Gemfile.lock
CHANGED
@@ -1,36 +1,40 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
ovto (0.
|
4
|
+
ovto (0.4.0)
|
5
5
|
opal (~> 0.11)
|
6
|
+
thor (~> 0.20)
|
6
7
|
|
7
8
|
GEM
|
8
9
|
remote: https://rubygems.org/
|
9
10
|
specs:
|
10
11
|
ast (2.4.0)
|
11
|
-
concurrent-ruby (1.1.
|
12
|
+
concurrent-ruby (1.1.5)
|
12
13
|
hike (1.2.3)
|
13
14
|
opal (0.11.4)
|
14
15
|
ast (>= 2.3.0)
|
15
16
|
hike (~> 1.2)
|
16
17
|
parser (= 2.3.3.1)
|
17
18
|
sourcemap (~> 0.1.0)
|
18
|
-
opal-rspec (0.
|
19
|
-
opal (>= 0.
|
20
|
-
|
19
|
+
opal-rspec (0.7.1)
|
20
|
+
opal (>= 0.11, < 0.12)
|
21
|
+
opal-sprockets
|
22
|
+
rake (~> 12.0)
|
23
|
+
opal-sprockets (0.4.3.0.11.0.3.7)
|
21
24
|
opal (~> 0.11.0)
|
22
|
-
sprockets (~> 3.
|
25
|
+
sprockets (~> 3.7)
|
23
26
|
tilt (>= 1.4)
|
24
27
|
parser (2.3.3.1)
|
25
28
|
ast (~> 2.2)
|
26
|
-
rack (2.0.
|
29
|
+
rack (2.0.7)
|
27
30
|
rake (12.3.2)
|
28
31
|
sourcemap (0.1.1)
|
29
32
|
sprockets (3.7.2)
|
30
33
|
concurrent-ruby (~> 1.0)
|
31
34
|
rack (> 1, < 3)
|
35
|
+
thor (0.20.3)
|
32
36
|
tilt (2.0.9)
|
33
|
-
yard (0.9.
|
37
|
+
yard (0.9.19)
|
34
38
|
|
35
39
|
PLATFORMS
|
36
40
|
ruby
|
@@ -44,4 +48,4 @@ DEPENDENCIES
|
|
44
48
|
yard
|
45
49
|
|
46
50
|
BUNDLED WITH
|
47
|
-
|
51
|
+
2.0.1
|
data/README.md
CHANGED
@@ -26,18 +26,18 @@ class MyApp < Ovto::App
|
|
26
26
|
end
|
27
27
|
|
28
28
|
class Actions < Ovto::Actions
|
29
|
-
def set_celsius(
|
29
|
+
def set_celsius(value:)
|
30
30
|
return {celsius: value}
|
31
31
|
end
|
32
32
|
|
33
|
-
def set_fahrenheit(
|
33
|
+
def set_fahrenheit(value:)
|
34
34
|
new_celsius = (value - 32) * 5 / 9.0
|
35
35
|
return {celsius: new_celsius}
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
39
|
class MainComponent < Ovto::Component
|
40
|
-
def render
|
40
|
+
def render
|
41
41
|
o 'div' do
|
42
42
|
o 'span', 'Celcius:'
|
43
43
|
o 'input', {
|
data/Rakefile
CHANGED
@@ -29,15 +29,15 @@ task :release do
|
|
29
29
|
cd('examples/sinatra'){ sh 'bundle update' }
|
30
30
|
cd('examples/static'){ sh 'bundle update' }
|
31
31
|
load 'lib/ovto/version.rb'
|
32
|
-
sh "git diff"
|
32
|
+
sh "git diff HEAD"
|
33
33
|
v = "v#{Ovto::VERSION}"
|
34
34
|
puts "release as #{v}? [y/N]"
|
35
35
|
break unless $stdin.gets.chomp == "y"
|
36
36
|
|
37
|
+
sh "gem build ovto" # First, make sure we can build gem
|
37
38
|
sh "bundle exec rake docs:build"
|
38
39
|
sh "git ci -am '#{v}'"
|
39
40
|
sh "git tag '#{v}'"
|
40
41
|
sh "git push origin master --tags"
|
41
|
-
sh "gem build ovto"
|
42
42
|
sh "gem push ovto-#{Ovto::VERSION}.gem"
|
43
43
|
end
|
data/book/api/actions.md
CHANGED
@@ -4,8 +4,8 @@ Actions are the only way to change the state. Actions must be defined as methods
|
|
4
4
|
the `Actions` class. Here is some more conventions:
|
5
5
|
|
6
6
|
- You must use keyword arguments
|
7
|
-
- You must provide `state:` keyword to receive the app state
|
8
7
|
- You must return state updates as a Hash. It will be merged into the app state.
|
8
|
+
- You can get the current state by `state` method
|
9
9
|
|
10
10
|
Example:
|
11
11
|
|
@@ -19,13 +19,13 @@ class MyApp < Ovto::App
|
|
19
19
|
end
|
20
20
|
|
21
21
|
class Actions < Ovto::Actions
|
22
|
-
def increment(
|
22
|
+
def increment(by:)
|
23
23
|
return {count: state.count + by}
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
27
|
class MainComponent < Ovto::Component
|
28
|
-
def render
|
28
|
+
def render
|
29
29
|
o 'span', state.count
|
30
30
|
o 'button', onclick: ->{ actions.increment(by: 1) }
|
31
31
|
end
|
@@ -61,7 +61,7 @@ Example:
|
|
61
61
|
|
62
62
|
```rb
|
63
63
|
class Actions < Ovto::Actions
|
64
|
-
def fetch_tasks
|
64
|
+
def fetch_tasks
|
65
65
|
Ovto.fetch('/tasks.json').then {|tasks_json|
|
66
66
|
actions.receive_tasks(tasks: tasks_json)
|
67
67
|
}.fail {|e|
|
@@ -69,7 +69,7 @@ Example:
|
|
69
69
|
}
|
70
70
|
end
|
71
71
|
|
72
|
-
def receive_tasks(
|
72
|
+
def receive_tasks(tasks_json:)
|
73
73
|
tasks = tasks_json.map{|item| Task.new(**item)}
|
74
74
|
return {tasks: tasks}
|
75
75
|
end
|
data/book/api/app.md
CHANGED
@@ -19,7 +19,7 @@ class MyApp < Ovto::App
|
|
19
19
|
end
|
20
20
|
|
21
21
|
class MainComponent < Ovto::Component
|
22
|
-
def render
|
22
|
+
def render
|
23
23
|
o 'input', type: 'button', value: 'Hello'
|
24
24
|
end
|
25
25
|
end
|
@@ -42,14 +42,14 @@ class MyApp < Ovto::App
|
|
42
42
|
end
|
43
43
|
|
44
44
|
class Actions < Ovto::Actions
|
45
|
-
def update_color
|
45
|
+
def update_color
|
46
46
|
new_idx = (state.color_idx + 1) % COLORS.length
|
47
47
|
return {color_idx: new_idx}
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
51
|
class MainComponent < Ovto::Component
|
52
|
-
def render
|
52
|
+
def render
|
53
53
|
o 'input', {
|
54
54
|
type: 'button',
|
55
55
|
value: 'Hello',
|
data/book/api/component.md
CHANGED
@@ -5,11 +5,11 @@ An Ovto app must have `MainComponent` class, a subclass of `Ovto::Component`.
|
|
5
5
|
## 'render' method
|
6
6
|
|
7
7
|
`render` is the only method you need to define in the `MainComponent` class.
|
8
|
-
|
8
|
+
You can get the global app state by calling `state` method.
|
9
9
|
|
10
10
|
```rb
|
11
11
|
class MainComponent < Ovto::Component
|
12
|
-
def render
|
12
|
+
def render
|
13
13
|
o 'div' do
|
14
14
|
o 'h1', 'Your todos'
|
15
15
|
o 'ul' do
|
@@ -27,7 +27,7 @@ It must take the global app state as a keyword argument `state:`.
|
|
27
27
|
If you missed the surrounding 'div' tag, Ovto raises an `MoreThanOneNode` error. `render` must create a single DOM node.
|
28
28
|
|
29
29
|
```rb
|
30
|
-
def render
|
30
|
+
def render
|
31
31
|
o 'h1', 'Your todos'
|
32
32
|
o 'ul' do
|
33
33
|
state.todos.each do |todo|
|
@@ -141,7 +141,7 @@ https://github.com/hyperapp/hyperapp#keys
|
|
141
141
|
|
142
142
|
# Main component
|
143
143
|
class MainComponent < Ovto::Component
|
144
|
-
def render
|
144
|
+
def render
|
145
145
|
o 'div' do
|
146
146
|
o 'h1', 'Your todos'
|
147
147
|
o TodoList, todos: state.todos
|
@@ -150,8 +150,6 @@ https://github.com/hyperapp/hyperapp#keys
|
|
150
150
|
end
|
151
151
|
```
|
152
152
|
|
153
|
-
For sub components, the `state:` keyword of `render` method is optional.
|
154
|
-
|
155
153
|
## Text node
|
156
154
|
|
157
155
|
Sometimes you may want to create a text node.
|
data/book/guides/tutorial.md
CHANGED
@@ -18,18 +18,18 @@ class MyApp < Ovto::App
|
|
18
18
|
end
|
19
19
|
|
20
20
|
class Actions < Ovto::Actions
|
21
|
-
def set_celsius(
|
21
|
+
def set_celsius(value:)
|
22
22
|
return {celsius: value}
|
23
23
|
end
|
24
24
|
|
25
|
-
def set_fahrenheit(
|
25
|
+
def set_fahrenheit(value:)
|
26
26
|
new_celsius = (value - 32) * 5 / 9.0
|
27
27
|
return {celsius: new_celsius}
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
31
|
class MainComponent < Ovto::Component
|
32
|
-
def render
|
32
|
+
def render
|
33
33
|
o 'div' do
|
34
34
|
o 'span', 'Celcius:'
|
35
35
|
o 'input', {
|
@@ -103,7 +103,7 @@ class MyApp < Ovto::App
|
|
103
103
|
end
|
104
104
|
|
105
105
|
class MainComponent < Ovto::Component
|
106
|
-
def render
|
106
|
+
def render # Don't miss the `:`. This is not a typo but
|
107
107
|
o 'div' do # a "mandatory keyword argument".
|
108
108
|
o 'h1', "HELLO" # All of the Ovto methods take keyword arguments.
|
109
109
|
end
|
@@ -169,7 +169,7 @@ value with `MyApp::MainComponent`.
|
|
169
169
|
|
170
170
|
```rb
|
171
171
|
class MainComponent < Ovto::Component
|
172
|
-
def render
|
172
|
+
def render
|
173
173
|
o 'div' do
|
174
174
|
o 'span', 'Celcius:'
|
175
175
|
o 'input', type: 'text', value: state.celsius
|
@@ -199,7 +199,7 @@ Now you can know the value by `state.fahrenheit`. Update `MainComponent` to show
|
|
199
199
|
|
200
200
|
```
|
201
201
|
class MainComponent < Ovto::Component
|
202
|
-
def render
|
202
|
+
def render
|
203
203
|
o 'div' do
|
204
204
|
o 'span', 'Celcius:'
|
205
205
|
o 'input', type: 'text', value: state.celsius
|
@@ -224,7 +224,7 @@ the updates to the state. This return value is `merge`d into the global app stat
|
|
224
224
|
|
225
225
|
```rb
|
226
226
|
class Actions < Ovto::Actions
|
227
|
-
def set_celsius(
|
227
|
+
def set_celsius(value:)
|
228
228
|
return {celsius: value}
|
229
229
|
end
|
230
230
|
end
|
@@ -279,7 +279,7 @@ Then add an action `set_fahrenheit` to `MyApp::Actions`. This action convers the
|
|
279
279
|
Fahrenheit degree into Celsius and set it to the global state.
|
280
280
|
|
281
281
|
```rb
|
282
|
-
def set_fahrenheit(
|
282
|
+
def set_fahrenheit(value:)
|
283
283
|
new_celsius = (value - 32) * 5 / 9.0
|
284
284
|
return {celsius: new_celsius}
|
285
285
|
end
|
@@ -3,6 +3,7 @@ PATH
|
|
3
3
|
specs:
|
4
4
|
ovto (0.3.0)
|
5
5
|
opal (~> 0.11)
|
6
|
+
thor (~> 0.20)
|
6
7
|
|
7
8
|
GEM
|
8
9
|
remote: https://rubygems.org/
|
@@ -43,6 +44,7 @@ GEM
|
|
43
44
|
sprockets (3.7.2)
|
44
45
|
concurrent-ruby (~> 1.0)
|
45
46
|
rack (> 1, < 3)
|
47
|
+
thor (0.20.3)
|
46
48
|
tilt (2.0.9)
|
47
49
|
|
48
50
|
PLATFORMS
|
@@ -56,4 +58,4 @@ DEPENDENCIES
|
|
56
58
|
sinatra-contrib
|
57
59
|
|
58
60
|
BUNDLED WITH
|
59
|
-
|
61
|
+
2.0.1
|
@@ -27,7 +27,7 @@ class TodoApp < Ovto::App
|
|
27
27
|
end
|
28
28
|
|
29
29
|
class Actions < Ovto::Actions
|
30
|
-
def add_todo
|
30
|
+
def add_todo
|
31
31
|
new_todo = Todo.new(
|
32
32
|
id: state.todos.length + 1,
|
33
33
|
value: state.input,
|
@@ -39,15 +39,15 @@ class TodoApp < Ovto::App
|
|
39
39
|
}
|
40
40
|
end
|
41
41
|
|
42
|
-
def destroy_todo(
|
42
|
+
def destroy_todo(id:)
|
43
43
|
return {todos: state.todos.reject{|t| t.id == id}}
|
44
44
|
end
|
45
45
|
|
46
|
-
def destroy_completed_todos
|
46
|
+
def destroy_completed_todos
|
47
47
|
return {todos: state.todos.reject(&:done)}
|
48
48
|
end
|
49
49
|
|
50
|
-
def toggle_todo(
|
50
|
+
def toggle_todo(id:)
|
51
51
|
new_todos = state.todos.map{|t|
|
52
52
|
if t.id == id
|
53
53
|
t.merge(done: !t.done)
|
@@ -58,15 +58,15 @@ class TodoApp < Ovto::App
|
|
58
58
|
return {todos: new_todos}
|
59
59
|
end
|
60
60
|
|
61
|
-
def toggle_all(
|
61
|
+
def toggle_all(done:)
|
62
62
|
return {todos: state.todos.map{|t| t.merge(done: done)}}
|
63
63
|
end
|
64
64
|
|
65
|
-
def set_input(
|
65
|
+
def set_input(value:)
|
66
66
|
return {input: value}
|
67
67
|
end
|
68
68
|
|
69
|
-
def set_filter(
|
69
|
+
def set_filter(filter:)
|
70
70
|
return {filter: filter}
|
71
71
|
end
|
72
72
|
end
|
@@ -153,7 +153,7 @@ class TodoApp < Ovto::App
|
|
153
153
|
end
|
154
154
|
|
155
155
|
class MainComponent < Ovto::Component
|
156
|
-
def render
|
156
|
+
def render
|
157
157
|
o 'section.todoapp' do
|
158
158
|
o Header,
|
159
159
|
input: state.input
|
data/examples/static/Gemfile
CHANGED
@@ -3,12 +3,14 @@ PATH
|
|
3
3
|
specs:
|
4
4
|
ovto (0.3.0)
|
5
5
|
opal (~> 0.11)
|
6
|
+
thor (~> 0.20)
|
6
7
|
|
7
8
|
GEM
|
8
9
|
remote: https://rubygems.org/
|
9
10
|
specs:
|
10
11
|
ast (2.4.0)
|
11
12
|
hike (1.2.3)
|
13
|
+
ifchanged (1.0.1)
|
12
14
|
opal (0.11.4)
|
13
15
|
ast (>= 2.3.0)
|
14
16
|
hike (~> 1.2)
|
@@ -18,13 +20,15 @@ GEM
|
|
18
20
|
ast (~> 2.2)
|
19
21
|
rake (12.3.2)
|
20
22
|
sourcemap (0.1.1)
|
23
|
+
thor (0.20.3)
|
21
24
|
|
22
25
|
PLATFORMS
|
23
26
|
ruby
|
24
27
|
|
25
28
|
DEPENDENCIES
|
29
|
+
ifchanged
|
26
30
|
ovto!
|
27
31
|
rake
|
28
32
|
|
29
33
|
BUNDLED WITH
|
30
|
-
|
34
|
+
2.0.1
|
data/examples/static/Rakefile
CHANGED
data/examples/static/app.rb
CHANGED
@@ -10,18 +10,18 @@ class MyApp < Ovto::App
|
|
10
10
|
end
|
11
11
|
|
12
12
|
class Actions < Ovto::Actions
|
13
|
-
def set_celsius(
|
13
|
+
def set_celsius(value:)
|
14
14
|
return {celsius: value}
|
15
15
|
end
|
16
16
|
|
17
|
-
def set_fahrenheit(
|
17
|
+
def set_fahrenheit(value:)
|
18
18
|
new_celsius = (value - 32) * 5 / 9.0
|
19
19
|
return {celsius: new_celsius}
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
23
|
class MainComponent < Ovto::Component
|
24
|
-
def render
|
24
|
+
def render
|
25
25
|
o 'div' do
|
26
26
|
o 'span', 'Celcius:'
|
27
27
|
o 'input', {
|
data/exe/ovto
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'fileutils'
|
3
|
+
require 'rack'
|
4
|
+
require 'thor'
|
5
|
+
require_relative '../lib/ovto/version'
|
6
|
+
|
7
|
+
module Ovto
|
8
|
+
class Cli < Thor
|
9
|
+
GEM_ROOT = "#{__dir__}/../"
|
10
|
+
|
11
|
+
APP_TYPES = %w(static sinatra)
|
12
|
+
desc "new APP_PATH", "Create an Ovto project (--type=any of #{APP_TYPES.inspect})"
|
13
|
+
option "type", type: :string, required: true
|
14
|
+
def new(app_path)
|
15
|
+
if File.exist?(app_path)
|
16
|
+
puts "Already exists: #{app_path}"
|
17
|
+
return
|
18
|
+
end
|
19
|
+
unless APP_TYPES.include?(options[:type])
|
20
|
+
puts "--type must be any of #{APP_TYPES.inspect}"
|
21
|
+
return
|
22
|
+
end
|
23
|
+
FileUtils.mkdir_p(app_path)
|
24
|
+
Dir.chdir(app_path) do
|
25
|
+
Dir["#{GEM_ROOT}/examples/#{options[:type]}/*"].each do |src_path|
|
26
|
+
FileUtils.cp_r(src_path, ".")
|
27
|
+
end
|
28
|
+
# Remove `path:` from the Gemfile
|
29
|
+
File.write("Gemfile", File.read('Gemfile').gsub(", path: '../../'", ""))
|
30
|
+
sh "bundle install"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
desc "server", "Start local server"
|
35
|
+
option "port", aliases: :p, type: :numeric, default: 7521
|
36
|
+
def server
|
37
|
+
puts "Starting Ovto Server"
|
38
|
+
puts "(Open http://localhost:#{options[:port]}/index.html in the browser)"
|
39
|
+
puts "---"
|
40
|
+
if File.file?("config.ru")
|
41
|
+
sh "bundle exec rackup -p #{options[:port]}"
|
42
|
+
else
|
43
|
+
app = Rack::Directory.new(Dir.pwd)
|
44
|
+
Rack::Server.start(app: app, Port: options[:port])
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def sh(*cmd)
|
51
|
+
puts cmd.join(' ')
|
52
|
+
system *cmd
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
puts "Ovto v#{Ovto::VERSION}"
|
58
|
+
Ovto::Cli.start
|
59
|
+
|
data/index.html
CHANGED
@@ -3,15 +3,6 @@
|
|
3
3
|
<head>
|
4
4
|
<meta charset="utf-8" />
|
5
5
|
<title>Ovto - Front-end framework for Rubyist</title>
|
6
|
-
|
7
|
-
<script src="http://cdnjs.cloudflare.com/ajax/libs/zepto/1.0rc1/zepto.min.js" type="text/javascript"></script>
|
8
|
-
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script>
|
9
|
-
|
10
|
-
<script type="text/javascript" charset="utf-8">
|
11
|
-
// this must be set absolutely before any other script on the app is loaded for IE7
|
12
|
-
document.domain = 'twitter.com';
|
13
|
-
</script>
|
14
|
-
|
15
6
|
<link href="https://fonts.googleapis.com/css?family=Rubik" rel="stylesheet">
|
16
7
|
<link rel="stylesheet" href="website/screen.css" type="text/css" media="screen" />
|
17
8
|
</head>
|
data/lib/ovto/actions.rb
CHANGED
data/lib/ovto/component.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'native'
|
2
|
+
|
1
3
|
module Ovto
|
2
4
|
class Component
|
3
5
|
# `render` tried to yield multiple nodes
|
@@ -21,16 +23,20 @@ module Ovto
|
|
21
23
|
''
|
22
24
|
end
|
23
25
|
|
26
|
+
def state
|
27
|
+
@wired_actions._app.state
|
28
|
+
end
|
29
|
+
|
24
30
|
private
|
25
31
|
|
26
32
|
# Render entire MyApp::MainComponent
|
27
33
|
# Called from runtime.rb
|
28
34
|
def render_view(state)
|
29
|
-
Ovto.debug_trace_log("rendering #{self}")
|
30
35
|
do_render(state: state)
|
31
36
|
end
|
32
37
|
|
33
38
|
def do_render(**args)
|
39
|
+
Ovto.debug_trace_log("rendering #{self}")
|
34
40
|
@vdom_tree = []
|
35
41
|
@done_render = false
|
36
42
|
@current_state = args[:state]
|
@@ -69,8 +75,12 @@ module Ovto
|
|
69
75
|
# o 'div' do
|
70
76
|
# o 'h1', 'Hello.'
|
71
77
|
# end
|
78
|
+
# o 'div', `{nodeName: ....}` # Inject VDom spec directly
|
72
79
|
def o(_tag_name, arg1=nil, arg2=nil, &block)
|
73
|
-
if
|
80
|
+
if native?(arg1)
|
81
|
+
attributes = {}
|
82
|
+
content = arg1
|
83
|
+
elsif arg1.is_a?(Hash)
|
74
84
|
attributes = arg1
|
75
85
|
content = arg2
|
76
86
|
elsif arg2 == nil
|
@@ -146,13 +156,21 @@ module Ovto
|
|
146
156
|
when content && block
|
147
157
|
raise ArgumentError, "o cannot take both content and block"
|
148
158
|
when content
|
149
|
-
|
159
|
+
if native?(content)
|
160
|
+
[content]
|
161
|
+
else
|
162
|
+
[content.to_s]
|
163
|
+
end
|
150
164
|
when block
|
151
165
|
@vdom_tree.push []
|
152
166
|
block_value = block.call
|
153
167
|
results = @vdom_tree.pop
|
154
168
|
if results.length > 0 # 'o' was called at least once
|
155
169
|
results
|
170
|
+
elsif native?(block_value)
|
171
|
+
# Inject VDom tree written in JS object
|
172
|
+
# eg. Embed markdown
|
173
|
+
[block_value]
|
156
174
|
elsif block_value.is_a?(String)
|
157
175
|
# When 'o' is never called in the child block, use the last value
|
158
176
|
# eg.
|
data/lib/ovto/runtime.rb
CHANGED
@@ -12,6 +12,10 @@ module Ovto
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def scheduleRender
|
15
|
+
# An action is invoked before Ovto::Runtime#run.
|
16
|
+
# Do nothing here because `scheduleRender` will eventually be called by #run
|
17
|
+
return unless @scheduleRender
|
18
|
+
|
15
19
|
@scheduleRender.call
|
16
20
|
end
|
17
21
|
end
|
@@ -94,63 +98,6 @@ return "";
|
|
94
98
|
return out
|
95
99
|
}
|
96
100
|
|
97
|
-
// function setPartialState(path, value, source) {
|
98
|
-
// var target = {}
|
99
|
-
// if (path.length) {
|
100
|
-
// target[path[0]] =
|
101
|
-
// path.length > 1
|
102
|
-
// ? setPartialState(path.slice(1), value, source[path[0]])
|
103
|
-
// : value
|
104
|
-
// return clone(source, target)
|
105
|
-
// }
|
106
|
-
// return value
|
107
|
-
// }
|
108
|
-
//
|
109
|
-
// function getPartialState(path, source) {
|
110
|
-
// var i = 0
|
111
|
-
// while (i < path.length) {
|
112
|
-
// source = source[path[i++]]
|
113
|
-
// }
|
114
|
-
// return source
|
115
|
-
// }
|
116
|
-
//
|
117
|
-
// function wireStateToActions(path, state, actions) {
|
118
|
-
// for (var key in actions) {
|
119
|
-
// typeof actions[key] === "function"
|
120
|
-
// ? (function(key, action) {
|
121
|
-
// actions[key] = function(data) {
|
122
|
-
// var result = action(data)
|
123
|
-
//
|
124
|
-
// if (typeof result === "function") {
|
125
|
-
// result = result(getPartialState(path, getState()), actions)
|
126
|
-
// }
|
127
|
-
//
|
128
|
-
// if (
|
129
|
-
// result &&
|
130
|
-
// result !== (state = getPartialState(path, getState())) &&
|
131
|
-
// !result.then // !isPromise
|
132
|
-
// ) {
|
133
|
-
// globalState = setPartialState(
|
134
|
-
// path,
|
135
|
-
// clone(state, result),
|
136
|
-
// getState()
|
137
|
-
// )
|
138
|
-
// scheduleRender(globalState)
|
139
|
-
// }
|
140
|
-
//
|
141
|
-
// return result
|
142
|
-
// }
|
143
|
-
// })(key, actions[key])
|
144
|
-
// : wireStateToActions(
|
145
|
-
// path.concat(key),
|
146
|
-
// (state[key] = clone(state[key])),
|
147
|
-
// (actions[key] = clone(actions[key]))
|
148
|
-
// )
|
149
|
-
// }
|
150
|
-
//
|
151
|
-
// return actions
|
152
|
-
// }
|
153
|
-
|
154
101
|
function getKey(node) {
|
155
102
|
return node ? node.key : null
|
156
103
|
}
|
data/lib/ovto/version.rb
CHANGED
data/lib/ovto/wired_actions.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'native'
|
1
2
|
require 'promise'
|
2
3
|
|
3
4
|
module Ovto
|
@@ -7,21 +8,40 @@ module Ovto
|
|
7
8
|
end
|
8
9
|
|
9
10
|
def method_missing(name, args_hash={})
|
10
|
-
|
11
|
+
Ovto.log_error {
|
12
|
+
invoke_action(name, args_hash)
|
13
|
+
}
|
11
14
|
end
|
12
15
|
|
13
16
|
def respond_to?(name)
|
14
17
|
@actions.respond_to?(name)
|
15
18
|
end
|
16
19
|
|
20
|
+
# internal
|
21
|
+
def _app
|
22
|
+
@app
|
23
|
+
end
|
24
|
+
|
17
25
|
private
|
18
26
|
|
19
27
|
# Call action and schedule rendering
|
20
28
|
def invoke_action(name, args_hash)
|
21
29
|
kwargs = {state: @app.state}.merge(args_hash)
|
22
30
|
state_diff = @actions.__send__(name, **kwargs)
|
23
|
-
return if state_diff.nil? ||
|
31
|
+
return if state_diff.nil? ||
|
32
|
+
state_diff.is_a?(Promise) || `!!state_diff.then` ||
|
33
|
+
# eg.
|
34
|
+
# def action1(state:)
|
35
|
+
# actions.action2 if some_condition #=> MyApp::State or nil
|
36
|
+
# end
|
37
|
+
state_diff.is_a?(Ovto::State)
|
24
38
|
|
39
|
+
if native?(state_diff)
|
40
|
+
raise "action `#{name}' returned js object: #{`name.toString()`}"
|
41
|
+
end
|
42
|
+
unless state_diff.is_a?(Hash)
|
43
|
+
raise "action `#{name}' must return hash but got #{state_diff.inspect}"
|
44
|
+
end
|
25
45
|
new_state = @app.state.merge(state_diff)
|
26
46
|
if new_state != @app.state
|
27
47
|
@runtime.scheduleRender
|
data/ovto.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ovto
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yutaka HARA
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-04-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: opal
|
@@ -24,11 +24,26 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0.11'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: thor
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.20'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.20'
|
27
41
|
description: Ovto is a client-side framework for Opal. You can write single-page apps
|
28
42
|
with Ruby.
|
29
43
|
email:
|
30
44
|
- yutaka.hara+github@gmail.com
|
31
|
-
executables:
|
45
|
+
executables:
|
46
|
+
- ovto
|
32
47
|
extensions: []
|
33
48
|
extra_rdoc_files: []
|
34
49
|
files:
|
@@ -123,6 +138,7 @@ files:
|
|
123
138
|
- examples/static/Rakefile
|
124
139
|
- examples/static/app.rb
|
125
140
|
- examples/static/index.html
|
141
|
+
- exe/ovto
|
126
142
|
- index.html
|
127
143
|
- lib/ovto.rb
|
128
144
|
- lib/ovto/actions.rb
|
@@ -158,7 +174,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
158
174
|
version: '0'
|
159
175
|
requirements: []
|
160
176
|
rubyforge_project:
|
161
|
-
rubygems_version: 2.7.6
|
177
|
+
rubygems_version: 2.7.6.2
|
162
178
|
signing_key:
|
163
179
|
specification_version: 4
|
164
180
|
summary: Simple client-side framework for Opal
|