ruta 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +61 -0
- data/.travis.yml +4 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +39 -0
- data/LICENSE.txt +21 -0
- data/README.md +188 -0
- data/Rakefile +1 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/lib/ruta/context.rb +153 -0
- data/lib/ruta/handler.rb +55 -0
- data/lib/ruta/history.rb +106 -0
- data/lib/ruta/route.rb +139 -0
- data/lib/ruta/router.rb +128 -0
- data/lib/ruta/version.rb +3 -0
- data/lib/ruta.rb +62 -0
- data/ruta.gemspec +27 -0
- metadata +121 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6a8777ca0158cf75be951622603e8213369e4d41
|
4
|
+
data.tar.gz: fa3f3d3ce7a1713c25c9928b1493a5a4ed1e7299
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ffcd6159486425e1d7f7d827d30fc5767dab0e5a4d9a1ddb8e151f00cc2f259f503f07568d957690c8970ffaed9a97bc6f49dbc53a92dec366f55825e239214f
|
7
|
+
data.tar.gz: acd9e9a34d23d88e0cb44bbd525c0917ef50773d6c59e07035855d0e4bbe7817e9f4c17293ff367a4524fdf690491f4e8e50f3418c716ee3005823cce69377d6
|
data/.gitignore
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
# Compiled source #
|
2
|
+
###################
|
3
|
+
*target
|
4
|
+
*.war
|
5
|
+
*.ear
|
6
|
+
*.com
|
7
|
+
*.class
|
8
|
+
*.dll
|
9
|
+
*.exe
|
10
|
+
*.o
|
11
|
+
*.so
|
12
|
+
|
13
|
+
# Packages #
|
14
|
+
############
|
15
|
+
# it's better to unpack these files and commit the raw source
|
16
|
+
# git has its own built in compression methods
|
17
|
+
*.7z
|
18
|
+
*.dmg
|
19
|
+
*.gz
|
20
|
+
*.iso
|
21
|
+
*.jar
|
22
|
+
*.rar
|
23
|
+
*.tar
|
24
|
+
*.zip
|
25
|
+
*.gem
|
26
|
+
|
27
|
+
# Logs and databases #
|
28
|
+
######################
|
29
|
+
*.log
|
30
|
+
*.sql
|
31
|
+
*.sqlite
|
32
|
+
|
33
|
+
# OS generated files #
|
34
|
+
######################
|
35
|
+
**/.DS_Store
|
36
|
+
**/.DS_Store?
|
37
|
+
**/._*
|
38
|
+
**/.Spotlight-V100
|
39
|
+
**/.Trashes
|
40
|
+
**/ehthumbs.db
|
41
|
+
**/Thumbs.db
|
42
|
+
**/desktop.ini
|
43
|
+
|
44
|
+
# text/IDE editor generated files #
|
45
|
+
###################################
|
46
|
+
**/*~
|
47
|
+
**/*#
|
48
|
+
**/*.pyo
|
49
|
+
**/*.pyc
|
50
|
+
**/*.bak
|
51
|
+
**/*.swp
|
52
|
+
**/.idea
|
53
|
+
|
54
|
+
# misc files #
|
55
|
+
######################
|
56
|
+
#any supporting credentials used during testings goes in a .creds file but is loaded like any other ruby file
|
57
|
+
**/*.creds
|
58
|
+
#sass cache folder
|
59
|
+
.sass-cache
|
60
|
+
#files generated by git diff
|
61
|
+
**/.orig
|
data/.travis.yml
ADDED
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# Contributor Code of Conduct
|
2
|
+
|
3
|
+
As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
|
4
|
+
|
5
|
+
We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion.
|
6
|
+
|
7
|
+
Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
|
8
|
+
|
9
|
+
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
|
10
|
+
|
11
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
|
12
|
+
|
13
|
+
This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
ruta (0.1.0)
|
5
|
+
opal (~> 0.8)
|
6
|
+
opal-browser (~> 0.2)
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
concurrent-ruby (1.0.0)
|
12
|
+
hike (1.2.3)
|
13
|
+
opal (0.8.1)
|
14
|
+
hike (~> 1.2)
|
15
|
+
sourcemap (~> 0.1.0)
|
16
|
+
sprockets (~> 3.1)
|
17
|
+
tilt (>= 1.4)
|
18
|
+
opal-browser (0.2.0)
|
19
|
+
opal
|
20
|
+
paggio
|
21
|
+
paggio (0.2.5)
|
22
|
+
rack (1.6.4)
|
23
|
+
rake (10.4.2)
|
24
|
+
sourcemap (0.1.1)
|
25
|
+
sprockets (3.5.2)
|
26
|
+
concurrent-ruby (~> 1.0)
|
27
|
+
rack (> 1, < 3)
|
28
|
+
tilt (2.0.1)
|
29
|
+
|
30
|
+
PLATFORMS
|
31
|
+
ruby
|
32
|
+
|
33
|
+
DEPENDENCIES
|
34
|
+
bundler (~> 1.10)
|
35
|
+
rake (~> 10.0)
|
36
|
+
ruta!
|
37
|
+
|
38
|
+
BUNDLED WITH
|
39
|
+
1.10.6
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Martin Becker
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,188 @@
|
|
1
|
+
# Ruta
|
2
|
+
|
3
|
+
## Installation
|
4
|
+
|
5
|
+
Add this line to your application's Gemfile:
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
gem 'ruta'
|
9
|
+
```
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install ruta
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
Making use of this router is pretty simple.
|
22
|
+
|
23
|
+
###Contexts
|
24
|
+
|
25
|
+
The first thing to do is to define your contexts.
|
26
|
+
|
27
|
+
A context is a composition of on screen component containers, routes and handlers.
|
28
|
+
|
29
|
+
You can even place another context under a context as a sub-context
|
30
|
+
|
31
|
+
`component` is used to define a container, you give it a name and then a block and inside of which you
|
32
|
+
place a renderable component.
|
33
|
+
|
34
|
+
you can also use `sub_context` to mount a sub-context at this position, first you give it a name then
|
35
|
+
a reference to the context you wish to place here.
|
36
|
+
|
37
|
+
This initial composition is used to as the default settings for when the context is first rendered
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
Ruta::Context.define :main do
|
41
|
+
component :header do
|
42
|
+
Header
|
43
|
+
end
|
44
|
+
|
45
|
+
sub_context :info, :info_view
|
46
|
+
|
47
|
+
component :footer do
|
48
|
+
Footer
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
Ruta::Context.define :info_view do
|
54
|
+
component :hero do
|
55
|
+
Hero_Image
|
56
|
+
end
|
57
|
+
|
58
|
+
component :scroller do
|
59
|
+
Info_Scroller
|
60
|
+
end
|
61
|
+
|
62
|
+
component :buttons do
|
63
|
+
Buttons
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
Ruta::Context.define :sign_up do
|
68
|
+
component :sign_up_form do
|
69
|
+
Sign_Up_Form
|
70
|
+
end
|
71
|
+
end
|
72
|
+
```
|
73
|
+
|
74
|
+
###Handlers
|
75
|
+
|
76
|
+
Next you should define some handlers, not every component needs a handler but every component has one
|
77
|
+
needs to match names with a corresponding handler.
|
78
|
+
|
79
|
+
you use the `handle` method to define a handler and you pass into it the name of the element you want this
|
80
|
+
handler to drive.
|
81
|
+
|
82
|
+
The handler has two variables passed to it:
|
83
|
+
|
84
|
+
1. `params` a hash containing the named params of the route
|
85
|
+
2. `url` a string containing the url of the route being passed to the handler
|
86
|
+
|
87
|
+
The handler must return a renderable component.
|
88
|
+
|
89
|
+
```ruby
|
90
|
+
Ruta::Handlers.define_for :main do
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
Ruta::Handlers.define_for :info_view do
|
95
|
+
handle :scroller do |params,url|
|
96
|
+
Info_Scroller.render(page: params[:switch_to])
|
97
|
+
end
|
98
|
+
|
99
|
+
handle :buttons do |params,url|
|
100
|
+
Buttons.render(selected: params[:switch_to])
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
Ruta::Handlers.define_for :sign_up do
|
105
|
+
|
106
|
+
end
|
107
|
+
```
|
108
|
+
|
109
|
+
###Routes
|
110
|
+
|
111
|
+
The last thing to define before your app is ready is the routes that will activate the correct handlers to
|
112
|
+
drive onscreen components.
|
113
|
+
|
114
|
+
Roots that drive on screen components should always be mounted to a context.
|
115
|
+
You can state the context using `for_context` then pass in the context you wish to define routes for.
|
116
|
+
whilst you can place context's within each other this doesn't actually do anything beyond aesthetics, but
|
117
|
+
it's planned that you can mount contexts to routes
|
118
|
+
|
119
|
+
You map a route by using the `map` command then pass a unique reference (to that context) for the route,
|
120
|
+
the route you want to match against and then the driver, one or more handlers; remember handlers are
|
121
|
+
executed in the order specified. You can also provide a context that the route will activate.
|
122
|
+
|
123
|
+
To set the initial context that is presented use `root_to` then provide the context you want to be rendered first
|
124
|
+
|
125
|
+
```ruby
|
126
|
+
Ruta::Router.define do
|
127
|
+
for_context :main do
|
128
|
+
for_context :info_view do
|
129
|
+
map :i_switch, '/buttons/:switch_to', to: [:scroller,:buttons]
|
130
|
+
map :sign_up, '/sign_up', context: :sign_up
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
root_to :main
|
135
|
+
end
|
136
|
+
|
137
|
+
```
|
138
|
+
|
139
|
+
###Renderer
|
140
|
+
|
141
|
+
The last step is to tell the router how to render your components.
|
142
|
+
|
143
|
+
You do this using `Ruta::Context.handle_render` and then creating a macro.
|
144
|
+
Passed into the macro is the `component` you wish to render and the `element_id` of the components mounting
|
145
|
+
point.
|
146
|
+
|
147
|
+
```ruby
|
148
|
+
Ruta::Context.handle_render do |component,element_id|
|
149
|
+
element = if component.class == React::Element
|
150
|
+
component
|
151
|
+
else
|
152
|
+
React.create_element(component)
|
153
|
+
end
|
154
|
+
React.render element, `document.getElementById(#{element_id})`
|
155
|
+
end
|
156
|
+
```
|
157
|
+
|
158
|
+
###starting the app
|
159
|
+
|
160
|
+
The last step is to start the router and thus your app this can be accomplished by using `Ruta.start_app`;
|
161
|
+
it's best to wrap this inside of a `$document.ready` block so that the app will only start when the dom is
|
162
|
+
fully ready.
|
163
|
+
```ruby
|
164
|
+
$document.ready do
|
165
|
+
Ruta.start_app
|
166
|
+
end
|
167
|
+
```
|
168
|
+
|
169
|
+
### Example
|
170
|
+
|
171
|
+
Here is an [example app](https://github.com/Thermatix/ruta_with_reactrb_example) where you can see the router in action, remember to `bundle install` first before running with `rackup`
|
172
|
+
|
173
|
+
|
174
|
+
|
175
|
+
## Development
|
176
|
+
|
177
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake false` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
178
|
+
|
179
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
180
|
+
|
181
|
+
## Contributing
|
182
|
+
|
183
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/ruta. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
|
184
|
+
|
185
|
+
|
186
|
+
## License
|
187
|
+
|
188
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "ruta"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
data/lib/ruta/context.rb
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
# stores contexts
|
2
|
+
module Ruta
|
3
|
+
class Context
|
4
|
+
|
5
|
+
# @!attribute [r] elements
|
6
|
+
# @return [{ref => { attributes: {},type: Symbol, content: Proc,Symbol}] Hash of all elements defined
|
7
|
+
|
8
|
+
# @!attribute [r] ref
|
9
|
+
# @return [Symbol] this contexts reference in (see #Context#collection)
|
10
|
+
|
11
|
+
# @!attribute [r,w] handlers
|
12
|
+
# @return [{ref => Proc}] list of route handlers attached to this context
|
13
|
+
|
14
|
+
# @!attribute [r,w] routes
|
15
|
+
# @return [{ref => Route}] list of all routes attached to this context
|
16
|
+
|
17
|
+
attr_reader :elements, :ref
|
18
|
+
attr_accessor :handlers, :routes,:sub_contexts
|
19
|
+
DOM = ::Kernel.method(:DOM)
|
20
|
+
|
21
|
+
# @see #Context#handle_render
|
22
|
+
def initialize ref,block
|
23
|
+
@ref = ref
|
24
|
+
@elements = {}
|
25
|
+
@handlers = {}
|
26
|
+
@routes = {}
|
27
|
+
@sub_contexts = []
|
28
|
+
instance_exec &block if block
|
29
|
+
end
|
30
|
+
|
31
|
+
# an element of the composition
|
32
|
+
#
|
33
|
+
# @param [Symbol] id of element to mount element contents to
|
34
|
+
# @param [{Symbol => String,Number,Boolean}] list of attributes to attach to tag
|
35
|
+
# @yield block containing component to be rendered to page
|
36
|
+
# @yieldreturn [Object] a component that will be passed to the renderer to be rendered to the page
|
37
|
+
def component id,attribs={}, &block
|
38
|
+
self.elements[id] = {
|
39
|
+
attributes: attribs,
|
40
|
+
type: :element,
|
41
|
+
content: block
|
42
|
+
}
|
43
|
+
end
|
44
|
+
|
45
|
+
# mount a context as a sub context here
|
46
|
+
#
|
47
|
+
# @param [Symbol] id of component to mount context to
|
48
|
+
# @param [Symbol] ref of context to be mounted
|
49
|
+
# @param [{Symbol => String,Number,Boolean}] list of attributes to attach to tag
|
50
|
+
def sub_context id,ref,attribs={}
|
51
|
+
@sub_contexts << ref
|
52
|
+
self.elements[id] = {
|
53
|
+
attributes: attribs,
|
54
|
+
type: :sub_context,
|
55
|
+
content: ref,
|
56
|
+
}
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
class << self
|
61
|
+
# @!attribute [r] collection
|
62
|
+
# @return [{ref => Context}] Hash of all Contexts created
|
63
|
+
|
64
|
+
# @!attribute [r] renderer
|
65
|
+
# @return [Proc] the renderer used to render and or mount components on to the DOM
|
66
|
+
|
67
|
+
# @!attribute [r,w] current_context
|
68
|
+
# @return [Symbol] The reference to the current context being rendered
|
69
|
+
|
70
|
+
|
71
|
+
attr_reader :collection,:renderer
|
72
|
+
attr_accessor :current_context
|
73
|
+
|
74
|
+
# Used to tell the router how to render components to the DOM
|
75
|
+
#
|
76
|
+
# @example render a react.rb component to the dom
|
77
|
+
# Ruta::Context.handle_render do |object,element_id|
|
78
|
+
# React.render React.create_element(object), `document.getElementById(#{element_id})`
|
79
|
+
# end
|
80
|
+
# @yield [object,element_id] A block of code that gets executed to render a given object to a given element id
|
81
|
+
# @yieldparam [Object] object to be rendered
|
82
|
+
# @yieldparam [String] ID of page element object will be mounted to
|
83
|
+
def handle_render &block
|
84
|
+
@renderer = block
|
85
|
+
end
|
86
|
+
|
87
|
+
# used to define a context's page composition
|
88
|
+
#
|
89
|
+
# @example Define a composition for a context called :main
|
90
|
+
# Ruta::Context.define :main do
|
91
|
+
# element :header do
|
92
|
+
# #some code that returns a component
|
93
|
+
# end
|
94
|
+
#
|
95
|
+
# sub_context :info, :info_view
|
96
|
+
#
|
97
|
+
# element :footer do
|
98
|
+
# #some code that returns a component
|
99
|
+
# end
|
100
|
+
# end
|
101
|
+
# @param [Symbol] ref reference to the context being defined
|
102
|
+
# @yield a block that is used to define the composition of a context
|
103
|
+
def define ref, &block
|
104
|
+
@collection[ref] = new(ref,block)
|
105
|
+
end
|
106
|
+
|
107
|
+
# used to wipe clear an elementt's content
|
108
|
+
#
|
109
|
+
# @param [String] id of element to be cleared, if no id is provided will clear body tag of content
|
110
|
+
def wipe id=nil
|
111
|
+
if id
|
112
|
+
$document[id].clear
|
113
|
+
else
|
114
|
+
$document.body.clear
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# used to render a composition to the screen
|
119
|
+
#
|
120
|
+
# @param [Symbol] context the context to render
|
121
|
+
# @param [String] id of element context is to be rendered to, if no id is provided will default to body tagt
|
122
|
+
def render context, id=nil
|
123
|
+
this = id ? $document[id]: $document.body
|
124
|
+
context_to_render = @collection[context]
|
125
|
+
render_context_elements context_to_render,context, this
|
126
|
+
render_element_contents context_to_render,context
|
127
|
+
end
|
128
|
+
private
|
129
|
+
def render_context_elements context_to_render,context,this
|
130
|
+
context_to_render.elements.each do |element_name,details|
|
131
|
+
DOM {
|
132
|
+
div(details[:attributes].merge(id: element_name, "data-context" => context))
|
133
|
+
}.append_to(this)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def render_element_contents context_to_render,context
|
138
|
+
@current_context = context
|
139
|
+
context_to_render.elements.each do |element_name,details|
|
140
|
+
case details[:type]
|
141
|
+
when :sub_context
|
142
|
+
render details[:content],element_name
|
143
|
+
when :element
|
144
|
+
@renderer.call(details[:content].call,element_name,context)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
@current_context = :no_context
|
148
|
+
end
|
149
|
+
end
|
150
|
+
@collection = {}
|
151
|
+
@current_context = :no_context
|
152
|
+
end
|
153
|
+
end
|
data/lib/ruta/handler.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
module Ruta
|
2
|
+
class Handlers
|
3
|
+
|
4
|
+
# create a handle to be excuted when a matching route is hit
|
5
|
+
#
|
6
|
+
# @param [Symbol] handler_name the unique ident of the handler, it should match the id of an element that you want the component to be rendered to
|
7
|
+
# @yield [params,path] a block containing logic for processing any params before passing it to a component to render
|
8
|
+
# @yieldparam [{Symbol => String}] params containing a list of params passed into it from the matching route
|
9
|
+
# @yieldparam [String] path the non processed url
|
10
|
+
# @yieldreturn [Object] a component that will be passed to the renderer to be rendered to the page
|
11
|
+
def handle handler_name,&handler
|
12
|
+
@handler_name = handler_name
|
13
|
+
@context.handlers[@handler_name] = handler
|
14
|
+
end
|
15
|
+
|
16
|
+
# @see #Handlers#define_for
|
17
|
+
def initialize context,block
|
18
|
+
@context = context
|
19
|
+
instance_exec &block
|
20
|
+
end
|
21
|
+
|
22
|
+
# wipe the matching element and render a context
|
23
|
+
#
|
24
|
+
# @param [Symbol] context context to be mounted to matching element of handler
|
25
|
+
# @todo Move these functions to execution context?
|
26
|
+
# @return [Proc] returns a proc to be executed later
|
27
|
+
def mount context
|
28
|
+
handler_name = @handler_name
|
29
|
+
proc {
|
30
|
+
Context.wipe handler_name
|
31
|
+
Context.render context
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
class << self
|
36
|
+
# define handlers for a context
|
37
|
+
#
|
38
|
+
# @example
|
39
|
+
# Ruta::Handlers.define_for :main do
|
40
|
+
# handler :header do |params,url|
|
41
|
+
# some code that process the params and returns a component
|
42
|
+
# end
|
43
|
+
# handler :header do |params,url|
|
44
|
+
# some code that process the params and returns a component
|
45
|
+
# end
|
46
|
+
# end
|
47
|
+
# @param [Symbol] context to define handlers for
|
48
|
+
# @yield block containing handlers for a context
|
49
|
+
def define_for context, &block
|
50
|
+
new(Context.collection.fetch(context){|c_n|raise"Tried to define handlers for #{c_n} before it exists"},
|
51
|
+
block)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/ruta/history.rb
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'native'
|
2
|
+
module Ruta
|
3
|
+
|
4
|
+
class History
|
5
|
+
class << self
|
6
|
+
|
7
|
+
# push new url to history
|
8
|
+
#
|
9
|
+
# @param [String] url to be added to history
|
10
|
+
# @param [Hash] data to be added to history
|
11
|
+
# @param [String] title to be added to history, defaults to ""
|
12
|
+
def push(url,data,title="")
|
13
|
+
`history.pushState(#{data.to_n}, #{title}, #{url})`
|
14
|
+
end
|
15
|
+
|
16
|
+
# replace current url in history
|
17
|
+
#
|
18
|
+
# @param [String] url to replace current item in history
|
19
|
+
# @param [Hash] data to replace current item in history
|
20
|
+
# @param [String] title to replace current item in history, defaults to ""
|
21
|
+
def replace(url,data,title=nil)
|
22
|
+
`history.replaceState(#{data.to_n}, #{title}, #{url})`
|
23
|
+
end
|
24
|
+
|
25
|
+
# move browser forward
|
26
|
+
#
|
27
|
+
# @param [Integer] by the amount to go forwards by, defaults to 1
|
28
|
+
def forward(by=1)
|
29
|
+
`history.go(#{by.to_i})`
|
30
|
+
end
|
31
|
+
|
32
|
+
# move browser backwards
|
33
|
+
#
|
34
|
+
# @param [Integer] by the amount to go backwards by, defaults to 1
|
35
|
+
def back(by=1)
|
36
|
+
`history.go(#{-by.to_i})`
|
37
|
+
end
|
38
|
+
|
39
|
+
# navigate browser to remote path
|
40
|
+
#
|
41
|
+
# @param [String] path to navigate to
|
42
|
+
def navigate_to_remote path
|
43
|
+
`location.href = #{path}`
|
44
|
+
end
|
45
|
+
|
46
|
+
# get current `thing` from locaction
|
47
|
+
#
|
48
|
+
# current things supported are:
|
49
|
+
# * query
|
50
|
+
# * fragment
|
51
|
+
# * path
|
52
|
+
# * url
|
53
|
+
# * uri
|
54
|
+
# @param [Symbol] thing to get the current value of from the current location
|
55
|
+
def current thing
|
56
|
+
case thing
|
57
|
+
when :query
|
58
|
+
`location.query`
|
59
|
+
when :fragment
|
60
|
+
` location.fragment`
|
61
|
+
when :path
|
62
|
+
`location.pathname`
|
63
|
+
when :url
|
64
|
+
`location.href`
|
65
|
+
when :uri
|
66
|
+
`location.uri`
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
# will turn on a listener for when the forward and backward buttons on the browser are pressed
|
72
|
+
def listen_for_pop
|
73
|
+
`window.onpopstate = function(event) {
|
74
|
+
#{
|
75
|
+
Router.find_and_execute(current :path)
|
76
|
+
}
|
77
|
+
}`
|
78
|
+
end
|
79
|
+
|
80
|
+
# will stop listening for when forward and backward buttons on the browser are pressed
|
81
|
+
def stop_listening_for_pop
|
82
|
+
`window.onpopstate = nil`
|
83
|
+
end
|
84
|
+
|
85
|
+
# will stop listening for when the page move away from the current page(refresh or back), will present user with dialogue box
|
86
|
+
def stop_listening_for_on_before_load
|
87
|
+
`window.onbeforeunload = nil`
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
# will turn on a listener for when the page move away from the current page(refresh or back), will present user with dialogue box
|
92
|
+
def listen_for_on_before_load
|
93
|
+
`window.onbeforeunload = function (evt) {
|
94
|
+
var message = 'Are you sure you want to leave?';
|
95
|
+
if (typeof evt == 'undefined') {
|
96
|
+
evt = window.event;
|
97
|
+
}
|
98
|
+
if (evt) {
|
99
|
+
evt.returnValue = message;
|
100
|
+
}
|
101
|
+
return message;
|
102
|
+
}`
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
data/lib/ruta/route.rb
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
module Ruta
|
2
|
+
# this class was taken from vienna and modified
|
3
|
+
# https://github.com/opal/vienna/blob/master/opal/vienna/router.rb#L42
|
4
|
+
class Route
|
5
|
+
DOM = ::Kernel.method(:DOM)
|
6
|
+
NAMED = /:(\w+)/
|
7
|
+
|
8
|
+
SPLAT = /\\\*(\w+)/
|
9
|
+
|
10
|
+
OPTIONAL = /\\\((.*?)\\\)/
|
11
|
+
|
12
|
+
# @!attribute [r] regexp
|
13
|
+
# @return [Symbol] the regexp used to match against a route
|
14
|
+
# @!attribute [r] named
|
15
|
+
# @return [Symbol] list of all named paramters
|
16
|
+
# @!attribute [r] type
|
17
|
+
# @return [Symbol] the type of the route's handler
|
18
|
+
# @!attribute [r] handlers
|
19
|
+
# @return [Symbol] a list of the handlers this route is suposed to execute
|
20
|
+
# @!attribute [r] url
|
21
|
+
# @return [Symbol] the raw url to match against
|
22
|
+
# @!attribute [r] flags
|
23
|
+
# @return [Symbol] any flags this route possesses
|
24
|
+
|
25
|
+
attr_reader :regexp, :named, :type, :handlers, :url,:flags
|
26
|
+
|
27
|
+
# @param [String] pattern of url to match against
|
28
|
+
# @param [Symbol] context_ref to context route is mounted to
|
29
|
+
# @param [{Symbol => String,Number,Boolean}] flags attached to route
|
30
|
+
def initialize(pattern, context_ref,flags)
|
31
|
+
|
32
|
+
if flags[:to]
|
33
|
+
@type = :handlers
|
34
|
+
@handlers = [flags.delete :to].flatten
|
35
|
+
elsif flags[:context]
|
36
|
+
@type = :context
|
37
|
+
@handlers = flags.delete :context
|
38
|
+
else
|
39
|
+
@type = :ref_only
|
40
|
+
end
|
41
|
+
@context_ref = context_ref
|
42
|
+
@flags = flags
|
43
|
+
@url = pattern
|
44
|
+
@named = []
|
45
|
+
|
46
|
+
pattern = Regexp.escape pattern
|
47
|
+
pattern = pattern.gsub OPTIONAL, "(?:$1)?"
|
48
|
+
|
49
|
+
pattern.gsub(NAMED) { |m| @named << m[1..-1] }
|
50
|
+
pattern.gsub(SPLAT) { |m| @named << m[2..-1] }
|
51
|
+
|
52
|
+
pattern = pattern.gsub NAMED, "([^\\/]*)"
|
53
|
+
pattern = pattern.gsub SPLAT, "(.*?)"
|
54
|
+
|
55
|
+
@regexp = Regexp.new "^#{pattern}$"
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
#take in params and return a paramaterized route
|
60
|
+
#
|
61
|
+
# @param [Array<String,Number,Boolean>] params a list of params to replace named params in a route
|
62
|
+
# @return [String] url containing named params replaced
|
63
|
+
def paramaterize params
|
64
|
+
segments = @url.split('/')
|
65
|
+
segments.map { |item| item[0] == ':' ? params.shift : item }.join('/')
|
66
|
+
end
|
67
|
+
|
68
|
+
# get route hash and paramaterize url if needed
|
69
|
+
#
|
70
|
+
# @param [Array<String,Number,Boolean>] params to replace named params in the returned url
|
71
|
+
# @return [Symbol => Number,String,Route] hash specificly formatted:
|
72
|
+
# {
|
73
|
+
# url: of the route with named params replaced,
|
74
|
+
# title: the name of page if the url has one,
|
75
|
+
# params: a list of all the params used in the route,
|
76
|
+
# route: the #Route object
|
77
|
+
# }
|
78
|
+
def get params=nil
|
79
|
+
path = if params
|
80
|
+
paramaterize params.dup
|
81
|
+
else
|
82
|
+
@url
|
83
|
+
end
|
84
|
+
{
|
85
|
+
path: path,
|
86
|
+
title: self.flags.fetch(:title){nil},
|
87
|
+
params: params_hash(params),
|
88
|
+
route: self
|
89
|
+
}
|
90
|
+
end
|
91
|
+
|
92
|
+
# match this route against a given path
|
93
|
+
#
|
94
|
+
# @param [String,Regex] path to match against
|
95
|
+
# @return [Hash,false] (see #get) or false if there is no match
|
96
|
+
def match(path)
|
97
|
+
if match = @regexp.match(path)
|
98
|
+
params = {}
|
99
|
+
@named.each_with_index { |name, i| params[name] = match[i + 1] } if @type == :handlers
|
100
|
+
{
|
101
|
+
path: path,
|
102
|
+
title: self.flags.fetch(:title){nil},
|
103
|
+
params: params,
|
104
|
+
route: self
|
105
|
+
}
|
106
|
+
else
|
107
|
+
false
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# execute's route's associated handlers
|
112
|
+
#
|
113
|
+
# @param [Symbol => String] params from the route with there respective keys
|
114
|
+
# @param [String] path containing params placed into there respective named positions
|
115
|
+
def execute_handler params={},path=nil
|
116
|
+
case @type
|
117
|
+
when :handlers
|
118
|
+
@handlers.each do |handler_ident|
|
119
|
+
handler = @context_ref.handlers.fetch(handler_ident) {raise "handler #{handler_ident} doesn't exist in context #{@context_ref.ref}"}
|
120
|
+
component = handler.(params,path||@url,&:call)
|
121
|
+
Context.current_context = @context_ref.ref
|
122
|
+
if component.class == Proc
|
123
|
+
component.call
|
124
|
+
else
|
125
|
+
Context.renderer.call(component,handler_ident)
|
126
|
+
end
|
127
|
+
Context.current_context = :no_context
|
128
|
+
end
|
129
|
+
when :context
|
130
|
+
Context.wipe
|
131
|
+
Context.render handlers
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def params_hash(params)
|
136
|
+
Hash[@named.zip(params)]
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
data/lib/ruta/router.rb
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
# matches routes to a handeler
|
2
|
+
module Ruta
|
3
|
+
|
4
|
+
class Router
|
5
|
+
|
6
|
+
|
7
|
+
# @todo: ensure sub-context routes are mounted into parent context routes
|
8
|
+
|
9
|
+
# @!attribute [r,w] current_context
|
10
|
+
# @return [Array<Symbol>] current_context a list of contexts, the last being the current
|
11
|
+
|
12
|
+
attr_accessor :current_context
|
13
|
+
|
14
|
+
# @see (see #Router#define)
|
15
|
+
def initialize block
|
16
|
+
@current_context = []
|
17
|
+
Context.define(:no_context)
|
18
|
+
instance_exec &block
|
19
|
+
end
|
20
|
+
|
21
|
+
# set which Context to map the following routes to
|
22
|
+
#
|
23
|
+
# @param [Symbol] context to map routes to
|
24
|
+
def for_context context
|
25
|
+
@current_context << context
|
26
|
+
yield
|
27
|
+
@current_context.pop
|
28
|
+
end
|
29
|
+
|
30
|
+
# map a route
|
31
|
+
# @param [Symbol] ref to map route to for easy future reference
|
32
|
+
def map ref,route, options={}
|
33
|
+
context = Context.collection[get_context]
|
34
|
+
context.routes[ref]= Route.new(route, context,options)
|
35
|
+
end
|
36
|
+
|
37
|
+
# set the root context, this is the initial context that will be renered by the router
|
38
|
+
#
|
39
|
+
# @note there is only ever one root, calling this multiple times will over right the original root
|
40
|
+
# @param [Symbol] reference to context
|
41
|
+
def root_to reference
|
42
|
+
Router.set_root_to reference
|
43
|
+
context = Context.collection[:no_context]
|
44
|
+
context.routes[:root]= Route.new('/', context,{ context: reference})
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def get_context
|
50
|
+
@current_context.last || :no_context
|
51
|
+
end
|
52
|
+
|
53
|
+
class << self
|
54
|
+
|
55
|
+
# @!attribute [r] current_context
|
56
|
+
# @return [Array<Symbol>] current_context the current context that the user is in
|
57
|
+
|
58
|
+
# @!attribute [r] history
|
59
|
+
# @return [Array<Symbol>] history
|
60
|
+
|
61
|
+
# @!attribute [r] window
|
62
|
+
# @return [Array<Symbol>] window
|
63
|
+
|
64
|
+
# @!attribute [r] root
|
65
|
+
# @return [Array<Symbol>] root the initial context of the app
|
66
|
+
|
67
|
+
attr_reader :current_context, :root
|
68
|
+
|
69
|
+
# define a router, this can be called multiple times
|
70
|
+
# @example defining routes
|
71
|
+
# Ruta::Router.define do
|
72
|
+
# for_context :main do
|
73
|
+
# for_context :info_view do
|
74
|
+
# map :i_switch, '/buttons/:switch_to', to: [:scroller,:buttons]
|
75
|
+
# map :sign_up, '/sign_up', context: :sign_up
|
76
|
+
# end
|
77
|
+
# end
|
78
|
+
#
|
79
|
+
# root_to :main
|
80
|
+
# end
|
81
|
+
# @note please be aware that placing contexts within other contexts doesn't actully do anything.
|
82
|
+
# however it is planed to be able to mount sub contexts to a route and re-direct as neccasary
|
83
|
+
# think mounting engines or sub apps in RoR or Padrino
|
84
|
+
# @yield Use this block to define any routes
|
85
|
+
def define &block
|
86
|
+
new block
|
87
|
+
end
|
88
|
+
|
89
|
+
def set_context_to context
|
90
|
+
@current_context = context
|
91
|
+
end
|
92
|
+
|
93
|
+
def find_and_execute(path)
|
94
|
+
res = find(path)
|
95
|
+
if res
|
96
|
+
navigate_to res
|
97
|
+
else
|
98
|
+
raise "no matching route for #{path}"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def find path
|
103
|
+
Context.collection.each do |con_ref,context|
|
104
|
+
context.routes.each do |r_ref,route|
|
105
|
+
res = route.match(path)
|
106
|
+
return res if res
|
107
|
+
end
|
108
|
+
end
|
109
|
+
false
|
110
|
+
end
|
111
|
+
|
112
|
+
def navigate_to(route)
|
113
|
+
route[:route].execute_handler route[:params],route[:path]
|
114
|
+
end
|
115
|
+
|
116
|
+
def route_for context, ref,params=nil
|
117
|
+
Context.collection[context].routes[ref].get(params)
|
118
|
+
end
|
119
|
+
|
120
|
+
def set_root_to context
|
121
|
+
@root = context
|
122
|
+
Router.set_context_to root
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
end
|
data/lib/ruta/version.rb
ADDED
data/lib/ruta.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
# @todo: Ensure sub-context routes are mounted into parent context routes
|
2
|
+
# @todo: Allow empty components to be exists and ensure they are only rendered when they are not blank
|
3
|
+
|
4
|
+
if RUBY_ENGINE == 'opal'
|
5
|
+
require 'browser'
|
6
|
+
require 'browser/history'
|
7
|
+
|
8
|
+
require 'ruta/context'
|
9
|
+
require 'ruta/handler'
|
10
|
+
require 'ruta/history'
|
11
|
+
require 'ruta/route'
|
12
|
+
require 'ruta/router'
|
13
|
+
require 'ruta/version'
|
14
|
+
|
15
|
+
|
16
|
+
module Ruta
|
17
|
+
class << self
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
# used to retrive a stored url
|
22
|
+
#
|
23
|
+
# @param [Symbol] context of the stored url, if this is nil it defaults to the current context
|
24
|
+
# @param [Symbol] reference to the route
|
25
|
+
# @param [Array<String,Number,Boolean>] *params 0 or more params to replace params in the paramterized route
|
26
|
+
# @return [String] string containing url with any params given correctly inserted
|
27
|
+
def get_url_for context, reference, *params
|
28
|
+
Router.route( context || Router.current_context, reference, params)[:path]
|
29
|
+
end
|
30
|
+
|
31
|
+
# used to navigate to a route
|
32
|
+
# @param [Symbol] context that route is mounted to
|
33
|
+
# @param [Symbol] ref to a route that you wish to navigate to
|
34
|
+
# @param [Array<String,Number,Boolean>] *params 0 or more params to replace params in the paramterized route
|
35
|
+
# @note you have to use this function as a proc direcly as in the example, if you place this into a callback block and call it there, you will find that the incorrect context is used for the route
|
36
|
+
# @return [Proc] A proc that can be used as a callback block for an event
|
37
|
+
def navigate_to_ref context, ref,*params
|
38
|
+
route = Router.route_for(context,ref,params)
|
39
|
+
History.push(route[:path],route[:params],route[:title])
|
40
|
+
Router.navigate_to(route)
|
41
|
+
end
|
42
|
+
|
43
|
+
# used to start the app
|
44
|
+
# @example app start command placed inside of $document.ready block
|
45
|
+
# $document.ready do
|
46
|
+
# Ruta.start_app
|
47
|
+
# end
|
48
|
+
def start_app
|
49
|
+
Context.render(Router.current_context)
|
50
|
+
History.listen_for_pop
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
else
|
58
|
+
require "ruta/version"
|
59
|
+
require 'opal'
|
60
|
+
lib_path = File.dirname(File.expand_path('.', __FILE__))
|
61
|
+
Opal.append_path lib_path
|
62
|
+
end
|
data/ruta.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'ruta/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "ruta"
|
8
|
+
spec.version = Ruta::VERSION
|
9
|
+
spec.authors = ["Martin Becker",'Adam Beynon']
|
10
|
+
spec.email = ["mbeckerwork@gmail.com",'adam.beynon@gmail.com']
|
11
|
+
|
12
|
+
spec.summary = %q{Front end agnostic router built in opal}
|
13
|
+
spec.homepage = "https://github.com/Thermatix/ruta"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
+
spec.bindir = "exe"
|
19
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_runtime_dependency "opal", "~> 0.8"
|
23
|
+
spec.add_runtime_dependency "opal-browser", "~> 0.2"
|
24
|
+
|
25
|
+
spec.add_development_dependency "bundler", "~> 1.10"
|
26
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
27
|
+
end
|
metadata
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ruta
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Martin Becker
|
8
|
+
- Adam Beynon
|
9
|
+
autorequire:
|
10
|
+
bindir: exe
|
11
|
+
cert_chain: []
|
12
|
+
date: 2015-12-14 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: opal
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0.8'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "~>"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '0.8'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: opal-browser
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - "~>"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0.2'
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0.2'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: bundler
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - "~>"
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '1.10'
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - "~>"
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '1.10'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: rake
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - "~>"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '10.0'
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '10.0'
|
70
|
+
description:
|
71
|
+
email:
|
72
|
+
- mbeckerwork@gmail.com
|
73
|
+
- adam.beynon@gmail.com
|
74
|
+
executables: []
|
75
|
+
extensions: []
|
76
|
+
extra_rdoc_files: []
|
77
|
+
files:
|
78
|
+
- ".gitignore"
|
79
|
+
- ".travis.yml"
|
80
|
+
- CODE_OF_CONDUCT.md
|
81
|
+
- Gemfile
|
82
|
+
- Gemfile.lock
|
83
|
+
- LICENSE.txt
|
84
|
+
- README.md
|
85
|
+
- Rakefile
|
86
|
+
- bin/console
|
87
|
+
- bin/setup
|
88
|
+
- lib/ruta.rb
|
89
|
+
- lib/ruta/context.rb
|
90
|
+
- lib/ruta/handler.rb
|
91
|
+
- lib/ruta/history.rb
|
92
|
+
- lib/ruta/route.rb
|
93
|
+
- lib/ruta/router.rb
|
94
|
+
- lib/ruta/version.rb
|
95
|
+
- ruta.gemspec
|
96
|
+
homepage: https://github.com/Thermatix/ruta
|
97
|
+
licenses:
|
98
|
+
- MIT
|
99
|
+
metadata: {}
|
100
|
+
post_install_message:
|
101
|
+
rdoc_options: []
|
102
|
+
require_paths:
|
103
|
+
- lib
|
104
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - ">="
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '0'
|
109
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
110
|
+
requirements:
|
111
|
+
- - ">="
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: '0'
|
114
|
+
requirements: []
|
115
|
+
rubyforge_project:
|
116
|
+
rubygems_version: 2.4.5.1
|
117
|
+
signing_key:
|
118
|
+
specification_version: 4
|
119
|
+
summary: Front end agnostic router built in opal
|
120
|
+
test_files: []
|
121
|
+
has_rdoc:
|