inesita 0.3.5 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/Gemfile +1 -2
- data/README.md +4 -4
- data/Rakefile +0 -1
- data/bin/inesita +1 -1
- data/inesita.gemspec +2 -4
- data/lib/inesita.rb +0 -5
- data/lib/inesita/cli/build.rb +58 -56
- data/lib/inesita/cli/new.rb +18 -16
- data/lib/inesita/cli/server.rb +16 -14
- data/lib/inesita/cli/template/Gemfile.tt +1 -0
- data/lib/inesita/cli/template/app/application.js.rb.tt +2 -2
- data/lib/inesita/cli/watch.rb +57 -44
- data/opal/inesita.rb +1 -4
- data/opal/inesita/application.rb +7 -6
- data/opal/inesita/browser.rb +63 -0
- data/opal/inesita/component.rb +15 -17
- data/opal/inesita/component_virtual_dom_extension.rb +5 -3
- data/opal/inesita/router.rb +28 -23
- data/opal/inesita/routes.rb +12 -7
- data/opal/inesita/store.rb +9 -3
- data/spec/opal/component_spec.rb +3 -3
- data/spec/opal/spec_helper.rb +0 -1
- metadata +5 -36
- data/lib/inesita/app_files_listener.rb +0 -42
- data/lib/inesita/live_reload.rb +0 -47
- data/lib/rubame.rb +0 -156
- data/opal/inesita/live_reload.rb +0 -79
@@ -1,42 +0,0 @@
|
|
1
|
-
module Inesita
|
2
|
-
class AppFilesListener
|
3
|
-
include Singleton
|
4
|
-
CURRENT_DIR = Dir.pwd
|
5
|
-
|
6
|
-
def initialize
|
7
|
-
@websockets = []
|
8
|
-
listener = Listen.to(Config::APP_DIR) do |modified, added, _removed|
|
9
|
-
(modified + added).each do |file|
|
10
|
-
@websockets.each do |ws|
|
11
|
-
ws.send transform_filename(file)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
listener.start
|
16
|
-
end
|
17
|
-
|
18
|
-
def add_ws(ws)
|
19
|
-
@websockets << ws
|
20
|
-
end
|
21
|
-
|
22
|
-
def rm_ws(ws)
|
23
|
-
@websockets.delete(ws)
|
24
|
-
end
|
25
|
-
|
26
|
-
def transform_filename(filename)
|
27
|
-
filename.sub!(CURRENT_DIR, '')
|
28
|
-
path = filename.split('/')
|
29
|
-
path.delete('')
|
30
|
-
path.delete(Config::APP_DIR)
|
31
|
-
path = path.join('/').split('.')
|
32
|
-
|
33
|
-
prefix = Config::ASSETS_PREFIX
|
34
|
-
name = path.first
|
35
|
-
if path.include?('rb') || path.include?('js')
|
36
|
-
"#{prefix}|#{name}|js"
|
37
|
-
elsif path.include?('sass') || path.include?('css')
|
38
|
-
"#{prefix}|stylesheet|css"
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
data/lib/inesita/live_reload.rb
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
require 'rubame'
|
2
|
-
|
3
|
-
module Inesita
|
4
|
-
class LiveReload
|
5
|
-
INJECT_CODE = Opal.compile(File.read(File.expand_path('../../../opal/inesita/live_reload.rb', __FILE__)))
|
6
|
-
|
7
|
-
def initialize(app, _options = {})
|
8
|
-
@app = app
|
9
|
-
Thread.new do
|
10
|
-
begin
|
11
|
-
init_live_reload
|
12
|
-
rescue => e
|
13
|
-
puts e
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def call(env)
|
19
|
-
status, headers, body = @app.call(env)
|
20
|
-
if status == 200
|
21
|
-
new_body = inject_script(body)
|
22
|
-
headers['Content-Length'] = new_body.bytesize.to_s
|
23
|
-
[status, headers, [new_body]]
|
24
|
-
else
|
25
|
-
[status, headers, body]
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def inject_script(body)
|
30
|
-
new_body = ''
|
31
|
-
body.each { |line| new_body += line.to_s }
|
32
|
-
new_body.gsub('{ Opal.loaded', "{ #{INJECT_CODE} Opal.loaded")
|
33
|
-
end
|
34
|
-
|
35
|
-
def init_live_reload
|
36
|
-
AppFilesListener.instance
|
37
|
-
server = Rubame::Server.new('0.0.0.0', 23654)
|
38
|
-
loop do
|
39
|
-
server.run do |ws|
|
40
|
-
ws.onopen { AppFilesListener.instance.add_ws(ws) }
|
41
|
-
ws.onclose { AppFilesListener.instance.rm_ws(ws) }
|
42
|
-
ws.onmessage { |msg| ws.send 'pong' if msg == 'ping' }
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
data/lib/rubame.rb
DELETED
@@ -1,156 +0,0 @@
|
|
1
|
-
require 'websocket'
|
2
|
-
require 'socket'
|
3
|
-
|
4
|
-
module Rubame
|
5
|
-
class Server
|
6
|
-
def initialize(host, port)
|
7
|
-
Socket.do_not_reverse_lookup
|
8
|
-
@hostname = host
|
9
|
-
@port = port
|
10
|
-
|
11
|
-
@reading = []
|
12
|
-
@writing = []
|
13
|
-
|
14
|
-
@clients = {} # Socket as key, and Client as value
|
15
|
-
|
16
|
-
@socket = TCPServer.new(@hostname, @port)
|
17
|
-
@reading.push @socket
|
18
|
-
end
|
19
|
-
|
20
|
-
def accept
|
21
|
-
socket = @socket.accept_nonblock
|
22
|
-
@reading.push socket
|
23
|
-
handshake = WebSocket::Handshake::Server.new
|
24
|
-
client = Rubame::Client.new(socket, handshake, self)
|
25
|
-
|
26
|
-
while line = socket.gets
|
27
|
-
client.handshake << line
|
28
|
-
break if client.handshake.finished?
|
29
|
-
end
|
30
|
-
if client.handshake.valid?
|
31
|
-
@clients[socket] = client
|
32
|
-
client.write handshake.to_s
|
33
|
-
client.opened = true
|
34
|
-
return client
|
35
|
-
else
|
36
|
-
close(client)
|
37
|
-
end
|
38
|
-
return nil
|
39
|
-
end
|
40
|
-
|
41
|
-
def read(client)
|
42
|
-
|
43
|
-
pairs = client.socket.recvfrom(2000)
|
44
|
-
messages = []
|
45
|
-
|
46
|
-
if pairs[0].length == 0
|
47
|
-
close(client)
|
48
|
-
else
|
49
|
-
client.frame << pairs[0]
|
50
|
-
|
51
|
-
while f = client.frame.next
|
52
|
-
if (f.type == :close)
|
53
|
-
close(client)
|
54
|
-
return messages
|
55
|
-
else
|
56
|
-
messages.push f
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
end
|
61
|
-
|
62
|
-
return messages
|
63
|
-
|
64
|
-
end
|
65
|
-
|
66
|
-
def close(client)
|
67
|
-
@reading.delete client.socket
|
68
|
-
@clients.delete client.socket
|
69
|
-
begin
|
70
|
-
client.socket.close
|
71
|
-
ensure
|
72
|
-
client.closed = true
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
def run(&blk)
|
77
|
-
readable, _writable = IO.select(@reading, @writing)
|
78
|
-
|
79
|
-
if readable
|
80
|
-
readable.each do |socket|
|
81
|
-
client = @clients[socket]
|
82
|
-
if socket == @socket
|
83
|
-
client = accept
|
84
|
-
else
|
85
|
-
msg = read(client)
|
86
|
-
client.messaged = msg
|
87
|
-
end
|
88
|
-
|
89
|
-
blk.call(client) if client and blk
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
def stop
|
95
|
-
@socket.close
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
class Client
|
100
|
-
attr_accessor :socket, :handshake, :frame, :opened, :messaged, :closed
|
101
|
-
|
102
|
-
def initialize(socket, handshake, server)
|
103
|
-
@socket = socket
|
104
|
-
@handshake = handshake
|
105
|
-
@frame = WebSocket::Frame::Incoming::Server.new(:version => @handshake.version)
|
106
|
-
@opened = false
|
107
|
-
@messaged = []
|
108
|
-
@closed = false
|
109
|
-
@server = server
|
110
|
-
end
|
111
|
-
|
112
|
-
def write(data)
|
113
|
-
@socket.write data
|
114
|
-
end
|
115
|
-
|
116
|
-
def send(data)
|
117
|
-
frame = WebSocket::Frame::Outgoing::Server.new(:version => @handshake.version, :data => data, :type => :text)
|
118
|
-
begin
|
119
|
-
@socket.write frame
|
120
|
-
@socket.flush
|
121
|
-
rescue
|
122
|
-
@server.close(self) unless @closed
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
def onopen(&blk)
|
127
|
-
if @opened
|
128
|
-
begin
|
129
|
-
blk.call
|
130
|
-
ensure
|
131
|
-
@opened = false
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
def onmessage(&blk)
|
137
|
-
if @messaged.size > 0
|
138
|
-
begin
|
139
|
-
@messaged.each do |x|
|
140
|
-
blk.call(x.to_s)
|
141
|
-
end
|
142
|
-
ensure
|
143
|
-
@messaged = []
|
144
|
-
end
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
def onclose(&blk)
|
149
|
-
if @closed
|
150
|
-
begin
|
151
|
-
blk.call
|
152
|
-
end
|
153
|
-
end
|
154
|
-
end
|
155
|
-
end
|
156
|
-
end
|
data/opal/inesita/live_reload.rb
DELETED
@@ -1,79 +0,0 @@
|
|
1
|
-
require 'inesita'
|
2
|
-
|
3
|
-
module Inesita
|
4
|
-
WebSocket = JS.global.JS[:WebSocket]
|
5
|
-
Document = JS.global.JS[:document]
|
6
|
-
Head = Document.JS[:head]
|
7
|
-
Window = JS.global
|
8
|
-
|
9
|
-
module Component
|
10
|
-
alias_method :old_mount_to, :mount_to
|
11
|
-
def mount_to(element)
|
12
|
-
Window.JS.addEventListener('inesita:refresh', -> { render! }, false)
|
13
|
-
old_mount_to(element)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
class LiveReload
|
18
|
-
def initialize
|
19
|
-
connect
|
20
|
-
end
|
21
|
-
|
22
|
-
def connect
|
23
|
-
ws = `new WebSocket('ws://0.0.0.0:23654')`
|
24
|
-
ws.JS[:onmessage] = ->(e) { on_file_change(e.JS[:data]) }
|
25
|
-
ws.JS[:onclose] = -> { reconnect }
|
26
|
-
end
|
27
|
-
|
28
|
-
def reconnect
|
29
|
-
JS.setTimeout(-> { connect }, 1000)
|
30
|
-
end
|
31
|
-
|
32
|
-
def on_file_change(filename)
|
33
|
-
prefix, mod, ext = filename.split('|')
|
34
|
-
filename = "#{prefix}/#{mod}.self.#{ext}"
|
35
|
-
case ext
|
36
|
-
when 'js'
|
37
|
-
replace_js(filename, mod)
|
38
|
-
when 'css'
|
39
|
-
replace_css(filename)
|
40
|
-
else
|
41
|
-
fail Error, "Don't know how to reload #{ext} file!"
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def replace_js(filename, mod)
|
46
|
-
s = create_element(:script, type: 'text/javascript', src: filename, onload: lambda do
|
47
|
-
Opal.load(mod)
|
48
|
-
Window.JS.dispatchEvent(`new Event('inesita:refresh')`)
|
49
|
-
end)
|
50
|
-
replace_or_append(s, 'script') { |t| t.JS[:src].match(filename) }
|
51
|
-
end
|
52
|
-
|
53
|
-
def replace_css(filename)
|
54
|
-
s = create_element(:link, rel: 'stylesheet', type: 'text/css', href: filename)
|
55
|
-
replace_or_append(s, 'link') { |t| t.JS[:href].match(filename) }
|
56
|
-
end
|
57
|
-
|
58
|
-
def create_element(name, attrs = {})
|
59
|
-
s = Document.JS.createElement(name)
|
60
|
-
s.JS[:onload] = attrs.delete(:onload)
|
61
|
-
attrs.each do |k, v|
|
62
|
-
s.JS.setAttribute(k, v)
|
63
|
-
end
|
64
|
-
s
|
65
|
-
end
|
66
|
-
|
67
|
-
def replace_or_append(tag, tags, &block)
|
68
|
-
tags = Document.JS.getElementsByTagName(tags)
|
69
|
-
tags.JS[:length].times do |i|
|
70
|
-
next unless block.call(tags.JS.item(i))
|
71
|
-
Head.JS.replaceChild(tag, tags.JS.item(i))
|
72
|
-
return
|
73
|
-
end
|
74
|
-
Head.JS.appendChild(tag)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
Inesita::LiveReload.new
|