beryl 0.2.5 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 024bc3d265686b410dc6f3fc59b3768f68387a6acea8c47e1871b037a4e81b19
4
- data.tar.gz: 7a5fad376ffce81ecba38189a661d0eaf1c82224b3667f99ba98c9d1886c9ca3
3
+ metadata.gz: '0359afa9fc5dcf6e6116594b9ba70c06425e9c889069e60c5398c1be9b39d100'
4
+ data.tar.gz: 505f33152ec6db4b9ddfd2dcbd30351357a3dacc5434493a67e271104cde0c40
5
5
  SHA512:
6
- metadata.gz: 1b035c97f8e44c4dcd69b092df5d2b83019b9f7e33c2eb728877c264ccab9ee15b2e05c5cf3f279b70bf96d2eb98a95d67ca593eb21e7256c091d1b5711f2e6c
7
- data.tar.gz: 4ca220ec4b41fcf09122d3fdd926095124f4b74c66a7d22b42b97153f09aa091cdc7551500708fcfa4db1d53ff6d23a1e2f949d3f988771584f598730dfe1947
6
+ metadata.gz: bce4b5249650d957206888567d29ca76d21038a11f228466da07dd1824ac2a0a76161bbc84cbf89f61e32bea48f3322302e0dd75294c1dd5f69c67a8c77f8135
7
+ data.tar.gz: 68bc437aa950783b2c37ed46410140067202e30103d35c901273f4eaa4cbd8e47da4390c607d9268a05cd5256c78c9d2225869a6ce9467c404dc511bf1b68a54
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- beryl (0.2.4)
4
+ beryl (0.2.5)
5
5
  bowser
6
6
  capybara
7
7
  opal
data/app/initial_state.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  {
2
2
  content: 'here we will load something',
3
3
  counter: 0,
4
- route: nil
5
4
  }
data/app/routes.rb ADDED
@@ -0,0 +1,5 @@
1
+ route '/', :homepage
2
+
3
+ route '/page-x', :page_x
4
+
5
+ route 'dupa/:id', :dupa_page
data/app/view.rb CHANGED
@@ -1,8 +1,17 @@
1
1
  require 'beryl/view'
2
- require 'something'
2
+ require 'widgets/homepage'
3
+ require 'widgets/page_x'
4
+ require 'widgets/not_found'
3
5
 
4
6
  class View < Beryl::View
5
7
  def render
6
- Something.new.render(state)
8
+ case state[:route]
9
+ when :homepage
10
+ Homepage.new.render(state)
11
+ when :page_x
12
+ PageX.new.render(state)
13
+ else
14
+ NotFound.new.render(state)
15
+ end
7
16
  end
8
17
  end
@@ -1,6 +1,6 @@
1
1
  require 'beryl/widget'
2
2
 
3
- class Something < Beryl::Widget
3
+ class Homepage < Beryl::Widget
4
4
  def render(state)
5
5
  column :fill_width, :fill_height do
6
6
  row :fill_width do
@@ -38,12 +38,4 @@ class Something < Beryl::Widget
38
38
  end
39
39
  end
40
40
  end
41
- end
42
-
43
-
44
- # column :fill_width, :fill_height do
45
- # text 'Bart', height: 100, width: 300
46
- # text 'Abc', proportional_height: 2
47
- # text 'Karol', :fill_height
48
- # text 'Xyz', proportional_height: 3
49
- # end
41
+ end
@@ -0,0 +1,7 @@
1
+ require 'beryl/widget'
2
+
3
+ class NotFound < Beryl::Widget
4
+ def render(state)
5
+ text "Not found..."
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ require 'beryl/widget'
2
+
3
+ class PageX < Beryl::Widget
4
+ def render(state)
5
+ text "Other route: #{state[:route]}"
6
+ end
7
+ end
data/config.ru CHANGED
@@ -1,5 +1,9 @@
1
+ app_path = File.expand_path('../app', __FILE__)
2
+ $LOAD_PATH.unshift(app_path) unless $LOAD_PATH.include?(app_path)
3
+
1
4
  require 'beryl/backend'
2
5
  require 'rack'
6
+ require 'view'
3
7
 
4
8
  use Rack::Static, :urls => ['/build']
5
- run Beryl::Backend.new
9
+ run Beryl::Backend.new(View.new)
data/lib/beryl/backend.rb CHANGED
@@ -1,16 +1,31 @@
1
1
  require 'command_handler'
2
2
  require 'json'
3
3
  require 'serializer'
4
+ require 'beryl/routing/router'
5
+ require 'beryl/html_renderer'
6
+ require 'beryl/backend_runtime'
4
7
 
5
8
  module Beryl
6
9
  class Backend
10
+ def initialize(view)
11
+ @view = view
12
+ initial_state = eval(File.read('app/initial_state.rb'))
13
+ @state = initial_state.clone
14
+ end
15
+
7
16
  def call(env)
8
17
  req = Rack::Request.new(env)
9
18
  case req.path_info
10
19
  when '/command'
11
20
  [200, { 'Content-Type' => 'application/json; charset=utf-8' }, [handle_command(req)]]
