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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cbe9fd351db11fdad3445d8a44c356e4343c789a4ce0521cbfc1b70d5c72eed1
4
- data.tar.gz: 9c37eaf812a82accfc9e9da7ba6c1e5bea62c90a27b5965f13ddd514a38cdba5
3
+ metadata.gz: c16fab45131f98235cddc5a78d0128105dea5d60d4b5a2849980af71b21d40bf
4
+ data.tar.gz: cec1207210d7f94f3791655c0ed2bed8f7d91d0f579997c913a8e95b2afae438
5
5
  SHA512:
6
- metadata.gz: 35caabda59fef24ff185b829ce794c4e4cc23645790c33ba544245ecc0fd66d4d78a005190afbba9d07c9edf5e9b33bd62fb4a5496234c1ede06fd14e31d4565
7
- data.tar.gz: b5654ce1ffed9aba99eafc4905828bdd525b4b3f461667fc013058ad943455fab6e332e0a20808f779a3128f56225907b89c2c3b0e1daf0139b9ff1cf4a03d92
6
+ metadata.gz: b142cc06e37df28acfee9f94ad9cb1ce46e2a565878f0078afb584f793e7365bb383c39f4aa38d7406b4681daab7499ce433d14984a5ab27f5417d286563757b
7
+ data.tar.gz: ef7c8e4d03dfedf31d4052b5c758d33e307f8211b5ef42e648267d1c1c502119dae4b2e0bfa4fc58e83152775e3ff76c6f1811fe3ed628eba4a6a42c7664736b
data/.gitmodules CHANGED
@@ -1,3 +0,0 @@
1
- [submodule "opal-rspec"]
2
- path = opal-rspec
3
- url = git://github.com/opal/opal-rspec.git
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.3.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.4)
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.6.2)
19
- opal (>= 0.10.0, < 0.12)
20
- opal-sprockets (0.4.2.0.11.0.3.1)
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.1)
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.6)
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.16)
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
- 1.17.1
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(state:, value:)
29
+ def set_celsius(value:)
30
30
  return {celsius: value}
31
31
  end
32
32
 
33
- def set_fahrenheit(state:, value:)
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(state:)
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(state:, by:)
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(state:)
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(state:)
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(state:, tasks_json:)
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(state:)
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(state:)
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(state:)
52
+ def render
53
53
  o 'input', {
54
54
  type: 'button',
55
55
  value: 'Hello',
@@ -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
- It must take the global app state as a keyword argument `state:`.
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(state:)
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(state:)
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(state:)
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.
@@ -18,18 +18,18 @@ class MyApp < Ovto::App
18
18
  end
19
19
 
20
20
  class Actions < Ovto::Actions
21
- def set_celsius(state:, value:)
21
+ def set_celsius(value:)
22
22
  return {celsius: value}
23
23
  end
24
24
 
25
- def set_fahrenheit(state:, value:)
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(state:)
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(state:) # Don't miss the `:`. This is not a typo but
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(state:)
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(state:)
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(state:, value:)
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(state:, value:)
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
- 1.17.1
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(state:)
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(state:, id:)
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(state:)
46
+ def destroy_completed_todos
47
47
  return {todos: state.todos.reject(&:done)}
48
48
  end
49
49
 
50
- def toggle_todo(state:, id:)
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(state:, done:)
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(state:, value:)
65
+ def set_input(value:)
66
66
  return {input: value}
67
67
  end
68
68
 
69
- def set_filter(state:, 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(state:)
156
+ def render
157
157
  o 'section.todoapp' do
158
158
  o Header,
159
159
  input: state.input
@@ -1,3 +1,4 @@
1
1
  source "https://rubygems.org"
2
2
  gem "ovto", path: '../../'
3
3
  gem 'rake'
4
+ gem 'ifchanged'
@@ -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
- 1.17.1
34
+ 2.0.1
@@ -2,3 +2,8 @@ desc 'compile into js'
2
2
  task :default do
3
3
  sh 'bundle exec opal -c -g ovto app.rb > app.js'
4
4
  end
5
+
6
+ desc 'start auto-compiling'
7
+ task :watch do
8
+ sh 'ifchanged app.rb -d "bundle exec rake"'
9
+ end
@@ -10,18 +10,18 @@ class MyApp < Ovto::App
10
10
  end
11
11
 
12
12
  class Actions < Ovto::Actions
13
- def set_celsius(state:, value:)
13
+ def set_celsius(value:)
14
14
  return {celsius: value}
15
15
  end
16
16
 
17
- def set_fahrenheit(state:, value:)
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(state:)
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
@@ -6,5 +6,9 @@ module Ovto
6
6
  def actions
7
7
  @wired_actions
8
8
  end
9
+
10
+ def state
11
+ @wired_actions._app.state
12
+ end
9
13
  end
10
14
  end
@@ -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 arg1.is_a?(Hash)
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
- [content.to_s]
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
@@ -1,3 +1,3 @@
1
1
  module Ovto
2
- VERSION = '0.3.0'
2
+ VERSION = '0.4.0'
3
3
  end
@@ -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
- invoke_action(name, args_hash)
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? || state_diff.is_a?(Promise) || `!!state_diff.then`
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
@@ -19,4 +19,5 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ["lib"]
20
20
 
21
21
  spec.add_dependency "opal", '~> 0.11'
22
+ spec.add_dependency "thor", '~> 0.20'
22
23
  end
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.3.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: 2018-12-24 00:00:00.000000000 Z
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