live 0.2.0 → 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: f33999c1164c25bd9fccfac8d7be846b6ad536ae04da0302b450662a7db1624f
4
- data.tar.gz: 0bbd2f3b7b06819b9ae5cb8b057277a1885fe7d44598238a46d21704eb62173c
3
+ metadata.gz: a836ae392c3fb38c18c6317e94786d0ad943d01afe1486026333148531bb681b
4
+ data.tar.gz: e5f9ecb4911b74fbecad809d068d8a076d8cd4d93c8d015f9d709ccb737c5b76
5
5
  SHA512:
6
- metadata.gz: a5bcd37c979d0155cd70b822f7959ae7d97661c7652f2e945cc9b9ff6ff4a099600894f8348b0b135abeb90dd1156e724ed2b063b68c2c908c5823240b41af3c
7
- data.tar.gz: 68aae390d5d46ca5e81d4f333a40d3db1e9fbf8394d41600576dace4b0a2bd2df5c94ab8795cbdd156bab01e07ecc0b372d84853c5e99c965481b4fb1f9a0ce6
6
+ metadata.gz: b896681bad42c651744baaef703204ef112e226446ce3ca530453f4247053f0dde771897d898a45b0a2c5ff64e3291e0e1a856d8e05041dcc5424d28e093aed1
7
+ data.tar.gz: bb53aa53e263bcbc03ae22dc8280c21cdc388e261430ac9e70533f6a551a360341bbffa255a0271cc1e88cd4d7c1d2757b185fd057b75d0e224920d2205d74ff
data/lib/live/element.rb CHANGED
@@ -23,7 +23,10 @@
23
23
  require 'json'
24
24
 
25
25
  module Live
26
+ # Represents a single dynamic content area on the page.
26
27
  class Element
28
+ # @parameter id [String] The unique identifier within the page.
29
+ # @parameter data [Hash] The data associated with the element, typically stored as `data-` attributes.
27
30
  def initialize(id, **data)
28
31
  @id = id
29
32
  @data = data
@@ -32,8 +35,11 @@ module Live
32
35
  @page = nil
33
36
  end
34
37
 
38
+ # The unique id within the bound page.
35
39
  attr :id
36
40
 
41
+ # Generate a JavaScript string which forwards the specified event to the server.
42
+ # @parameter details [Hash] The details associated with the forwarded event.
37
43
  def forward(details = nil)
38
44
  if details
39
45
  "live.forward(#{JSON.dump(@id)}, event, #{JSON.dump(details)})"
@@ -42,13 +48,25 @@ module Live
42
48
  end
43
49
  end
44
50
 
51
+ # Bind this tag to a dynamically updating page.
52
+ # @parameter page [Live::Page]
45
53
  def bind(page)
46
54
  @page = page
47
55
  end
48
56
 
49
- def handle(event, details)
57
+ def close
58
+ @page = nil
59
+ end
60
+
61
+ # Handle a client event, typically as triggered by {#forward}.
62
+ # @parameter event [String] The type of the event.
63
+ # @parameter details [Hash] The associated details if any.
64
+ def handle(event, details = nil)
50
65
  end
51
66
 
67
+ # Enqueue a remote procedure call to the currently bound page.
68
+ # @parameter method [Symbol] The name of the remote functio to invoke.
69
+ # @parameter arguments [Array]
52
70
  def rpc(method, arguments)
53
71
  # This update might not be sent right away. Therefore, mutable arguments may be serialized to JSON at a later time (or never). This could be a race condition:
54
72
  @page.updates.enqueue([method, arguments])
data/lib/live/page.rb CHANGED
@@ -27,7 +27,9 @@ require 'async'
27
27
  require 'async/queue'
28
28
 
29
29
  module Live
30
+ # Represents a connected client page with bound dynamic content areas.
30
31
  class Page
32
+ # @parameter resolver [Live::Resolver] Used to resolve client-side elements to server-side element instances.
31
33
  def initialize(resolver)
32
34
  @resolver = resolver
33
35
 
@@ -35,18 +37,30 @@ module Live
35
37
  @updates = Async::Queue.new
36
38
  end
37
39
 
40
+ # The queue of outstanding events to be sent to the client.
38
41
  attr :updates
39
42
 
43
+ # Bind a client-side element to a server side element.
44
+ # @parameter element [Live::Element] The element to bind.
40
45
  def bind(element)
41
46
  @elements[element.id] = element
42
47
 
43
48
  element.bind(self)
44
49
  end
45
50
 
51
+ # Resolve a client-side element to a server side instance.
52
+ # @parameter id [String] The unique identifier within the page.
53
+ # @parameter data [Hash] The data associated with the element, typically stored as `data-` attributes.
46
54
  def resolve(id, data)
47
55
  @resolver.call(id, data)