12
21
  else
13
- [200, { 'Content-Type' => 'text/html; charset=utf-8' }, [response]]
22
+ router = Beryl::Routing::Router.new
23
+ route = router.match(req.path_info)
24
+ @state[:route] = route[0]
25
+ @state[:params] = route[1]
26
+ puts "STATE = #{@state}"
27
+ code = (route[0] != :not_found ? 200 : 404)
28
+ [code, { 'Content-Type' => 'text/html; charset=utf-8' }, [response]]
14
29
  end
15
30
  end
16
31
 
@@ -23,7 +38,15 @@ module Beryl
23
38
  end
24
39
 
25
40
  def hydrate_state
26
- Serializer.serialize(eval(File.read('app/initial_state.rb'))).gsub('"', '&quot;')
41
+ Serializer.serialize(@state).gsub('"', '&quot;')
42
+ end
43
+
44
+ def render
45
+ runtime = Beryl::BackendRuntime.new(@state, @view)
46
+ runtime.process_all_messages
47
+ @view.state = runtime.state
48
+ virtual_dom = VirtualDOM.new(@view.render)
49
+ HTMLRenderer.new.render(virtual_dom.dom.first)
27
50
  end
28
51
 
29
52
  def response
@@ -35,7 +58,7 @@ module Beryl
35
58
  <link rel="stylesheet" type="text/css" href="build/style.css">
36
59
  </head>
37
60
  <body>
38
- <div id="beryl" data-beryl="#{hydrate_state}" class="bg-color-255-255-255-255 font-color-0-0-0-255 font-size-20 font-open-sanshelveticaverdanasans-serif s e ui s e"></div>
61
+ <div id="beryl" data-beryl="#{hydrate_state}" class="bg-color-255-255-255-255 font-color-0-0-0-255 font-size-20 font-open-sanshelveticaverdanasans-serif s e ui s e">#{render}</div>
39
62
  </body>
40
63
  </html>
41
64
  HEREDOC
@@ -0,0 +1,54 @@
1
+ module Beryl
2
+ class BackendRuntime
3
+ attr_reader :state
4
+
5
+ def initialize(state, view)
6
+ @messages = []
7
+ @state = state
8
+ @view = view
9
+ @commands = []
10
+ end
11
+
12
+ def push(message)
13
+ @messages << message
14
+ end
15
+
16
+ def process_all_messages
17
+ while @messages.any?
18
+ message = @messages.shift
19
+ result = transition(message.first, message.last)
20
+ @state = result.is_a?(Array) ? result.first : result
21
+ command = result.is_a?(Array) ? result[1] : nil
22
+ run_command(result[1], result[2]) if command
23
+ if @commands.any?
24
+ while @commands.any? do end # TODO: refactor
25
+ process_all_messages
26
+ end
27
+ end
28
+ end
29
+
30
+ def run
31
+ process
32
+ render
33
+ end
34
+
35
+ def run_command(type, payload)
36
+ puts 'running command'
37
+ end
38
+
39
+ def transition(type, payload)
40
+ case type
41
+
42
+ when :IncrementClicked
43
+ @state.merge(counter: @state[:counter] + 1)
44
+
45
+ when :LoadClicked
46
+ [@state, :FetchData, key_1: 1, key_2: 2]
47
+
48
+ when :LoadSuccess
49
+ @state.merge(content: payload[:data])
50
+
51
+ end
52
+ end
53
+ end
54
+ end
@@ -15,6 +15,8 @@ module Beryl
15
15
  item['value'].to_i
16
16
  when 'String'
17
17
  item['value']
18
+ when 'Symbol'
19
+ item['value'].to_sym
18
20
  end
19
21
  end
20
22
  end
@@ -1,7 +1,7 @@
1
1
  require 'opal'
2
2
  require 'native'
3
3
  require 'beryl/deserializer'
4
- require 'beryl/runtime'
4
+ require 'beryl/frontend_runtime'
5
5
 
6
6
  module Beryl
7
7
  class Frontend
@@ -19,7 +19,8 @@ module Beryl
19
19
  root = document.getElementById('beryl')
20
20
  serialized_state = root.getAttribute('data-beryl').gsub('&quot;', '"')
21
21
  state = Beryl::Deserializer.deserialize(serialized_state)
22
- Beryl::Runtime.new(root, state, @view).run
22
+ puts "STATE = #{state.inspect}"
23
+ Beryl::FrontendRuntime.new(root, state, @view).run
23
24
  end
24
25
  end
25
26
  end
@@ -4,12 +4,15 @@ require 'bowser/http'
4
4
  require 'serializer'
5
5
 
6
6
  module Beryl
7
- class Runtime
7
+ class FrontendRuntime
8
+ attr_reader :state
9
+
8
10
  def initialize(root, state, view)
9
11
  @messages = []
10
12
  @root = root
11
13
  @state = state
12
14
  @view = view
15
+ @commands = []
13
16
  end
14
17
 
15
18
  def push(message)
@@ -33,17 +36,33 @@ module Beryl
33
36
  end
34
37
  end
35
38
 
