inesita 0.3.5 → 0.4.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/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
data/opal/inesita.rb
CHANGED
@@ -2,12 +2,9 @@ require 'opal'
|
|
2
2
|
require 'js'
|
3
3
|
require 'console'
|
4
4
|
|
5
|
-
require 'browser'
|
6
|
-
require 'browser/history'
|
7
|
-
require 'browser/animation_frame'
|
8
|
-
|
9
5
|
require 'virtual_dom'
|
10
6
|
|
7
|
+
require 'inesita/browser'
|
11
8
|
require 'inesita/error'
|
12
9
|
require 'inesita/component_virtual_dom_extension'
|
13
10
|
require 'inesita/component_properties'
|
data/opal/inesita/application.rb
CHANGED
@@ -17,16 +17,16 @@ module Inesita
|
|
17
17
|
|
18
18
|
def setup_router(router)
|
19
19
|
if router
|
20
|
-
|
20
|
+
raise Error, "Invalid #{router} class, should mixin Inesita::Router" unless router.include?(Inesita::Router)
|
21
21
|
@router = router.new
|
22
22
|
else
|
23
|
-
@router = Class.new { define_method(:method_missing) {
|
23
|
+
@router = Class.new { define_method(:method_missing) { raise 'Router missing' } }.new
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
27
|
def setup_layout(layout)
|
28
28
|
if layout
|
29
|
-
|
29
|
+
raise Error, "Invalid #{layout} class, should mixin Inesita::Layout" unless layout.include?(Inesita::Layout)
|
30
30
|
@layout = layout.new
|
31
31
|
end
|
32
32
|
end
|
@@ -37,14 +37,15 @@ module Inesita
|
|
37
37
|
elsif @router
|
38
38
|
@root = @router
|
39
39
|
else
|
40
|
-
|
40
|
+
raise Error, 'Router or Layout not found!'
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
44
|
def setup_store(store)
|
45
45
|
return unless store
|
46
|
-
|
47
|
-
@store = store.new.with_root_component(@root).store
|
46
|
+
raise Error, "Invalid #{store} class, should mixin Inesita::Store" unless store.include?(Inesita::Store)
|
47
|
+
@store = store.new.with_root_component(@root).with_router(@router).store
|
48
|
+
@store.init
|
48
49
|
end
|
49
50
|
end
|
50
51
|
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Inesita
|
2
|
+
module Browser
|
3
|
+
module_function
|
4
|
+
|
5
|
+
Window = JS.global
|
6
|
+
Document = Window.JS[:document]
|
7
|
+
Location = Document.JS[:location]
|
8
|
+
History = Window.JS[:history]
|
9
|
+
AddEventListener = Window.JS[:addEventListener]
|
10
|
+
|
11
|
+
if Native(Window.JS[:requestAnimationFrame])
|
12
|
+
def animation_frame(&block)
|
13
|
+
Window.JS.requestAnimationFrame(block)
|
14
|
+
end
|
15
|
+
else
|
16
|
+
def animation_frame(&block)
|
17
|
+
block.call
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def path
|
22
|
+
Location.JS[:pathname]
|
23
|
+
end
|
24
|
+
|
25
|
+
def query
|
26
|
+
Location.JS[:search]
|
27
|
+
end
|
28
|
+
|
29
|
+
def decode_uri_component(value)
|
30
|
+
JS.decodeURIComponent(value)
|
31
|
+
end
|
32
|
+
|
33
|
+
def push_state(path)
|
34
|
+
History.JS.pushState({}, nil, path)
|
35
|
+
end
|
36
|
+
|
37
|
+
def onpopstate(&block)
|
38
|
+
Window.JS[:onpopstate] = block
|
39
|
+
end
|
40
|
+
|
41
|
+
def hashchange(&block)
|
42
|
+
AddEventListener.call(:hashchange, block)
|
43
|
+
end
|
44
|
+
|
45
|
+
def ready?(&block)
|
46
|
+
AddEventListener.call('load', block)
|
47
|
+
end
|
48
|
+
|
49
|
+
def body
|
50
|
+
Document.JS[:body]
|
51
|
+
end
|
52
|
+
|
53
|
+
def append_child(node, new_node)
|
54
|
+
node = node.to_n unless native?(node)
|
55
|
+
new_node = new_node.to_n unless native?(new_node)
|
56
|
+
node.JS.appendChild(new_node)
|
57
|
+
end
|
58
|
+
|
59
|
+
def query_element(css)
|
60
|
+
Document.JS.querySelector(css)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/opal/inesita/component.rb
CHANGED
@@ -5,17 +5,18 @@ module Inesita
|
|
5
5
|
include ComponentProperties
|
6
6
|
include ComponentVirtualDomExtension
|
7
7
|
|
8
|
+
def init; end
|
9
|
+
|
8
10
|
def render
|
9
|
-
|
11
|
+
raise Error, "Implement #render in #{self.class} component"
|
10
12
|
end
|
11
13
|
|
12
14
|
def mount_to(element)
|
13
|
-
|
15
|
+
raise Error, "Can't mount #{self.class}, target element not found!" unless element
|
14
16
|
@root_component = self
|
15
17
|
@virtual_dom = render_virtual_dom
|
16
18
|
@root_node = VirtualDOM.create(@virtual_dom)
|
17
|
-
element
|
18
|
-
@root_component.call_after_render
|
19
|
+
Browser.append_child(element, @root_node)
|
19
20
|
self
|
20
21
|
end
|
21
22
|
|
@@ -28,36 +29,25 @@ module Inesita
|
|
28
29
|
end
|
29
30
|
|
30
31
|
def render_virtual_dom
|
31
|
-
@after_render_callbacks = []
|
32
|
-
@root_component.add_after_render(method(:after_render)) if respond_to?(:after_render)
|
33
32
|
@cache_component_counter = 0
|
34
33
|
@__virtual_nodes__ = []
|
35
34
|
render
|
36
|
-
if @__virtual_nodes__.
|
35
|
+
if @__virtual_nodes__.one?
|
37
36
|
@__virtual_nodes__.first
|
38
37
|
else
|
39
38
|
VirtualDOM::VirtualNode.new('div', {}, @__virtual_nodes__).to_n
|
40
39
|
end
|
41
40
|
end
|
42
41
|
|
43
|
-
def add_after_render(block)
|
44
|
-
@after_render_callbacks << block
|
45
|
-
end
|
46
|
-
|
47
|
-
def call_after_render
|
48
|
-
@after_render_callbacks.reverse_each(&:call)
|
49
|
-
end
|
50
|
-
|
51
42
|
def update_dom
|
52
43
|
$console.warn "Use 'render!' instead of 'update_dom'"
|
53
44
|
render!
|
54
45
|
end
|
55
46
|
|
56
47
|
def render!
|
57
|
-
animation_frame do
|
48
|
+
Browser.animation_frame do
|
58
49
|
if @root_component
|
59
50
|
@root_component.render_if_root
|
60
|
-
@root_component.call_after_render
|
61
51
|
end
|
62
52
|
end
|
63
53
|
end
|
@@ -68,5 +58,13 @@ module Inesita
|
|
68
58
|
@cache_component_counter += 1
|
69
59
|
@cache_component["#{component}-#{@cache_component_counter}"] || @cache_component["#{component}-#{@cache_component_counter}"] = block.call
|
70
60
|
end
|
61
|
+
|
62
|
+
def hook(mthd)
|
63
|
+
VirtualDOM::Hook.method(method(mthd))
|
64
|
+
end
|
65
|
+
|
66
|
+
def unhook(mthd)
|
67
|
+
VirtualDOM::UnHook.method(method(mthd))
|
68
|
+
end
|
71
69
|
end
|
72
70
|
end
|
@@ -3,19 +3,21 @@ module Inesita
|
|
3
3
|
def self.included(base)
|
4
4
|
base.alias_method :__a, :a
|
5
5
|
base.define_method(:a) do |params, &block|
|
6
|
-
params = { onclick: -> { @router.
|
6
|
+
params = { onclick: -> { @router.go_to(params[:href]) } }.merge(params) if params[:href] && @router
|
7
7
|
__a(params, &block)
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
11
|
def component(comp, opts = {})
|
12
|
-
|
12
|
+
raise Error, "Component is nil in #{self.class} class" if comp.nil?
|
13
13
|
@__virtual_nodes__ ||= []
|
14
14
|
@__virtual_nodes__ << cache_component(comp) do
|
15
|
-
(comp.is_a?(Class) ? comp.new : comp)
|
15
|
+
comp = (comp.is_a?(Class) ? comp.new : comp)
|
16
16
|
.with_root_component(@root_component)
|
17
17
|
.with_router(@router)
|
18
18
|
.with_store(@store)
|
19
|
+
comp.init
|
20
|
+
comp
|
19
21
|
end.with_props(opts[:props] || {}).render_virtual_dom
|
20
22
|
end
|
21
23
|
end
|
data/opal/inesita/router.rb
CHANGED
@@ -6,16 +6,17 @@ module Inesita
|
|
6
6
|
|
7
7
|
def initialize
|
8
8
|
@routes = Routes.new
|
9
|
-
|
10
|
-
fail Error, 'Add #routes method to router!' unless respond_to?(:routes)
|
9
|
+
raise Error, 'Add #routes method to router!' unless respond_to?(:routes)
|
11
10
|
routes
|
12
|
-
|
11
|
+
raise Error, 'Add #route to your #routes method!' if @routes.routes.empty?
|
12
|
+
find_route
|
13
|
+
parse_url_params
|
13
14
|
add_listeners
|
14
15
|
end
|
15
16
|
|
16
17
|
def add_listeners
|
17
|
-
|
18
|
-
|
18
|
+
Browser.onpopstate { find_route; parse_url_params; render! }
|
19
|
+
Browser.hashchange { find_route; parse_url_params; render! }
|
19
20
|
end
|
20
21
|
|
21
22
|
def route(*params, &block)
|
@@ -25,39 +26,39 @@ module Inesita
|
|
25
26
|
def find_route
|
26
27
|
@routes.routes.each do |route|
|
27
28
|
next unless path.match(route[:regex])
|
28
|
-
return
|
29
|
-
return route
|
29
|
+
return go_to(url_for(route[:redirect_to])) if route[:redirect_to]
|
30
|
+
return @route = route
|
30
31
|
end
|
31
|
-
|
32
|
+
raise Error, "Can't find route for url"
|
32
33
|
end
|
33
34
|
|
34
35
|
def find_component(route)
|
35
|
-
params = path.match(route[:regex])
|
36
|
-
@params = @url_params.merge(Hash[route[:params].zip(params[1..-1])])
|
37
36
|
@component_props = route[:component_props]
|
38
37
|
route[:component]
|
39
38
|
end
|
40
39
|
|
41
40
|
def render
|
42
|
-
|
43
|
-
component find_component(route), props: @component_props
|
44
|
-
end
|
41
|
+
component find_component(@route), props: @component_props if @route
|
45
42
|
end
|
46
43
|
|
47
|
-
def
|
48
|
-
|
44
|
+
def go_to(path)
|
45
|
+
Browser.push_state(path)
|
46
|
+
find_route
|
47
|
+
parse_url_params
|
49
48
|
render!
|
50
49
|
false
|
51
50
|
end
|
52
51
|
|
53
52
|
def parse_url_params
|
54
|
-
params =
|
55
|
-
|
56
|
-
url_query[1..-1].split('&').each do |param|
|
53
|
+
@params = compotent_url_params
|
54
|
+
query[1..-1].split('&').each do |param|
|
57
55
|
key, value = param.split('=')
|
58
|
-
params[
|
59
|
-
end unless
|
60
|
-
|
56
|
+
@params[Browser.decode_uri_component(key)] = Browser.decode_uri_component(value)
|
57
|
+
end unless query.empty?
|
58
|
+
end
|
59
|
+
|
60
|
+
def compotent_url_params
|
61
|
+
Hash[@route[:params].zip(path.match(@route[:regex])[1..-1])]
|
61
62
|
end
|
62
63
|
|
63
64
|
def url_for(name, params = nil)
|
@@ -71,11 +72,15 @@ module Inesita
|
|
71
72
|
false
|
72
73
|
end
|
73
74
|
end
|
74
|
-
route ? url_with_params(route, params) :
|
75
|
+
route ? url_with_params(route, params) : raise(Error, "Route '#{name}' not found.")
|
76
|
+
end
|
77
|
+
|
78
|
+
def query
|
79
|
+
Browser.query
|
75
80
|
end
|
76
81
|
|
77
82
|
def path
|
78
|
-
|
83
|
+
Browser.path
|
79
84
|
end
|
80
85
|
|
81
86
|
def current_url?(name)
|
data/opal/inesita/routes.rb
CHANGED
@@ -8,7 +8,7 @@ module Inesita
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def route(*params, &block)
|
11
|
-
path = params.first.
|
11
|
+
path = params.first.gsub(/^\//, '')
|
12
12
|
path = @parent ? "#{@parent}/#{path}" : "/#{path}"
|
13
13
|
|
14
14
|
add_subroutes(path, &block) if block_given?
|
@@ -21,15 +21,15 @@ module Inesita
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def validate_component(component)
|
24
|
-
|
25
|
-
|
24
|
+
raise Error, 'Component not exists' unless component
|
25
|
+
raise Error, "Invalid #{component} class, should mixin Inesita::Component" unless component.include?(Inesita::Component)
|
26
26
|
end
|
27
27
|
|
28
28
|
def add_redirect(path, redirect_to)
|
29
29
|
@routes << {
|
30
30
|
path: path,
|
31
31
|
redirect_to: redirect_to
|
32
|
-
}.merge(
|
32
|
+
}.merge(build_params_and_regex(path))
|
33
33
|
end
|
34
34
|
|
35
35
|
def add_route(name, path, component, component_props)
|
@@ -39,7 +39,7 @@ module Inesita
|
|
39
39
|
component: component,
|
40
40
|
component_props: component_props,
|
41
41
|
name: name || component.to_s.gsub(/(.)([A-Z])/, '\1_\2').downcase
|
42
|
-
}.merge(
|
42
|
+
}.merge(build_params_and_regex(path))
|
43
43
|
end
|
44
44
|
|
45
45
|
def add_subroutes(path, &block)
|
@@ -48,7 +48,7 @@ module Inesita
|
|
48
48
|
@routes += subroutes.routes
|
49
49
|
end
|
50
50
|
|
51
|
-
def
|
51
|
+
def build_params_and_regex(path)
|
52
52
|
regex = ['^']
|
53
53
|
params = []
|
54
54
|
parts = path.split('/')
|
@@ -56,9 +56,14 @@ module Inesita
|
|
56
56
|
parts.each do |part|
|
57
57
|
next if part.empty?
|
58
58
|
regex << '\/'
|
59
|
-
|
59
|
+
case part[0]
|
60
|
+
when ':'
|
60
61
|
params << part[1..-1]
|
61
62
|
regex << '([^\/]+)'
|
63
|
+
when '*'
|
64
|
+
params << part[1..-1]
|
65
|
+
regex << '(.*)'
|
66
|
+
break
|
62
67
|
else
|
63
68
|
regex << part
|
64
69
|
end
|
data/opal/inesita/store.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
module Inesita
|
2
2
|
module Store
|
3
|
-
|
4
|
-
|
5
|
-
end
|
3
|
+
|
4
|
+
def init; end
|
5
|
+
def store; self end
|
6
6
|
|
7
7
|
def update_dom
|
8
8
|
$console.warn "Use 'render!' instead of 'update_dom'"
|
@@ -18,5 +18,11 @@ module Inesita
|
|
18
18
|
@root_component = component
|
19
19
|
self
|
20
20
|
end
|
21
|
+
|
22
|
+
attr_reader :router
|
23
|
+
def with_router(router)
|
24
|
+
@router = router
|
25
|
+
self
|
26
|
+
end
|
21
27
|
end
|
22
28
|
end
|
data/spec/opal/component_spec.rb
CHANGED
@@ -37,7 +37,7 @@ describe Inesita::Router do
|
|
37
37
|
end
|
38
38
|
|
39
39
|
let(:element) do
|
40
|
-
|
40
|
+
Inesita::Browser::Document.JS.createElement('div')
|
41
41
|
end
|
42
42
|
|
43
43
|
it 'should fail when no #render method' do
|
@@ -46,11 +46,11 @@ describe Inesita::Router do
|
|
46
46
|
|
47
47
|
it 'should render html' do
|
48
48
|
component.new.mount_to(element)
|
49
|
-
expect(element.
|
49
|
+
expect(element.JS[:innerHTML]).to eq '<h1 class="test">Test</h1>'
|
50
50
|
end
|
51
51
|
|
52
52
|
it 'should render html with nested components' do
|
53
53
|
nested_component.new.mount_to(element)
|
54
|
-
expect(element.
|
54
|
+
expect(element.JS[:innerHTML]).to eq '<h1 class="test"><div>Inner</div></h1>'
|
55
55
|
end
|
56
56
|
end
|
data/spec/opal/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: inesita
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michał Kalbarczyk
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-05-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: opal
|
@@ -24,34 +24,20 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0.9'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: opal-browser
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - "~>"
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '0.2'
|
34
|
-
type: :runtime
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - "~>"
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '0.2'
|
41
27
|
- !ruby/object:Gem::Dependency
|
42
28
|
name: opal-virtual-dom
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|
44
30
|
requirements:
|
45
31
|
- - "~>"
|
46
32
|
- !ruby/object:Gem::Version
|
47
|
-
version: 0.
|
33
|
+
version: 0.4.0
|
48
34
|
type: :runtime
|
49
35
|
prerelease: false
|
50
36
|
version_requirements: !ruby/object:Gem::Requirement
|
51
37
|
requirements:
|
52
38
|
- - "~>"
|
53
39
|
- !ruby/object:Gem::Version
|
54
|
-
version: 0.
|
40
|
+
version: 0.4.0
|
55
41
|
- !ruby/object:Gem::Dependency
|
56
42
|
name: slim
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -122,20 +108,6 @@ dependencies:
|
|
122
108
|
- - "~>"
|
123
109
|
- !ruby/object:Gem::Version
|
124
110
|
version: '3.0'
|
125
|
-
- !ruby/object:Gem::Dependency
|
126
|
-
name: websocket
|
127
|
-
requirement: !ruby/object:Gem::Requirement
|
128
|
-
requirements:
|
129
|
-
- - "~>"
|
130
|
-
- !ruby/object:Gem::Version
|
131
|
-
version: '1.0'
|
132
|
-
type: :runtime
|
133
|
-
prerelease: false
|
134
|
-
version_requirements: !ruby/object:Gem::Requirement
|
135
|
-
requirements:
|
136
|
-
- - "~>"
|
137
|
-
- !ruby/object:Gem::Version
|
138
|
-
version: '1.0'
|
139
111
|
description: Frontent web framework for Opal
|
140
112
|
email: fazibear@gmail.com
|
141
113
|
executables:
|
@@ -153,7 +125,6 @@ files:
|
|
153
125
|
- bin/inesita
|
154
126
|
- inesita.gemspec
|
155
127
|
- lib/inesita.rb
|
156
|
-
- lib/inesita/app_files_listener.rb
|
157
128
|
- lib/inesita/cli.rb
|
158
129
|
- lib/inesita/cli/build.rb
|
159
130
|
- lib/inesita/cli/new.rb
|
@@ -174,19 +145,17 @@ files:
|
|
174
145
|
- lib/inesita/cli/template/static/inesita-rb.png
|
175
146
|
- lib/inesita/cli/watch.rb
|
176
147
|
- lib/inesita/config.rb
|
177
|
-
- lib/inesita/live_reload.rb
|
178
148
|
- lib/inesita/minify.rb
|
179
149
|
- lib/inesita/server.rb
|
180
|
-
- lib/rubame.rb
|
181
150
|
- opal/inesita.rb
|
182
151
|
- opal/inesita/application.rb
|
152
|
+
- opal/inesita/browser.rb
|
183
153
|
- opal/inesita/component.rb
|
184
154
|
- opal/inesita/component_helpers.rb
|
185
155
|
- opal/inesita/component_properties.rb
|
186
156
|
- opal/inesita/component_virtual_dom_extension.rb
|
187
157
|
- opal/inesita/error.rb
|
188
158
|
- opal/inesita/layout.rb
|
189
|
-
- opal/inesita/live_reload.rb
|
190
159
|
- opal/inesita/router.rb
|
191
160
|
- opal/inesita/routes.rb
|
192
161
|
- opal/inesita/store.rb
|