kawaii-core 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/Guardfile +42 -0
- data/LICENSE.txt +21 -0
- data/README.md +372 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/examples/controller.ru +30 -0
- data/examples/hello_world.rb +5 -0
- data/examples/hello_world.ru +4 -0
- data/examples/modular.ru +11 -0
- data/examples/modular/first_app.rb +6 -0
- data/examples/modular/second_app.rb +6 -0
- data/examples/nested_routes.rb +11 -0
- data/examples/views.ru +10 -0
- data/examples/views/index.html.erb +1 -0
- data/kawaii-core.gemspec +34 -0
- data/lib/kawaii.rb +17 -0
- data/lib/kawaii/base.rb +48 -0
- data/lib/kawaii/controller.rb +32 -0
- data/lib/kawaii/core_ext/hash.rb +23 -0
- data/lib/kawaii/core_ext/string.rb +6 -0
- data/lib/kawaii/matchers.rb +135 -0
- data/lib/kawaii/method_chain.rb +15 -0
- data/lib/kawaii/render_methods.rb +14 -0
- data/lib/kawaii/route.rb +27 -0
- data/lib/kawaii/route_context.rb +49 -0
- data/lib/kawaii/route_handler.rb +54 -0
- data/lib/kawaii/route_mapping.rb +35 -0
- data/lib/kawaii/routing_methods.rb +120 -0
- data/lib/kawaii/server_methods.rb +33 -0
- data/lib/kawaii/singleton_app.rb +58 -0
- data/lib/kawaii/version.rb +4 -0
- metadata +193 -0
@@ -0,0 +1,14 @@
|
|
1
|
+
module Kawaii
|
2
|
+
# Template rendering based on Tilt.
|
3
|
+
module RenderMethods
|
4
|
+
# Renders a template.
|
5
|
+
# @param tmpl [String] file name or path to template, relative to /views in project dir
|
6
|
+
# @example Rendering html erb file
|
7
|
+
# render('index.html.erb')
|
8
|
+
# @todo Layouts.
|
9
|
+
def render(tmpl)
|
10
|
+
t = Tilt.new(File.join('views', tmpl)) # @todo Caching!
|
11
|
+
t.render(self)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/kawaii/route.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
module Kawaii
|
2
|
+
# Matching and resolution for a single route.
|
3
|
+
class Route
|
4
|
+
include MethodChain
|
5
|
+
|
6
|
+
# Create a {Route} object.
|
7
|
+
# @param path [String, Regexp, Matcher] any path specification which can be
|
8
|
+
# consumed by {Matcher.compile}
|
9
|
+
# @param block [Proc] route handler
|
10
|
+
def initialize(scope, path, &block)
|
11
|
+
self.parent_scope = scope
|
12
|
+
@matcher = Matcher.compile(path, full_match: true)
|
13
|
+
@block = block
|
14
|
+
end
|
15
|
+
|
16
|
+
# Tries to match the route against a Rack environment.
|
17
|
+
# @param env [Hash] Rack environment
|
18
|
+
# @return [RouteHandler] a Rack application creating environment to run
|
19
|
+
# the route's handler block in on {RouteHandler#call}. Can be nil if
|
20
|
+
# no match found.
|
21
|
+
def match(env)
|
22
|
+
match = @matcher.match(env[Rack::PATH_INFO])
|
23
|
+
# puts "Route#match #{@matcher} #{env[Rack::PATH_INFO]} #{match.inspect}"
|
24
|
+
RouteHandler.new(self, match.params, &@block) if match
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Kawaii
|
2
|
+
# Implementation of nested routes generated via Router#context.
|
3
|
+
#
|
4
|
+
# @example A simple context
|
5
|
+
# context '/foo' do
|
6
|
+
# get '/bar' do
|
7
|
+
# end
|
8
|
+
# end
|
9
|
+
#
|
10
|
+
# # It is a rough equivalent of:
|
11
|
+
#
|
12
|
+
# ctx = RouteContext.new('/foo')
|
13
|
+
# ctx.get '/bar' do
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# @private
|
17
|
+
class RouteContext
|
18
|
+
include RoutingMethods
|
19
|
+
include MethodChain
|
20
|
+
|
21
|
+
# Create a {RouteContext} object.
|
22
|
+
# @param path [String, Regexp, Matcher] any path specification which can
|
23
|
+
# be consumed by {Matcher.compile}
|
24
|
+
def initialize(scope, path)
|
25
|
+
self.parent_scope = scope
|
26
|
+
super()
|
27
|
+
@matcher = Matcher.compile(path, starts_with: true)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Tries to match the context against a Rack environment.
|
31
|
+
# @param env [Hash] Rack environment
|
32
|
+
# @return [Route] matching route defined inside the context. Can be nil if
|
33
|
+
# no match found.
|
34
|
+
def match(env)
|
35
|
+
m = @matcher.match(env[Rack::PATH_INFO])
|
36
|
+
super(env.merge(Rack::PATH_INFO => ensure_slash(m.remaining_path))) if m
|
37
|
+
end
|
38
|
+
|
39
|
+
protected
|
40
|
+
|
41
|
+
def ensure_slash(path)
|
42
|
+
if path.start_with?('/')
|
43
|
+
path
|
44
|
+
else
|
45
|
+
'/' + path
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Kawaii
|
2
|
+
# Creates context for execution of route handler block provided by the user
|
3
|
+
# with {#params} and other objects.
|
4
|
+
#
|
5
|
+
# @example Route handler block
|
6
|
+
# get '/users/:id' do
|
7
|
+
# if params[:id] ...
|
8
|
+
# end
|
9
|
+
class RouteHandler
|
10
|
+
include MethodChain
|
11
|
+
include RenderMethods
|
12
|
+
|
13
|
+
# Params based on request visible in the route handler scope.
|
14
|
+
attr_reader :params
|
15
|
+
# Rack::Request object visible in the route handler scope
|
16
|
+
attr_reader :request
|
17
|
+
|
18
|
+
# Creates a new RouteHandler wrapping a handler block.
|
19
|
+
# @param path_params [Hash] named parameters from paths similar to
|
20
|
+
# /users/:id
|
21
|
+
# @param block [Proc] the actual route handler
|
22
|
+
def initialize(scope, path_params, &block)
|
23
|
+
self.parent_scope = scope
|
24
|
+
@path_params = path_params
|
25
|
+
@block = block
|
26
|
+
end
|
27
|
+
|
28
|
+
# Invokes the handler as a normal Rack application.
|
29
|
+
# @param env [Hash] Rack environment
|
30
|
+
# @return [Array] Rack response array
|
31
|
+
def call(env)
|
32
|
+
@request = Rack::Request.new(env)
|
33
|
+
@params = @path_params.merge(@request.params.symbolize_keys)
|
34
|
+
process_response(instance_exec(self, params, request, &@block))
|
35
|
+
end
|
36
|
+
|
37
|
+
protected
|
38
|
+
|
39
|
+
class ResponseError < RuntimeError; end
|
40
|
+
|
41
|
+
def process_response(response)
|
42
|
+
if response.is_a?(String)
|
43
|
+
[200,
|
44
|
+
{ Rack::CONTENT_TYPE => 'text/html',
|
45
|
+
Rack::CONTENT_LENGTH => response.size.to_s },
|
46
|
+
[response]]
|
47
|
+
elsif response.is_a?(Array)
|
48
|
+
response
|
49
|
+
else
|
50
|
+
fail ResponseError, "Unsupported handler aresponse: #{response.inspect}"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Kawaii
|
2
|
+
# @private
|
3
|
+
# Maps route to a handler based on parameters.
|
4
|
+
# Supports mapping to blocks and to controller actions.
|
5
|
+
class RouteMapping
|
6
|
+
def initialize(mapping, &block)
|
7
|
+
fail 'Do not provide a block if mapping given' if mapping && block
|
8
|
+
fail 'Provide a mapping or a block' unless mapping || block
|
9
|
+
@mapping = mapping
|
10
|
+
@block = block
|
11
|
+
end
|
12
|
+
|
13
|
+
def resolve
|
14
|
+
return @block if @block
|
15
|
+
controller_name, method = parse(@mapping)
|
16
|
+
controller_class = find_controller(controller_name)
|
17
|
+
fail "Cannot find controller: #{controller_name}" if controller_class.nil?
|
18
|
+
proc do |& _args|
|
19
|
+
controller = controller_class.new(params, request)
|
20
|
+
controller.send(method)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
protected
|
25
|
+
|
26
|
+
def find_controller(controller_name)
|
27
|
+
Object.const_get(controller_name)
|
28
|
+
end
|
29
|
+
|
30
|
+
def parse(mapping)
|
31
|
+
controller, method = mapping.split('#')
|
32
|
+
[controller.camelcase, method.to_sym]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
module Kawaii
|
2
|
+
# Core route-building and matching.
|
3
|
+
#
|
4
|
+
# These functions can be used both in a class inheriting from {Base}
|
5
|
+
# and in file scope.
|
6
|
+
#
|
7
|
+
# @example Using a class deriving from {Base}
|
8
|
+
# class MyApp < Kawaii::Base
|
9
|
+
# get '/' do
|
10
|
+
# 'Hello, world'
|
11
|
+
# end
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# @example Using top-level (source file scope) route definitions
|
15
|
+
# get '/' do
|
16
|
+
# 'Hello, world'
|
17
|
+
# end
|
18
|
+
module RoutingMethods
|
19
|
+
# @!macro [attach] add_http_method
|
20
|
+
# @method $1(path, &block)
|
21
|
+
# Route handler for $1 HTTP method
|
22
|
+
# @param path [String, Regexp, Matcher] any path specification which can
|
23
|
+
# be consumed by {Matcher.compile}
|
24
|
+
# @param block the route handler
|
25
|
+
# @yield to the given block
|
26
|
+
# @note Supported HTTP verbs based on https://github.com/rack/rack/blob/master/lib/rack.rb#L48
|
27
|
+
def self.add_http_method(meth)
|
28
|
+
define_method(meth) do |path, mapping = nil, &block|
|
29
|
+
handler = RouteMapping.new(mapping, &block).resolve
|
30
|
+
add_route!(meth.to_s.upcase, Route.new(self, path, &handler))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
add_http_method :get
|
35
|
+
add_http_method :post
|
36
|
+
add_http_method :put
|
37
|
+
add_http_method :patch
|
38
|
+
add_http_method :delete
|
39
|
+
add_http_method :head
|
40
|
+
add_http_method :options
|
41
|
+
add_http_method :link
|
42
|
+
add_http_method :unlink
|
43
|
+
add_http_method :trace
|
44
|
+
# Note: Have to generate them individually due to yard limitations.
|
45
|
+
|
46
|
+
|
47
|
+
# Insert routes corresponding to REST actions (similar to Rails `resource`).
|
48
|
+
# @param path [String] path prefix (e.g. "/users/")
|
49
|
+
# @param controller [String] snakecase controller name (e.g. "hello_world"
|
50
|
+
# corresponds to HelloWorld).
|
51
|
+
# @example REST resource routes
|
52
|
+
# route '/users/', 'hello_world'
|
53
|
+
#
|
54
|
+
# # Will insert routes corresponding to:
|
55
|
+
# # GET /users/? -> Controller#index
|
56
|
+
# # GET /users/:id/? -> Controller#show
|
57
|
+
# # POST /users/? -> Controller#create
|
58
|
+
# # PATCH /users/:id/? -> Controller#update
|
59
|
+
# # DELETE /users/:id/? -> Controller#destroy
|
60
|
+
def route(path, controller)
|
61
|
+
get(File.join(path, '?'), "#{controller}#index")
|
62
|
+
get(File.join(path, '/:id/?'), "#{controller}#show")
|
63
|
+
post(File.join(path, '?'), "#{controller}#create")
|
64
|
+
patch(File.join(path, '/:id/?'), "#{controller}#update")
|
65
|
+
delete(File.join(path, '/:id/?'), "#{controller}#destroy")
|
66
|
+
end
|
67
|
+
|
68
|
+
# Create a context for route nesting.
|
69
|
+
#
|
70
|
+
# @param path [String, Regexp, Matcher] any path specification which can
|
71
|
+
# be consumed by {Matcher.compile}
|
72
|
+
# @param block the route handler
|
73
|
+
# @yield to the given block
|
74
|
+
#
|
75
|
+
# @example A simple context
|
76
|
+
# context '/foo' do
|
77
|
+
# get '/bar' do
|
78
|
+
# end
|
79
|
+
# end
|
80
|
+
def context(path, &block)
|
81
|
+
ctx = RouteContext.new(self, path)
|
82
|
+
# @todo Is there a better way to keep ordering of routes?
|
83
|
+
# An alternative would be to enter each route in a context only once
|
84
|
+
# (with 'prefix' based on containing contexts).
|
85
|
+
# On the other hand, we're only doing that when compiling routes, further
|
86
|
+
# processing is faster this way.
|
87
|
+
ctx.instance_eval(&block)
|
88
|
+
ctx.methods_used.each do |meth|
|
89
|
+
add_route!(meth, ctx)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# Tries to match against a Rack environment.
|
94
|
+
# @param env [Hash] Rack environment
|
95
|
+
# @return [Route] matching route. Can be nil if no match found.
|
96
|
+
def match(env)
|
97
|
+
routes[env[Rack::REQUEST_METHOD]]
|
98
|
+
.lazy # Lazy to avoid unnecessary calls to #match.
|
99
|
+
.map { |r| r.match(env) }
|
100
|
+
.find { |r| !r.nil? }
|
101
|
+
end
|
102
|
+
|
103
|
+
# Returns a list of HTTP methods used by the routes (incl. nested routes).
|
104
|
+
# @return [Array<String>] example ["GET", "POST"]
|
105
|
+
def methods_used
|
106
|
+
routes.keys
|
107
|
+
end
|
108
|
+
|
109
|
+
protected
|
110
|
+
|
111
|
+
def routes
|
112
|
+
@routes ||= Hash.new { |h, k| h[k] = [] }
|
113
|
+
end
|
114
|
+
|
115
|
+
def add_route!(method, route)
|
116
|
+
# puts "add_route! #{method} #{route.inspect}"
|
117
|
+
routes[method] << route
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Kawaii
|
2
|
+
# Mixins for starting a self-contained server. To be included in a class
|
3
|
+
# derived from {Base}.
|
4
|
+
# @note At the moment hard-coded to use WEBrick.
|
5
|
+
module ServerMethods
|
6
|
+
WEBRICK = 'WEBrick'
|
7
|
+
|
8
|
+
# Starts serving the app.
|
9
|
+
# @param port [Fixnum] port number to bind to
|
10
|
+
def start!(port) # @todo Support other handlers http://www.rubydoc.info/github/rack/rack/Rack/Handler
|
11
|
+
Rack::Handler.get(WEBRICK).run(self, Port: port) do |s|
|
12
|
+
@server = s
|
13
|
+
at_exit { stop! }
|
14
|
+
[:INT, :TERM].each do |signal|
|
15
|
+
old = trap(signal) do
|
16
|
+
stop!
|
17
|
+
old.call if old.respond_to?(:call)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Stops serving the app.
|
24
|
+
def stop!
|
25
|
+
@server.stop if @server # NOTE: WEBrick-specific
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns true if the server is running.
|
29
|
+
def running?
|
30
|
+
!@server.nil?
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Kawaii
|
2
|
+
# Class used to implement a standalone Kawaii app generated with top-level
|
3
|
+
# route helpers (e.g. monkey-patched onto the `main` object).
|
4
|
+
#
|
5
|
+
# This lets you create a .rb file containing just route definitions and run it
|
6
|
+
# with `ruby` command.
|
7
|
+
#
|
8
|
+
# @example test.rb
|
9
|
+
# require 'kawaii'
|
10
|
+
#
|
11
|
+
# get '/' do
|
12
|
+
# 'Hello, world'
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# @example Running from command line
|
16
|
+
# ruby -r kawaii test.rb
|
17
|
+
# ...
|
18
|
+
#
|
19
|
+
class SingletonApp < Base
|
20
|
+
class << self
|
21
|
+
def maybe_start!(port)
|
22
|
+
# Give routes a chance to install and app to initialize.
|
23
|
+
at_exit { start!(port) unless $ERROR_INFO } if !running? && run_direct?
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
|
28
|
+
def run_direct?
|
29
|
+
c = caller_locations.map(&:path).find { |path| !skip_caller?(path) }
|
30
|
+
File.identical?($PROGRAM_NAME, c)
|
31
|
+
end
|
32
|
+
|
33
|
+
def skip_caller?(path)
|
34
|
+
File.identical?(path, __FILE__) ||
|
35
|
+
path[%r{rubygems/core_ext/kernel_require\.rb$}] ||
|
36
|
+
path[%r{/kawaii.rb$}]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Helpers you use directly in a .rb file without using a class
|
43
|
+
# inheriting from {Base}.
|
44
|
+
#
|
45
|
+
# @example hello_world.rb
|
46
|
+
# get '/' do
|
47
|
+
# 'Hello, world'
|
48
|
+
# end
|
49
|
+
class << self
|
50
|
+
include Kawaii::RoutingMethods
|
51
|
+
|
52
|
+
def routes
|
53
|
+
Kawaii::SingletonApp.routes # Add route handlers to {SingletonApp}
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# For self-contained execution without config.ru. See {SingletonApp} above.
|
58
|
+
Kawaii::SingletonApp.maybe_start!(8088) # @todo Hard-coded port number.
|
metadata
ADDED
@@ -0,0 +1,193 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: kawaii-core
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Marcin Bilski
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-11-27 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rack
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.6'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: tilt
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.10'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.10'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '10.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '10.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '3.4'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3.4'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: guard-rspec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '4.6'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '4.6'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rack-test
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0.6'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0.6'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: yard
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0.8'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0.8'
|
125
|
+
description: Kawaii is a basic but extensible web framework based on Rack
|
126
|
+
email:
|
127
|
+
- gyamtso@gmail.com
|
128
|
+
executables: []
|
129
|
+
extensions: []
|
130
|
+
extra_rdoc_files: []
|
131
|
+
files:
|
132
|
+
- ".gitignore"
|
133
|
+
- ".rspec"
|
134
|
+
- ".travis.yml"
|
135
|
+
- Gemfile
|
136
|
+
- Guardfile
|
137
|
+
- LICENSE.txt
|
138
|
+
- README.md
|
139
|
+
- Rakefile
|
140
|
+
- bin/console
|
141
|
+
- bin/setup
|
142
|
+
- examples/controller.ru
|
143
|
+
- examples/hello_world.rb
|
144
|
+
- examples/hello_world.ru
|
145
|
+
- examples/modular.ru
|
146
|
+
- examples/modular/first_app.rb
|
147
|
+
- examples/modular/second_app.rb
|
148
|
+
- examples/nested_routes.rb
|
149
|
+
- examples/views.ru
|
150
|
+
- examples/views/index.html.erb
|
151
|
+
- kawaii-core.gemspec
|
152
|
+
- lib/kawaii.rb
|
153
|
+
- lib/kawaii/base.rb
|
154
|
+
- lib/kawaii/controller.rb
|
155
|
+
- lib/kawaii/core_ext/hash.rb
|
156
|
+
- lib/kawaii/core_ext/string.rb
|
157
|
+
- lib/kawaii/matchers.rb
|
158
|
+
- lib/kawaii/method_chain.rb
|
159
|
+
- lib/kawaii/render_methods.rb
|
160
|
+
- lib/kawaii/route.rb
|
161
|
+
- lib/kawaii/route_context.rb
|
162
|
+
- lib/kawaii/route_handler.rb
|
163
|
+
- lib/kawaii/route_mapping.rb
|
164
|
+
- lib/kawaii/routing_methods.rb
|
165
|
+
- lib/kawaii/server_methods.rb
|
166
|
+
- lib/kawaii/singleton_app.rb
|
167
|
+
- lib/kawaii/version.rb
|
168
|
+
homepage: https://github.com/bilus/kawaii
|
169
|
+
licenses:
|
170
|
+
- MIT
|
171
|
+
metadata: {}
|
172
|
+
post_install_message:
|
173
|
+
rdoc_options: []
|
174
|
+
require_paths:
|
175
|
+
- lib
|
176
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
181
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
182
|
+
requirements:
|
183
|
+
- - ">="
|
184
|
+
- !ruby/object:Gem::Version
|
185
|
+
version: '0'
|
186
|
+
requirements: []
|
187
|
+
rubyforge_project:
|
188
|
+
rubygems_version: 2.2.2
|
189
|
+
signing_key:
|
190
|
+
specification_version: 4
|
191
|
+
summary: Kawaii is a simple web framework based on Rack
|
192
|
+
test_files: []
|
193
|
+
has_rdoc:
|