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.
@@ -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'
@@ -17,16 +17,16 @@ module Inesita
17
17
 
18
18
  def setup_router(router)
19
19
  if router
20
- fail Error, "Invalid #{router} class, should mixin Inesita::Router" unless router.include?(Inesita::Router)
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) { fail 'Router missing' } }.new
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
- fail Error, "Invalid #{layout} class, should mixin Inesita::Layout" unless layout.include?(Inesita::Layout)
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
- fail Error, 'Router or Layout not found!'
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
- fail Error, "Invalid #{store} class, should mixin Inesita::Store" unless store.include?(Inesita::Store)
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
@@ -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
- fail Error, "Implement #render in #{self.class} component"
11
+ raise Error, "Implement #render in #{self.class} component"
10
12
  end
11
13
 
12
14
  def mount_to(element)
13
- fail Error, "Can't mount #{self.class}, target element not found!" unless element
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.inner_dom = @root_node
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__.length == 1
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.handle_link(params[:href]) } }.merge(params) if params[:href] && @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
- fail Error, "Component is nil in #{self.class} class" if comp.nil?
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
@@ -6,16 +6,17 @@ module Inesita
6
6
 
7
7
  def initialize
8
8
  @routes = Routes.new
9
- @url_params = parse_url_params
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
- fail Error, 'Add #route to your #routes method!' if @routes.routes.empty?
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
- $window.on(:popstate) { render! }
18
- $window.on(:hashchange) { render! }
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 handle_link(url_for(route[:redirect_to])) if route[:redirect_to]
29
- return route
29
+ return go_to(url_for(route[:redirect_to])) if route[:redirect_to]
30
+ return @route = route
30
31
  end
31
- fail Error, "Can't find route for url"
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
- if route = find_route
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 handle_link(path)
48
- $window.history.push(path)
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
- url_query = $window.location.query.to_s
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[key.decode_uri_component] = value.decode_uri_component
59
- end unless url_query.length == 0
60
- params
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) : fail(Error, "Route '#{name}' not found.")
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
- $window.location.path
83
+ Browser.path
79
84
  end
80
85
 
81
86
  def current_url?(name)
@@ -8,7 +8,7 @@ module Inesita
8
8
  end
9
9
 
10
10
  def route(*params, &block)
11
- path = params.first.delete('/')
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
- fail Error, 'Component not exists' unless component
25
- fail Error, "Invalid #{component} class, should mixin Inesita::Component" unless component.include?(Inesita::Component)
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(params_and_regex(path))
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(params_and_regex(path))
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 params_and_regex(path)
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
- if part[0] == ':'
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
@@ -1,8 +1,8 @@
1
1
  module Inesita
2
2
  module Store
3
- def store
4
- self
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
@@ -37,7 +37,7 @@ describe Inesita::Router do
37
37
  end
38
38
 
39
39
  let(:element) do
40
- $document.create_element('div')
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.inner_html).to eq '<h1 class="test">Test</h1>'
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.inner_html).to eq '<h1 class="test"><div>Inner</div></h1>'
54
+ expect(element.JS[:innerHTML]).to eq '<h1 class="test"><div>Inner</div></h1>'
55
55
  end
56
56
  end
@@ -2,4 +2,3 @@ include RSpec
2
2
 
3
3
  require 'virtual-dom'
4
4
  require 'inesita'
5
- require 'browser'
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.3.5
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-03-10 00:00:00.000000000 Z
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.3.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.3.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