beryl 0.2.5 → 0.3.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/Gemfile.lock +1 -1
- data/app/initial_state.rb +0 -1
- data/app/routes.rb +5 -0
- data/app/view.rb +11 -2
- data/app/{something.rb → widgets/homepage.rb} +2 -10
- data/app/widgets/not_found.rb +7 -0
- data/app/widgets/page_x.rb +7 -0
- data/config.ru +5 -1
- data/lib/beryl/backend.rb +26 -3
- data/lib/beryl/backend_runtime.rb +54 -0
- data/lib/beryl/deserializer.rb +2 -0
- data/lib/beryl/frontend.rb +3 -2
- data/lib/beryl/{runtime.rb → frontend_runtime.rb} +22 -3
- data/lib/beryl/html_renderer.rb +30 -0
- data/lib/beryl/routing/matcher.rb +29 -0
- data/lib/beryl/routing/router.rb +32 -0
- data/lib/beryl/version.rb +1 -1
- metadata +11 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '0359afa9fc5dcf6e6116594b9ba70c06425e9c889069e60c5398c1be9b39d100'
|
4
|
+
data.tar.gz: 505f33152ec6db4b9ddfd2dcbd30351357a3dacc5434493a67e271104cde0c40
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bce4b5249650d957206888567d29ca76d21038a11f228466da07dd1824ac2a0a76161bbc84cbf89f61e32bea48f3322302e0dd75294c1dd5f69c67a8c77f8135
|
7
|
+
data.tar.gz: 68bc437aa950783b2c37ed46410140067202e30103d35c901273f4eaa4cbd8e47da4390c607d9268a05cd5256c78c9d2225869a6ce9467c404dc511bf1b68a54
|
data/Gemfile.lock
CHANGED
data/app/initial_state.rb
CHANGED
data/app/routes.rb
ADDED
data/app/view.rb
CHANGED
@@ -1,8 +1,17 @@
|
|
1
1
|
require 'beryl/view'
|
2
|
-
require '
|
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
|
-
|
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
|
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
|
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
|
-
|
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(
|
41
|
+
Serializer.serialize(@state).gsub('"', '"')
|
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"
|
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
|
data/lib/beryl/deserializer.rb
CHANGED
data/lib/beryl/frontend.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'opal'
|
2
2
|
require 'native'
|
3
3
|
require 'beryl/deserializer'
|
4
|
-
require 'beryl/
|
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('"', '"')
|
21
21
|
state = Beryl::Deserializer.deserialize(serialized_state)
|
22
|
-
|
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
|
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
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.
|
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-
|
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/
|
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/
|
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
|