48
56
  end
49
57
 
58
+ # Handle an event from the client. If the element could not be found, it is silently ignored.
59
+ # @parameter id [String] The unique identifier of the element which forwarded the event.
60
+ # @parameter event [String] The type of the event.
61
+ # @parameter details [Hash] The associated details if any.
62
+ # @returns [Object] The result of the element handler, if the element was found.
63
+ # @returns [Nil] If the element could not be found.
50
64
  def handle(id, event, details)
51
65
  if element = @elements[id]
52
66
  return element.handle(event, details)
@@ -57,39 +71,42 @@ module Live
57
71
  return nil
58
72
  end
59
73
 
60
- def run(connection)
61
- reader_task = start_reader(connection)
62
-
63
- while update = @updates.dequeue
64
- Console.logger.debug(self, "Sending update:", update)
65
-
66
- connection.write(update)
67
- connection.flush if @updates.empty?
74
+ def close
75
+ @elements.each do |id, element|
76
+ element.close
68
77
  end
69
- ensure
70
- reader_task&.stop
71
78
  end
72
79
 
73
- private
74
-
75
- def start_reader(connection)
76
- Async do
77
- while message = connection.read
78
- Console.logger.debug(self, "Reading message:", message)
80
+ # Run the event handling loop with the given websocket connection.
81
+ # @parameter connection [Async::WebSocket::Connection]
82
+ def run(connection)
83
+ queue_task = Async do
84
+ while update = @updates.dequeue
85
+ Console.logger.debug(self, "Sending update:", update)
79
86
 
80
- if id = message[:bind] and data = message[:data]
81
- if element = self.resolve(id, data)
82
- self.bind(element)
83
- else
84
- Console.logger.warn(self, "Could not resolve element:", message)
85
- end
86
- elsif id = message[:id]
87
- self.handle(id, message[:event], message[:details])
87
+ connection.write(update)
88
+ connection.flush if @updates.empty?
89
+ end
90
+ end
91
+
92
+ while message = connection.read
93
+ Console.logger.debug(self, "Reading message:", message)
94
+
95
+ if id = message[:bind] and data = message[:data]
96
+ if element = self.resolve(id, data)
97
+ self.bind(element)
88
98
  else
89
- Console.logger.warn(self, "Unhandled message:", message)
99
+ Console.logger.warn(self, "Could not resolve element:", message)
90
100
  end
101
+ elsif id = message[:id]
102
+ self.handle(id, message[:event], message[:details])
103
+ else
104
+ Console.logger.warn(self, "Unhandled message:", message)
91
105
  end
92
106
  end
107
+ ensure
108
+ self.close
109
+ queue_task&.stop
93
110
  end
94
111
  end
95
112
  end
data/lib/live/resolver.rb CHANGED
@@ -34,6 +34,7 @@ module Live
34
34
  @allowed = {}
35
35
  end
36
36
 
37
+ # @attribute [Hash(String, Class)] A map of allowed class names.
37
38
  attr :allowed
38
39
 
39
40
  def freeze
data/lib/live/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Live
4
- VERSION = "0.2.0"
4
+ VERSION = "0.3.0"
5
5
  end
data/lib/live/view.rb CHANGED
@@ -24,22 +24,31 @@ require_relative 'element'
24
24
  require 'trenni/builder'
25
25
 
26
26
  module Live
27
+ # Represents a single division of content on the page an provides helpers for rendering the content.
27
28
  class View < Element
29
+ # Replace the content of the client-side element by rendering this view.
28
30
  def replace!
29
31
  rpc(:replace, [@id, self.to_html])
30
32
  end
31
33
 
32
- def append!(node)
33
- rpc(:append, [@id, node.to_html])
34
+ # Append to the content of the client-side element by appending the specified element.
35
+ # @parameter node [Live::Element] The element to append.
36
+ def append!(element)
37
+ rpc(:append, [@id, element.to_html])
34
38
  end
35
39
 
36
- def prepend!(node)
37
- rpc(:prepend, [@id, node.to_html])
40
+ # Prepend to the content of the client-side element by appending the specified element.
41
+ # @parameter node [Live::Element] The element to prepend.
42
+ def prepend!(element)
43
+ rpc(:prepend, [@id, element.to_html])
38
44
  end
39
45
 
46
+ # Render the element.
47
+ # @parameter builder [Trenni::Builder] The HTML builder.
40
48
  def render(builder)
41
49
  end
42
50
 
51
+ # @returns [Object] The generated HTML.
43
52
  def to_html
44
53
  Trenni::Builder.fragment do |builder|
45
54
  builder.tag :div, id: @id, class: 'live', data: @data do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: live
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-04-19 00:00:00.000000000 Z
11
+ date: 2021-05-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: trenni