39
+ def process_all_messages
40
+ while @messages.any?
41
+ message = @messages.shift
42
+ result = transition(message.first, message.last)
43
+ @state = result.is_a?(Array) ? result.first : result
44
+ command = result.is_a?(Array) ? result[1] : nil
45
+ run_command(result[1], result[2]) if command
46
+ if @commands.any?
47
+ while @commands.any? do end # TODO: refactor
48
+ process_all_messages
49
+ end
50
+ end
51
+ end
52
+
36
53
  def run
37
54
  process
38
55
  render
39
56
  end
40
57
 
41
58
  def run_command(type, payload)
59
+ uuid = SecureRandom.uuid
60
+ @commands << uuid
42
61
  Task.new do
43
62
  Bowser::HTTP.fetch('/command', method: :post, data: { type: type, payload: Serializer.serialize(payload) })
44
63
  .then(&:json) # JSONify the response
45
- .then { |response| puts response }
46
- .catch { |exception| warn exception.message }
64
+ .then { |response| puts response; @commands.delete(uuid) }
65
+ .catch { |exception| warn exception.message; @commands.delete(uuid) }
47
66
  end
48
67
  end
49
68
 
@@ -0,0 +1,30 @@
1
+ module Beryl
2
+ class HTMLRenderer
3
+ def render(element)
4
+ return element[:props][:nodeValue] if element[:type] == 'text'
5
+ "#{open_tag(element)}#{children(element)}#{close_tag(element)}"
6
+ end
7
+
8
+ private
9
+
10
+ def children(element)
11
+ element[:children].each_with_object('') do |child, html|
12
+ html << render(child)
13
+ end
14
+ end
15
+
16
+ def close_tag(element)
17
+ "</#{element[:type]}>"
18
+ end
19
+
20
+ def open_tag(element)
21
+ "<#{element[:type]}#{props(element[:props])}>"
22
+ end
23
+
24
+ def props(props)
25
+ props.each_with_object('') do |(key, value), html|
26
+ html << " #{key}=\"#{value}\""
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,29 @@
1
+ module Beryl
2
+ module Routing
3
+ module Matcher
4
+ extend self
5
+
6
+ DEFAULT_CONSTRAINT = '.*'
7
+
8
+ def match(route, path)
9
+ params = params(route)
10
+ r = params.each_with_object("#{route.clone}") do |param, result|
11
+ result.sub!(":#{param}", "(#{DEFAULT_CONSTRAINT})")
12
+ end
13
+ regex = /\A#{r}\z/
14
+ matched = regex.match(path)
15
+ return false unless matched
16
+ params(route).each_with_object({}).with_index do |(param, result), index|
17
+ result[param] = matched[index + 1]
18
+ end
19
+
20
+ end
21
+
22
+ private
23
+
24
+ def params(route)
25
+ route.scan(/:[[:lower:]_]+[[:lower:][:digit:]_]*/).map { |param| param[1..-1].to_sym }
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,32 @@
1
+ require 'beryl/routing/matcher'
2
+
3
+ module Beryl
4
+ module Routing
5
+ class Router
6
+ attr_reader :routes
7
+
8
+ def initialize
9
+ @routes = []
10
+ draw
11
+ end
12
+
13
+ def match(path)
14
+ @routes.each do |route|
15
+ matched = Beryl::Routing::Matcher.match(route[0], path)
16
+ return [route[1], matched] if matched
17
+ end
18
+ [:not_found]
19
+ end
20
+
21
+ private
22
+
23
+ def draw
24
+ eval(File.open(File.expand_path('./app/routes.rb')).read)
25
+ end
26
+
27
+ def route(path, route)
28
+ @routes << [path, route]
29
+ end
30
+ end
31
+ end
32
+ end
data/lib/beryl/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Beryl
2
- VERSION = '0.2.5'
2
+ VERSION = '0.3.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: beryl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.5
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bart Blast
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-09-28 00:00:00.000000000 Z
11
+ date: 2018-10-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -139,8 +139,11 @@ files:
139
139
  - Rakefile-template
140
140
  - app/frontend.rb
141
141
  - app/initial_state.rb
142
- - app/something.rb
142
+ - app/routes.rb
143
143
  - app/view.rb
144
+ - app/widgets/homepage.rb
145
+ - app/widgets/not_found.rb
146
+ - app/widgets/page_x.rb
144
147
  - beryl.gemspec
145
148
  - bin/console
146
149
  - bin/setup
@@ -148,9 +151,13 @@ files:
148
151
  - lib/beryl.rb
149
152
  - lib/beryl/Rakefile
150
153
  - lib/beryl/backend.rb
154
+ - lib/beryl/backend_runtime.rb
151
155
  - lib/beryl/deserializer.rb
152
156
  - lib/beryl/frontend.rb
153
- - lib/beryl/runtime.rb
157
+ - lib/beryl/frontend_runtime.rb
158
+ - lib/beryl/html_renderer.rb
159
+ - lib/beryl/routing/matcher.rb
160
+ - lib/beryl/routing/router.rb
154
161
  - lib/beryl/style.css
155
162
  - lib/beryl/utils.rb
156
163
  - lib/beryl/version.rb