mustermann 0.4.0 → 1.0.0.beta2
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/README.md +61 -46
- data/lib/mustermann.rb +3 -2
- data/lib/mustermann/ast/compiler.rb +2 -0
- data/lib/mustermann/ast/node.rb +4 -0
- data/lib/mustermann/ast/parser.rb +1 -22
- data/lib/mustermann/ast/pattern.rb +3 -3
- data/lib/mustermann/ast/transformer.rb +53 -4
- data/lib/mustermann/caster.rb +2 -10
- data/lib/mustermann/composite.rb +13 -3
- data/lib/mustermann/concat.rb +124 -0
- data/lib/mustermann/equality_map.rb +60 -0
- data/lib/mustermann/expander.rb +10 -6
- data/lib/mustermann/identity.rb +1 -0
- data/lib/mustermann/pattern.rb +53 -7
- data/lib/mustermann/regexp_based.rb +1 -1
- data/lib/mustermann/regular.rb +17 -2
- data/lib/mustermann/simple_match.rb +18 -5
- data/lib/mustermann/sinatra.rb +64 -16
- data/lib/mustermann/sinatra/parser.rb +45 -0
- data/lib/mustermann/sinatra/safe_renderer.rb +26 -0
- data/lib/mustermann/sinatra/try_convert.rb +48 -0
- data/lib/mustermann/version.rb +1 -1
- data/mustermann.gemspec +1 -2
- data/spec/composite_spec.rb +20 -5
- data/spec/concat_spec.rb +114 -0
- data/spec/equality_map_spec.rb +25 -0
- data/spec/mustermann_spec.rb +8 -5
- data/spec/regular_spec.rb +40 -0
- data/spec/sinatra_spec.rb +85 -5
- metadata +15 -42
- data/lib/mustermann/router.rb +0 -9
- data/lib/mustermann/router/rack.rb +0 -47
- data/lib/mustermann/router/simple.rb +0 -142
- data/spec/router/rack_spec.rb +0 -39
- data/spec/router/simple_spec.rb +0 -32
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mustermann
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0.beta2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Konstantin Haase
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
12
|
-
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: tool
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '0.2'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - "~>"
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '0.2'
|
11
|
+
date: 2016-08-22 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
27
13
|
description: library implementing patterns that behave like regular expressions
|
28
14
|
email: konstantin.mailinglists@googlemail.com
|
29
15
|
executables: []
|
@@ -49,6 +35,8 @@ files:
|
|
49
35
|
- lib/mustermann/ast/validation.rb
|
50
36
|
- lib/mustermann/caster.rb
|
51
37
|
- lib/mustermann/composite.rb
|
38
|
+
- lib/mustermann/concat.rb
|
39
|
+
- lib/mustermann/equality_map.rb
|
52
40
|
- lib/mustermann/error.rb
|
53
41
|
- lib/mustermann/expander.rb
|
54
42
|
- lib/mustermann/extension.rb
|
@@ -59,16 +47,18 @@ files:
|
|
59
47
|
- lib/mustermann/regexp.rb
|
60
48
|
- lib/mustermann/regexp_based.rb
|
61
49
|
- lib/mustermann/regular.rb
|
62
|
-
- lib/mustermann/router.rb
|
63
|
-
- lib/mustermann/router/rack.rb
|
64
|
-
- lib/mustermann/router/simple.rb
|
65
50
|
- lib/mustermann/simple_match.rb
|
66
51
|
- lib/mustermann/sinatra.rb
|
52
|
+
- lib/mustermann/sinatra/parser.rb
|
53
|
+
- lib/mustermann/sinatra/safe_renderer.rb
|
54
|
+
- lib/mustermann/sinatra/try_convert.rb
|
67
55
|
- lib/mustermann/to_pattern.rb
|
68
56
|
- lib/mustermann/version.rb
|
69
57
|
- mustermann.gemspec
|
70
58
|
- spec/ast_spec.rb
|
71
59
|
- spec/composite_spec.rb
|
60
|
+
- spec/concat_spec.rb
|
61
|
+
- spec/equality_map_spec.rb
|
72
62
|
- spec/expander_spec.rb
|
73
63
|
- spec/extension_spec.rb
|
74
64
|
- spec/identity_spec.rb
|
@@ -77,8 +67,6 @@ files:
|
|
77
67
|
- spec/pattern_spec.rb
|
78
68
|
- spec/regexp_based_spec.rb
|
79
69
|
- spec/regular_spec.rb
|
80
|
-
- spec/router/rack_spec.rb
|
81
|
-
- spec/router/simple_spec.rb
|
82
70
|
- spec/simple_match_spec.rb
|
83
71
|
- spec/sinatra_spec.rb
|
84
72
|
- spec/to_pattern_spec.rb
|
@@ -94,32 +82,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
94
82
|
requirements:
|
95
83
|
- - ">="
|
96
84
|
- !ruby/object:Gem::Version
|
97
|
-
version: 2.
|
85
|
+
version: 2.2.0
|
98
86
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
87
|
requirements:
|
100
|
-
- - "
|
88
|
+
- - ">"
|
101
89
|
- !ruby/object:Gem::Version
|
102
|
-
version:
|
90
|
+
version: 1.3.1
|
103
91
|
requirements: []
|
104
92
|
rubyforge_project:
|
105
|
-
rubygems_version: 2.
|
93
|
+
rubygems_version: 2.5.1
|
106
94
|
signing_key:
|
107
95
|
specification_version: 4
|
108
96
|
summary: use patterns like regular expressions
|
109
|
-
test_files:
|
110
|
-
- spec/ast_spec.rb
|
111
|
-
- spec/composite_spec.rb
|
112
|
-
- spec/expander_spec.rb
|
113
|
-
- spec/extension_spec.rb
|
114
|
-
- spec/identity_spec.rb
|
115
|
-
- spec/mapper_spec.rb
|
116
|
-
- spec/mustermann_spec.rb
|
117
|
-
- spec/pattern_spec.rb
|
118
|
-
- spec/regexp_based_spec.rb
|
119
|
-
- spec/regular_spec.rb
|
120
|
-
- spec/router/rack_spec.rb
|
121
|
-
- spec/router/simple_spec.rb
|
122
|
-
- spec/simple_match_spec.rb
|
123
|
-
- spec/sinatra_spec.rb
|
124
|
-
- spec/to_pattern_spec.rb
|
97
|
+
test_files: []
|
125
98
|
has_rdoc:
|
data/lib/mustermann/router.rb
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
require 'mustermann/router/simple'
|
2
|
-
|
3
|
-
module Mustermann
|
4
|
-
module Router
|
5
|
-
# Simple pattern based router that allows matching paths to a given Rack application.
|
6
|
-
#
|
7
|
-
# @example config.ru
|
8
|
-
# router = Mustermann::Rack.new do
|
9
|
-
# on '/' do |env|
|
10
|
-
# [200, {'Content-Type' => 'text/plain'}, ['Hello World!']]
|
11
|
-
# end
|
12
|
-
#
|
13
|
-
# on '/:name' do |env|
|
14
|
-
# name = env['mustermann.params']['name']
|
15
|
-
# [200, {'Content-Type' => 'text/plain'}, ["Hello #{name}!"]]
|
16
|
-
# end
|
17
|
-
#
|
18
|
-
# on '/something/*', call: SomeApp
|
19
|
-
# end
|
20
|
-
#
|
21
|
-
# # in a config.ru
|
22
|
-
# run router
|
23
|
-
class Rack < Simple
|
24
|
-
def initialize(env_prefix: "mustermann", params_key: "#{env_prefix}.params", pattern_key: "#{env_prefix}.pattern", **options, &block)
|
25
|
-
@params_key, @pattern_key = params_key, pattern_key
|
26
|
-
options[:default] = [404, {"Content-Type" => "text/plain", "X-Cascade" => "pass"}, ["Not Found"]] unless options.include? :default
|
27
|
-
super(**options, &block)
|
28
|
-
end
|
29
|
-
|
30
|
-
def invoke(callback, env, params, pattern)
|
31
|
-
params_was, pattern_was = env[@params_key], env[@pattern_key]
|
32
|
-
env[@params_key], env[@pattern_key] = params, pattern
|
33
|
-
response = callback.call(env)
|
34
|
-
response[1].each { |k,v| throw :pass if k.downcase == 'x-cascade' and v == 'pass' }
|
35
|
-
response
|
36
|
-
ensure
|
37
|
-
env[@params_key], env[@pattern_key] = params_was, pattern_was
|
38
|
-
end
|
39
|
-
|
40
|
-
def string_for(env)
|
41
|
-
env['PATH_INFO']
|
42
|
-
end
|
43
|
-
|
44
|
-
private :invoke, :string_for
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
@@ -1,142 +0,0 @@
|
|
1
|
-
require 'mustermann'
|
2
|
-
|
3
|
-
module Mustermann
|
4
|
-
module Router
|
5
|
-
# Simple pattern based router that allows matching a string to a given callback.
|
6
|
-
#
|
7
|
-
# @example
|
8
|
-
# require 'mustermann/router/simple'
|
9
|
-
#
|
10
|
-
# router = Mustermann::Router::Simple.new do
|
11
|
-
# on ':name/:sub' do |string, params|
|
12
|
-
# params['sub']
|
13
|
-
# end
|
14
|
-
#
|
15
|
-
# on 'foo' do
|
16
|
-
# "bar"
|
17
|
-
# end
|
18
|
-
# end
|
19
|
-
#
|
20
|
-
# router.call("foo") # => "bar"
|
21
|
-
# router.call("a/b") # => "b"
|
22
|
-
# router.call("bar") # => nil
|
23
|
-
class Simple
|
24
|
-
# Default value for when no pattern matches
|
25
|
-
attr_accessor :default
|
26
|
-
|
27
|
-
# @example with a default value
|
28
|
-
# require 'mustermann/router/simple'
|
29
|
-
#
|
30
|
-
# router = Mustermann::Router::Simple.new(default: 42)
|
31
|
-
# router.on(':name', capture: :digit) { |string| string.to_i }
|
32
|
-
# router.call("23") # => 23
|
33
|
-
# router.call("example") # => 42
|
34
|
-
#
|
35
|
-
# @example block with implicit receiver
|
36
|
-
# require 'mustermann/router/simple'
|
37
|
-
#
|
38
|
-
# router = Mustermann::Router::Simple.new do
|
39
|
-
# on('/foo') { 'foo' }
|
40
|
-
# on('/bar') { 'bar' }
|
41
|
-
# end
|
42
|
-
#
|
43
|
-
# @example block with explicit receiver
|
44
|
-
# require 'mustermann/router/simple'
|
45
|
-
#
|
46
|
-
# router = Mustermann::Router::Simple.new(type: :rails) do |r|
|
47
|
-
# r.on('/foo') { 'foo' }
|
48
|
-
# r.on('/bar') { 'bar' }
|
49
|
-
# end
|
50
|
-
#
|
51
|
-
# @param default value to be returned if nothing matches
|
52
|
-
# @param options [Hash] pattern options
|
53
|
-
# @return [Mustermann::Router::Simple] new router instance
|
54
|
-
def initialize(default: nil, **options, &block)
|
55
|
-
@options = options
|
56
|
-
@map = []
|
57
|
-
@default = default
|
58
|
-
|
59
|
-
block.arity == 0 ? instance_eval(&block) : yield(self) if block
|
60
|
-
end
|
61
|
-
|
62
|
-
# @example
|
63
|
-
# require 'mustermann/router/simple'
|
64
|
-
#
|
65
|
-
# router = Mustermann::Router::Simple.new
|
66
|
-
# router.on(':a/:b') { 42 }
|
67
|
-
# router['foo/bar'] # => <#Proc:...>
|
68
|
-
# router['foo_bar'] # => nil
|
69
|
-
#
|
70
|
-
# @return [#call, nil] callback for given string, if a pattern matches
|
71
|
-
def [](string)
|
72
|
-
string = string_for(string) unless string.is_a? String
|
73
|
-
@map.detect { |p,v| p === string }[1]
|
74
|
-
end
|
75
|
-
|
76
|
-
# @example
|
77
|
-
# require 'mustermann/router/simple'
|
78
|
-
#
|
79
|
-
# router = Mustermann::Router::Simple.new
|
80
|
-
# router['/:name'] = proc { |string, params| params['name'] }
|
81
|
-
# router.call('/foo') # => "foo"
|
82
|
-
#
|
83
|
-
# @param pattern [String, Mustermann::Pattern] matcher
|
84
|
-
# @param callback [#call] callback to call on match
|
85
|
-
# @see #on
|
86
|
-
def []=(pattern, callback)
|
87
|
-
on(pattern, call: callback)
|
88
|
-
end
|
89
|
-
|
90
|
-
# @example with block
|
91
|
-
# require 'mustermann/router/simple'
|
92
|
-
#
|
93
|
-
# router = Mustermann::Router::Simple.new
|
94
|
-
#
|
95
|
-
# router.on(':a/:b') { 42 }
|
96
|
-
# router.call('foo/bar') # => 42
|
97
|
-
# router.call('foo_bar') # => nil
|
98
|
-
#
|
99
|
-
# @example with callback option
|
100
|
-
# require 'mustermann/router/simple'
|
101
|
-
#
|
102
|
-
# callback = proc { 42 }
|
103
|
-
# router = Mustermann::Router::Simple.new
|
104
|
-
#
|
105
|
-
# router.on(':a/:b', call: callback)
|
106
|
-
# router.call('foo/bar') # => 42
|
107
|
-
# router.call('foo_bar') # => nil
|
108
|
-
#
|
109
|
-
# @param patterns [Array<String, Pattern>]
|
110
|
-
# @param call [#call] callback object, need to hand in block if missing
|
111
|
-
# @param options [Hash] pattern options
|
112
|
-
def on(*patterns, call: Proc.new, **options)
|
113
|
-
patterns.each do |pattern|
|
114
|
-
pattern = Mustermann.new(pattern.to_str, **options, **@options) if pattern.respond_to? :to_str
|
115
|
-
@map << [pattern, call]
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
# Finds the matching callback and calls `call` on it with the given input and the params.
|
120
|
-
# @return the callback's return value
|
121
|
-
def call(input)
|
122
|
-
@map.each do |pattern, callback|
|
123
|
-
catch(:pass) do
|
124
|
-
next unless params = pattern.params(string_for(input))
|
125
|
-
return invoke(callback, input, params, pattern)
|
126
|
-
end
|
127
|
-
end
|
128
|
-
@default
|
129
|
-
end
|
130
|
-
|
131
|
-
def invoke(callback, input, params, pattern)
|
132
|
-
callback.call(input, params)
|
133
|
-
end
|
134
|
-
|
135
|
-
def string_for(input)
|
136
|
-
input.to_str
|
137
|
-
end
|
138
|
-
|
139
|
-
private :invoke, :string_for
|
140
|
-
end
|
141
|
-
end
|
142
|
-
end
|
data/spec/router/rack_spec.rb
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
require 'mustermann/router/rack'
|
2
|
-
|
3
|
-
describe Mustermann::Router::Rack do
|
4
|
-
include Rack::Test::Methods
|
5
|
-
subject(:app) { Mustermann::Router::Rack.new }
|
6
|
-
|
7
|
-
context 'matching' do
|
8
|
-
before { app.on('/foo') { [418, {'Content-Type' => 'text/plain'}, 'bar'] } }
|
9
|
-
example { get('/foo').status.should be == 418 }
|
10
|
-
example { get('/bar').status.should be == 404 }
|
11
|
-
end
|
12
|
-
|
13
|
-
context "params" do
|
14
|
-
before { app.on('/:name') { |e| [200, {'Content-Type' => 'text/plain'}, e['mustermann.params']['name']] } }
|
15
|
-
example { get('/foo').body.should be == 'foo' }
|
16
|
-
example { get('/bar').body.should be == 'bar' }
|
17
|
-
end
|
18
|
-
|
19
|
-
context 'X-Cascade: pass' do
|
20
|
-
before do
|
21
|
-
app.on('/') { [200, { 'X-Cascade' => 'pass' }, ['a']] }
|
22
|
-
app.on('/') { [200, { 'x-cascade' => 'pass' }, ['b']] }
|
23
|
-
app.on('/') { [200, { 'Content-Type' => 'text/plain' }, ['c']] }
|
24
|
-
app.on('/') { [200, { 'Content-Type' => 'text/plain' }, ['d']] }
|
25
|
-
end
|
26
|
-
|
27
|
-
example { get('/').body.should be == 'c' }
|
28
|
-
end
|
29
|
-
|
30
|
-
context 'throw :pass' do
|
31
|
-
before do
|
32
|
-
app.on('/') { throw :pass }
|
33
|
-
app.on('/') { [200, { 'Content-Type' => 'text/plain' }, ['b']] }
|
34
|
-
app.on('/') { [200, { 'Content-Type' => 'text/plain' }, ['c']] }
|
35
|
-
end
|
36
|
-
|
37
|
-
example { get('/').body.should be == 'b' }
|
38
|
-
end
|
39
|
-
end
|
data/spec/router/simple_spec.rb
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
require 'mustermann/router/simple'
|
2
|
-
|
3
|
-
describe Mustermann::Router::Simple do
|
4
|
-
describe :initialize do
|
5
|
-
context "with implicit receiver" do
|
6
|
-
subject(:router) { Mustermann::Router::Simple.new { on('/foo') { 'bar' } } }
|
7
|
-
example { router.call('/foo').should be == 'bar' }
|
8
|
-
end
|
9
|
-
|
10
|
-
context "with explicit receiver" do
|
11
|
-
subject(:router) { Mustermann::Router::Simple.new { |r| r.on('/foo') { 'bar' } } }
|
12
|
-
example { router.call('/foo').should be == 'bar' }
|
13
|
-
end
|
14
|
-
|
15
|
-
context "with default" do
|
16
|
-
subject(:router) { Mustermann::Router::Simple.new(default: 'bar') }
|
17
|
-
example { router.call('/foo').should be == 'bar' }
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
describe :[]= do
|
22
|
-
subject(:router) { Mustermann::Router::Simple.new }
|
23
|
-
before { router['/:name'] = proc { |*a| a } }
|
24
|
-
example { router.call('/foo').should be == ['/foo', "name" => 'foo'] }
|
25
|
-
end
|
26
|
-
|
27
|
-
describe :[] do
|
28
|
-
subject(:router) { Mustermann::Router::Simple.new }
|
29
|
-
before { router.on('/x') { 42 } }
|
30
|
-
example { router['/x'].call.should be == 42 }
|
31
|
-
end
|
32
|
-
end
|