flok 0.0.34 → 0.0.35
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/app/kern/controller.js +5 -0
- data/docs/mod/intercept.md +26 -0
- data/lib/flok.rb +1 -0
- data/lib/flok/transition_compiler.rb +292 -0
- data/lib/flok/transition_compiler_templates/ttable.js.erb +0 -0
- data/lib/flok/version.rb +1 -1
- data/spec/etc/transition_compiler/trans0.rb +8 -0
- data/spec/etc/transition_complier_spec.rb +32 -0
- data/spec/kern/controller_spec.rb +21 -1
- metadata +9 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8c530893c64f57d4267ae2edd101adfe456954c2
|
4
|
+
data.tar.gz: a603052bb1bb83292214fc0b1fbcf386655f5987
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f21e469c145f3995ae115615def139675882cda69096f40eff514f76921badd257b21de65ed5b17321f70e020e134c53b62167d5ee3beb875346e2a8b0c8c18a
|
7
|
+
data.tar.gz: b8ff637ba02cb67f73c00f755e4a945f064870cab108471f74463820420518cbdea171bb855e1ba624f4e2f6fcd8dca339587615a80fc3967b62c60e12a79a50
|
data/app/kern/controller.js
CHANGED
@@ -20,6 +20,11 @@ function _embed(vc_name, sp, context, event_gw) {
|
|
20
20
|
var cte = ctable[vc_name];
|
21
21
|
|
22
22
|
//Find the root view name
|
23
|
+
<% if @debug %>
|
24
|
+
if (cte === undefined) {
|
25
|
+
throw "Tried to embed a flok controller named: '" + vc_name + "' but you have not created that controller yet, add controller :" + vc_name + "do ...";
|
26
|
+
}
|
27
|
+
<% end %>
|
23
28
|
var vname = cte.root_view;
|
24
29
|
|
25
30
|
//Get spot names
|
@@ -0,0 +1,26 @@
|
|
1
|
+
#Intercept
|
2
|
+
The intercept module supports the animation system by allowing you to hijack an action change for a particular view controller.
|
3
|
+
|
4
|
+
Typical Example:
|
5
|
+
```js
|
6
|
+
intercept("my_controller", "start_action", "to_action", function($sel) {
|
7
|
+
$sel.find("#content").css("left", "40%");
|
8
|
+
$sel.find("#tab-bar").css("left", "0%");
|
9
|
+
|
10
|
+
cd("../*/")
|
11
|
+
});
|
12
|
+
```
|
13
|
+
|
14
|
+
The actual code used to define an interceptor function is dependent on the platform.
|
15
|
+
|
16
|
+
An interceptor is defined like as follows:
|
17
|
+
```
|
18
|
+
transition "blah" do
|
19
|
+
#Define the context
|
20
|
+
controller "blah"
|
21
|
+
when "a" => "b"
|
22
|
+
|
23
|
+
path :home, "../../0"
|
24
|
+
path :about, "./1"
|
25
|
+
end
|
26
|
+
```
|
data/lib/flok.rb
CHANGED
@@ -0,0 +1,292 @@
|
|
1
|
+
#Compile a controller ruby file into a javascript string
|
2
|
+
|
3
|
+
require 'erb'
|
4
|
+
module Flok
|
5
|
+
module TransitionCompiler
|
6
|
+
#Compile a ruby file containing flok controller definitions (from the transition)
|
7
|
+
def self.compile rb_src
|
8
|
+
#Execute code in this context, the context will hold all the information
|
9
|
+
#that is used to then generate code
|
10
|
+
context = TransitionCompilerContext.new
|
11
|
+
context.instance_eval(rb_src, __FILE__, __LINE__)
|
12
|
+
|
13
|
+
@src = ""
|
14
|
+
ctable_erb = File.read File.join(File.dirname(__FILE__), "./transition_compiler_templates/ttable.js.erb")
|
15
|
+
ctable_renderer = ERB.new(ctable_erb)
|
16
|
+
@src << ctable_renderer.result(context.get_binding)
|
17
|
+
|
18
|
+
#puts @src
|
19
|
+
|
20
|
+
return @src
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
#Compiler executes all rb code inside this context
|
26
|
+
module Flok
|
27
|
+
class TransitionCompilerContext
|
28
|
+
attr_accessor :controllers, :actions, :ons
|
29
|
+
|
30
|
+
def initialize
|
31
|
+
@controllers = []
|
32
|
+
@actions = []
|
33
|
+
@ons = []
|
34
|
+
end
|
35
|
+
|
36
|
+
def get_binding
|
37
|
+
return binding
|
38
|
+
end
|
39
|
+
|
40
|
+
def transition name, &block
|
41
|
+
end
|
42
|
+
|
43
|
+
def action controller, name, &block
|
44
|
+
@actions << TransitionCompilerAction.new(controller, name, self, &block)
|
45
|
+
end
|
46
|
+
|
47
|
+
def on controller_name, action_name, name, &block
|
48
|
+
end
|
49
|
+
|
50
|
+
def actions_for_controller controller_name
|
51
|
+
return @actions.select{|e| e.controller.name == controller_name}
|
52
|
+
end
|
53
|
+
|
54
|
+
def spots_for_controller controller_name
|
55
|
+
return @controllers.detect{|e| e.name == controller_name}.spots
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
#Event handler inside an action
|
60
|
+
class TransitionCompilerOn
|
61
|
+
attr_accessor :controller_name, :action_name, :name
|
62
|
+
end
|
63
|
+
|
64
|
+
class TransitionCompilerAction
|
65
|
+
attr_accessor :controller, :name, :on_entry_src, :ons
|
66
|
+
|
67
|
+
def initialize controller, name, ctx, &block
|
68
|
+
@controller = controller
|
69
|
+
@name = name
|
70
|
+
@ctx = ctx
|
71
|
+
@ons = [] #Event handlers
|
72
|
+
|
73
|
+
self.instance_eval(&block)
|
74
|
+
end
|
75
|
+
|
76
|
+
def on_entry js_src
|
77
|
+
#returns a string
|
78
|
+
@on_entry_src = macro(js_src)
|
79
|
+
end
|
80
|
+
|
81
|
+
def on name, js_src
|
82
|
+
@ons << {:name => name, :src => macro(js_src)}
|
83
|
+
end
|
84
|
+
|
85
|
+
def macro js_src
|
86
|
+
lines = js_src.split("\n").map do |line|
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
return lines.join("\n")
|
91
|
+
end
|
92
|
+
|
93
|
+
def macro text
|
94
|
+
out = StringIO.new
|
95
|
+
|
96
|
+
text.split("\n").each do |l|
|
97
|
+
#EMBED(vc_name, spot_name, context) macro
|
98
|
+
if l =~ /Embed/
|
99
|
+
l.strip!
|
100
|
+
l.gsub!(/Embed\(/, "")
|
101
|
+
l.gsub! /\)$/, ""
|
102
|
+
l.gsub! /\);$/, ""
|
103
|
+
o = l.split(",").map{|e| e.strip}
|
104
|
+
|
105
|
+
vc_name = o.shift.gsub(/"/, "")
|
106
|
+
spot_name = o.shift.gsub(/"/, "")
|
107
|
+
context = o.shift
|
108
|
+
|
109
|
+
#Get the spot
|
110
|
+
spot_index = @controller.spots.index(spot_name)
|
111
|
+
raise "controller #{@controller.name.inspect} attempted to embed #{spot_name.inspect} inside #{@name.inspect}, but #{spot_name.inspect} was not defined in 'spots' (#{@controller.spots.inspect})" unless spot_index
|
112
|
+
|
113
|
+
#Calculate spot index as an offset from the base address using the index of the spot in the spots
|
114
|
+
#address offset
|
115
|
+
res = %{
|
116
|
+
|
117
|
+
var ptr = _embed("#{vc_name}", __base__+#{spot_index}+1, #{context}, __base__);
|
118
|
+
__info__.embeds[#{spot_index-1}].push(ptr);
|
119
|
+
}
|
120
|
+
out.puts res
|
121
|
+
#Send(event_name, info)
|
122
|
+
elsif l =~ /Send/
|
123
|
+
l.strip!
|
124
|
+
l.gsub!(/Send\(/, "")
|
125
|
+
l.gsub! /\)$/, ""
|
126
|
+
l.gsub! /\);$/, ""
|
127
|
+
o = l.split(",").map{|e| e.strip}
|
128
|
+
|
129
|
+
event_name = o.shift.gsub(/"/, "")
|
130
|
+
info = o.shift
|
131
|
+
|
132
|
+
out << %{
|
133
|
+
main_q.push([3, "if_event", __base__, "#{event_name}", #{info}])
|
134
|
+
}
|
135
|
+
#Raise(event_name, info)
|
136
|
+
elsif l =~ /Raise/
|
137
|
+
l.strip!
|
138
|
+
l.gsub!(/Raise\(/, "")
|
139
|
+
l.gsub! /\)$/, ""
|
140
|
+
l.gsub! /\);$/, ""
|
141
|
+
o = l.split(",").map{|e| e.strip}
|
142
|
+
|
143
|
+
event_name = o.shift
|
144
|
+
info = o.shift
|
145
|
+
|
146
|
+
out << %{
|
147
|
+
int_event(__info__.event_gw, #{event_name}, #{info});
|
148
|
+
}
|
149
|
+
#Lower(spot_name, event_name, info)
|
150
|
+
elsif l =~ /Lower/
|
151
|
+
l.strip!
|
152
|
+
l.gsub!(/Lower\(/, "")
|
153
|
+
l.gsub! /\)$/, ""
|
154
|
+
l.gsub! /\);$/, ""
|
155
|
+
o = l.split(",").map{|e| e.strip}
|
156
|
+
|
157
|
+
spot_name = o.shift.gsub(/"/, "")
|
158
|
+
event_name = o.shift
|
159
|
+
info = o.shift
|
160
|
+
|
161
|
+
#Get the spot
|
162
|
+
spot_index = @controller.spots.index(spot_name)
|
163
|
+
raise "controller #{@controller.name.inspect} attempted to lower message to #{spot_name.inspect} inside #{@name.inspect}, but #{spot_name.inspect} was not defined in 'spots' (#{@controller.spots.inspect})" unless spot_index
|
164
|
+
|
165
|
+
#Forward an event to the appropriate spot
|
166
|
+
out << %{
|
167
|
+
|
168
|
+
var vcs = __info__.embeds[#{spot_index-1}];
|
169
|
+
for (var i = 0; i < vcs.length; ++i) {
|
170
|
+
int_event(vcs[i], #{event_name}, #{info});
|
171
|
+
}
|
172
|
+
}
|
173
|
+
|
174
|
+
#GOTO(action_name)
|
175
|
+
elsif l =~ /Goto/
|
176
|
+
l.strip!
|
177
|
+
l.gsub!(/Goto\(/, "")
|
178
|
+
l.gsub! /\)$/, ""
|
179
|
+
l.gsub! /\);$/, ""
|
180
|
+
o = l.split(",").map{|e| e.strip}
|
181
|
+
|
182
|
+
action_name = o.shift.gsub(/"/, "")
|
183
|
+
|
184
|
+
#Switch the actions, reset embeds, and call on_entry
|
185
|
+
res = %{
|
186
|
+
var old_action = __info__.action;
|
187
|
+
__info__.action = "#{action_name}";
|
188
|
+
|
189
|
+
//Remove all views
|
190
|
+
var embeds = __info__.embeds;
|
191
|
+
for (var i = 0; i < __info__.embeds.length; ++i) {
|
192
|
+
for (var j = 0; j < __info__.embeds[i].length; ++j) {
|
193
|
+
//Free +1 because that will be the 'main' view
|
194
|
+
main_q.push([1, "if_free_view", embeds[i][j]+1]);
|
195
|
+
|
196
|
+
<% if @debug %>
|
197
|
+
var vp = embeds[i][j]+1;
|
198
|
+
//First locate spot this view belongs to in reverse hash
|
199
|
+
var spot = debug_ui_view_to_spot[vp];
|
200
|
+
|
201
|
+
//Find it's index in the spot
|
202
|
+
var idx = debug_ui_spot_to_views[spot].indexOf(vp);
|
203
|
+
|
204
|
+
//Remove it from the spot => [view]
|
205
|
+
debug_ui_spot_to_views[spot].splice(idx, 1);
|
206
|
+
|
207
|
+
//Remove it from the reverse hash
|
208
|
+
delete debug_ui_view_to_spot[vp];
|
209
|
+
<% end %>
|
210
|
+
}
|
211
|
+
}
|
212
|
+
|
213
|
+
//Prep embeds array, embeds[0] refers to the spot bp+2 (bp is vc, bp+1 is main)
|
214
|
+
__info__.embeds = [];
|
215
|
+
for (var i = 1; i < #{@controller.spots.count}; ++i) {
|
216
|
+
__info__.embeds.push([]);
|
217
|
+
}
|
218
|
+
|
219
|
+
//Call on_entry for the new action via the singleton on_entry
|
220
|
+
//located in ctable
|
221
|
+
__info__.cte.actions[__info__.action].on_entry(__base__)
|
222
|
+
|
223
|
+
//Send off event for action change
|
224
|
+
main_q.push([3, "if_event", __base__, "action", {
|
225
|
+
from: old_action,
|
226
|
+
to: "#{action_name}"
|
227
|
+
}]);
|
228
|
+
}
|
229
|
+
out.puts res
|
230
|
+
#Request(service_name, payload, event_name_cb)
|
231
|
+
elsif l =~ /Request/
|
232
|
+
l.strip!
|
233
|
+
l.gsub!(/Request\(/, "")
|
234
|
+
l.gsub! /\)$/, ""
|
235
|
+
l.gsub! /\);$/, ""
|
236
|
+
o = l.split(",").map{|e| e.strip}
|
237
|
+
|
238
|
+
name = o.shift.gsub(/"/, "")
|
239
|
+
info = o.shift.gsub(/"/, "")
|
240
|
+
event_name = o.shift
|
241
|
+
|
242
|
+
out << %{
|
243
|
+
service_#{name}_req(#{info}, __base__, #{event_name});
|
244
|
+
}
|
245
|
+
else
|
246
|
+
out.puts l
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
return out.string
|
251
|
+
end
|
252
|
+
|
253
|
+
#You can def things in controller and use them as macros inside actions
|
254
|
+
#But these defs. live in the TransitionCompilerController instance and we need
|
255
|
+
#to delegate these calls to the controller that are not available in the action
|
256
|
+
def method_missing method, *args, &block
|
257
|
+
if macro = @controller.macros[method]
|
258
|
+
#Call the macro in our context
|
259
|
+
self.instance_eval(¯o)
|
260
|
+
else
|
261
|
+
raise "No macro found named: #{method}"
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
class TransitionCompilerController
|
267
|
+
attr_accessor :name, :spots, :macros
|
268
|
+
def initialize name, ctx, &block
|
269
|
+
@name = name
|
270
|
+
@ctx = ctx
|
271
|
+
@spots = ['main']
|
272
|
+
@macros = {}
|
273
|
+
|
274
|
+
self.instance_eval(&block)
|
275
|
+
end
|
276
|
+
|
277
|
+
#Create an action macro
|
278
|
+
def macro name, &block
|
279
|
+
@macros[name] = block
|
280
|
+
end
|
281
|
+
|
282
|
+
#Names of spots
|
283
|
+
def spots *spots
|
284
|
+
@spots += spots
|
285
|
+
end
|
286
|
+
|
287
|
+
#Pass through action
|
288
|
+
def action name, &block
|
289
|
+
@ctx.action self, name, &block
|
290
|
+
end
|
291
|
+
end
|
292
|
+
end
|
File without changes
|
data/lib/flok/version.rb
CHANGED
@@ -0,0 +1,32 @@
|
|
1
|
+
#Load all the test files in ./user_compiler/*.js
|
2
|
+
|
3
|
+
Dir.chdir File.join File.dirname(__FILE__), '../../'
|
4
|
+
require './lib/flok'
|
5
|
+
|
6
|
+
#Testing the compilation of controller/action user files into javascript counterparts
|
7
|
+
RSpec.describe "Transition compiler" do
|
8
|
+
#Return a v8 instance of a compiled js file
|
9
|
+
def compile fn
|
10
|
+
compiler = Flok::TransitionCompiler
|
11
|
+
js_src(fn)
|
12
|
+
js_res = compiler.compile(js_src(fn))
|
13
|
+
ctx = V8::Context.new
|
14
|
+
ctx.eval js_res
|
15
|
+
ctx
|
16
|
+
end
|
17
|
+
|
18
|
+
#Get the source for a file in ./user_compiler/*.rb
|
19
|
+
def js_src fn
|
20
|
+
Dir.chdir File.join(File.dirname(__FILE__), "transition_compiler") do
|
21
|
+
return File.read(fn+'.rb')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
it "Can load the ruby module" do
|
26
|
+
compiler = Flok::TransitionCompiler
|
27
|
+
end
|
28
|
+
|
29
|
+
it "Can compile a controller" do
|
30
|
+
ctx = compile "trans0"
|
31
|
+
end
|
32
|
+
end
|
@@ -9,7 +9,7 @@ require './spec/lib/rspec_extensions.rb'
|
|
9
9
|
RSpec.describe "kern:controller_spec" do
|
10
10
|
include_context "kern"
|
11
11
|
|
12
|
-
#Can initialize a controller via embed and have the correct if_dispatch messages
|
12
|
+
#Can initialize a controller via embed and have the correct if_dispatch messages
|
13
13
|
it "Can initiate a controller via _embed" do
|
14
14
|
#Compile the controller
|
15
15
|
ctx = flok_new_user File.read('./spec/kern/assets/controller0.rb')
|
@@ -54,6 +54,26 @@ RSpec.describe "kern:controller_spec" do
|
|
54
54
|
@driver.mexpect("if_event", [base, "action", {"from" => nil, "to" => "my_action"}])
|
55
55
|
end
|
56
56
|
|
57
|
+
it "Does raise a sensible error if a controller does not exist" do
|
58
|
+
#Compile the controller
|
59
|
+
ctx = flok_new_user File.read('./spec/kern/assets/controller0.rb')
|
60
|
+
|
61
|
+
did_error = false
|
62
|
+
#Run the embed function
|
63
|
+
begin
|
64
|
+
secret = SecureRandom.hex
|
65
|
+
ctx.eval %{
|
66
|
+
//Call embed on main root view, should fail
|
67
|
+
base = _embed("my_non_existant_controller", 0, {secret: "#{secret}"}, null);
|
68
|
+
}
|
69
|
+
rescue V8::Error => e
|
70
|
+
expect(e.message).to include("my_non_existant_controller")
|
71
|
+
did_error = true
|
72
|
+
end
|
73
|
+
|
74
|
+
expect(did_error).to eq(true)
|
75
|
+
end
|
76
|
+
|
57
77
|
#Can initialize a controller via embed and the sub-controller has the correct info
|
58
78
|
it "Can initiate a controller via _embed" do
|
59
79
|
#Compile the controller
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flok
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.35
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- seo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-06-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: execjs
|
@@ -323,6 +323,7 @@ files:
|
|
323
323
|
- docs/mod/debug.md
|
324
324
|
- docs/mod/debug/dump_ui.md
|
325
325
|
- docs/mod/event.md
|
326
|
+
- docs/mod/intercept.md
|
326
327
|
- docs/mod/net.md
|
327
328
|
- docs/mod/persist.md
|
328
329
|
- docs/mod/sockio.md
|
@@ -348,6 +349,8 @@ files:
|
|
348
349
|
- lib/flok/project_template/app/controllers/controller.rb
|
349
350
|
- lib/flok/service_compiler_templates/services.js.erb
|
350
351
|
- lib/flok/services_compiler.rb
|
352
|
+
- lib/flok/transition_compiler.rb
|
353
|
+
- lib/flok/transition_compiler_templates/ttable.js.erb
|
351
354
|
- lib/flok/user_compiler.rb
|
352
355
|
- lib/flok/user_compiler_templates/ctable.js.erb
|
353
356
|
- lib/flok/utilities.rb
|
@@ -366,6 +369,8 @@ files:
|
|
366
369
|
- spec/etc/macro_spec.rb
|
367
370
|
- spec/etc/service_compiler/service0.rb
|
368
371
|
- spec/etc/services_compiler_spec.rb
|
372
|
+
- spec/etc/transition_compiler/trans0.rb
|
373
|
+
- spec/etc/transition_complier_spec.rb
|
369
374
|
- spec/etc/user_compiler/controller0.rb
|
370
375
|
- spec/etc/user_compiler_spec.rb
|
371
376
|
- spec/iface/driver/assets/debug_socket_server.js
|
@@ -1159,6 +1164,8 @@ test_files:
|
|
1159
1164
|
- spec/etc/macro_spec.rb
|
1160
1165
|
- spec/etc/service_compiler/service0.rb
|
1161
1166
|
- spec/etc/services_compiler_spec.rb
|
1167
|
+
- spec/etc/transition_compiler/trans0.rb
|
1168
|
+
- spec/etc/transition_complier_spec.rb
|
1162
1169
|
- spec/etc/user_compiler/controller0.rb
|
1163
1170
|
- spec/etc/user_compiler_spec.rb
|
1164
1171
|
- spec/iface/driver/assets/debug_socket_server.js
|