mustermann-simple 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +76 -0
- data/lib/mustermann/simple.rb +50 -0
- data/mustermann-simple.gemspec +18 -0
- data/spec/simple_spec.rb +268 -0
- metadata +63 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1ea32ffc659a85d4e2f1f0670e2f187b119f0ec0
|
4
|
+
data.tar.gz: c3079a0b6784c514512e7a6f9d71bd8c809ceb6e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: cefc68dec41e61edaf025029c447a192f44d01d95abe405505dc8554a94823d95e722a39d54149b8c90978a21a83676afc37b6cdb35021e5821bf8e099eb613b
|
7
|
+
data.tar.gz: 12a7a8d205961cd6a41e74f0b5acf183cda02b0f59dd476d224c156e6e564d56eb5c4214ff9d9030526ca4f02c183cbe69c853a44bab63cce10343ff58483935
|
data/README.md
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
# Simple Syntax for Mustermann
|
2
|
+
|
3
|
+
This gem implements the `simple` pattern type for Mustermann. It is compatible with [Sinatra](http://www.sinatrarb.com/) (1.x), [Scalatra](http://www.scalatra.org/) and [Dancer](http://perldancer.org/).
|
4
|
+
|
5
|
+
## Overview
|
6
|
+
|
7
|
+
**Supported options:**
|
8
|
+
`greedy`, `space_matches_plus`, `uri_decode` and `ignore_unknown_options`.
|
9
|
+
|
10
|
+
This is useful for porting an application that relies on this behavior to a later Sinatra version and to make sure Sinatra 2.0 patterns do not decrease performance. Simple patterns internally use the same code older Sinatra versions used for compiling the pattern. Error messages for broken patterns will therefore not be as informative as for other pattern implementations.
|
11
|
+
|
12
|
+
``` ruby
|
13
|
+
require 'mustermann'
|
14
|
+
|
15
|
+
pattern = Mustermann.new('/:example', type: :simple)
|
16
|
+
pattern === "/foo.bar" # => true
|
17
|
+
pattern === "/foo/bar" # => false
|
18
|
+
pattern.params("/foo.bar") # => { "example" => "foo.bar" }
|
19
|
+
pattern.params("/foo/bar") # => nil
|
20
|
+
|
21
|
+
pattern = Mustermann.new('/:example/?:optional?', type: :simple)
|
22
|
+
pattern === "/foo.bar" # => true
|
23
|
+
pattern === "/foo/bar" # => true
|
24
|
+
pattern.params("/foo.bar") # => { "example" => "foo.bar", "optional" => nil }
|
25
|
+
pattern.params("/foo/bar") # => { "example" => "foo", "optional" => "bar" }
|
26
|
+
|
27
|
+
pattern = Mustermann.new('/*', type: :simple)
|
28
|
+
pattern === "/foo.bar" # => true
|
29
|
+
pattern === "/foo/bar" # => true
|
30
|
+
pattern.params("/foo.bar") # => { "splat" => ["foo.bar"] }
|
31
|
+
pattern.params("/foo/bar") # => { "splat" => ["foo/bar"] }
|
32
|
+
```
|
33
|
+
|
34
|
+
## Syntax
|
35
|
+
|
36
|
+
<table>
|
37
|
+
<thead>
|
38
|
+
<tr>
|
39
|
+
<th>Syntax Element</th>
|
40
|
+
<th>Description</th>
|
41
|
+
</tr>
|
42
|
+
</thead>
|
43
|
+
<tbody>
|
44
|
+
<tr>
|
45
|
+
<td><b>:</b><i>name</i></td>
|
46
|
+
<td>
|
47
|
+
Captures anything but a forward slash in a greedy fashion. Capture is named <i>name</i>.
|
48
|
+
</td>
|
49
|
+
</tr>
|
50
|
+
<tr>
|
51
|
+
<td><b>*</b></td>
|
52
|
+
<td>
|
53
|
+
Captures anything in a non-greedy fashion. Capture is named splat.
|
54
|
+
It is always an array of captures, as you can use <tt>*</tt> more than once in a pattern.
|
55
|
+
</td>
|
56
|
+
</tr>
|
57
|
+
<tr>
|
58
|
+
<td><i>x</i><b>?</b></td>
|
59
|
+
<td>Makes <i>x</i> optional. For instance <tt>foo?</tt> matches <tt>foo</tt> or <tt>fo</tt>.</td>
|
60
|
+
</tr>
|
61
|
+
<tr>
|
62
|
+
<td><b>/</b></td>
|
63
|
+
<td>
|
64
|
+
Matches forward slash. Does not match URI encoded version of forward slash.
|
65
|
+
</td>
|
66
|
+
</tr>
|
67
|
+
<tr>
|
68
|
+
<td><i>any special character</i></td>
|
69
|
+
<td>Matches exactly that character or a URI encoded version of it.</td>
|
70
|
+
</tr>
|
71
|
+
<tr>
|
72
|
+
<td><i>any other character</i></td>
|
73
|
+
<td>Matches exactly that character.</td>
|
74
|
+
</tr>
|
75
|
+
</tbody>
|
76
|
+
</table>
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'mustermann'
|
2
|
+
require 'mustermann/regexp_based'
|
3
|
+
|
4
|
+
module Mustermann
|
5
|
+
# Sinatra 1.3 style pattern implementation.
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# Mustermann.new('/:foo', type: :simple) === '/bar' # => true
|
9
|
+
#
|
10
|
+
# @see Mustermann::Pattern
|
11
|
+
# @see file:README.md#simple Syntax description in the README
|
12
|
+
class Simple < RegexpBased
|
13
|
+
register :simple
|
14
|
+
supported_options :greedy, :space_matches_plus
|
15
|
+
instance_delegate highlighter: 'self.class'
|
16
|
+
|
17
|
+
# @!visibility private
|
18
|
+
# @return [#highlight, nil]
|
19
|
+
# highlighing logic for mustermann-visualizer,
|
20
|
+
# nil if mustermann-visualizer hasn't been loaded
|
21
|
+
def self.highlighter
|
22
|
+
return unless defined? Mustermann::Visualizer::Highlighter
|
23
|
+
@highlighter ||= Mustermann::Visualizer::Highlighter.create do
|
24
|
+
on(/:(\w+)/) { |matched| element(:capture, ':') { element(:name, matched[1..-1]) } }
|
25
|
+
on("*" => :splat, "?" => :optional)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def compile(greedy: true, uri_decode: true, space_matches_plus: true, **options)
|
30
|
+
pattern = @string.gsub(/[^\?\%\\\/\:\*\w]/) { |c| encoded(c, uri_decode, space_matches_plus) }
|
31
|
+
pattern.gsub!(/((:\w+)|\*)/) do |match|
|
32
|
+
match == "*" ? "(?<splat>.*?)" : "(?<#{$2[1..-1]}>[^/?#]+#{?? unless greedy})"
|
33
|
+
end
|
34
|
+
Regexp.new(pattern)
|
35
|
+
rescue SyntaxError, RegexpError => error
|
36
|
+
type = error.message["invalid group name"] ? CompileError : ParseError
|
37
|
+
raise type, error.message, error.backtrace
|
38
|
+
end
|
39
|
+
|
40
|
+
def encoded(char, uri_decode, space_matches_plus)
|
41
|
+
return Regexp.escape(char) unless uri_decode
|
42
|
+
parser = URI::Parser.new
|
43
|
+
encoded = Regexp.union(parser.escape(char), parser.escape(char, /./).downcase, parser.escape(char, /./).upcase)
|
44
|
+
encoded = Regexp.union(encoded, encoded('+', true, true)) if space_matches_plus and char == " "
|
45
|
+
encoded
|
46
|
+
end
|
47
|
+
|
48
|
+
private :compile, :encoded
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
$:.unshift File.expand_path("../../mustermann/lib", __FILE__)
|
2
|
+
require "mustermann/version"
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "mustermann-simple"
|
6
|
+
s.version = Mustermann::VERSION
|
7
|
+
s.author = "Konstantin Haase"
|
8
|
+
s.email = "konstantin.mailinglists@googlemail.com"
|
9
|
+
s.homepage = "https://github.com/rkh/mustermann"
|
10
|
+
s.summary = %q{Simple syntax for Mustermann}
|
11
|
+
s.description = %q{Adds Sinatra 1.x style patterns to Mustermman}
|
12
|
+
s.license = 'MIT'
|
13
|
+
s.required_ruby_version = '>= 2.1.0'
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
|
+
s.add_dependency 'mustermann', Mustermann::VERSION
|
18
|
+
end
|
data/spec/simple_spec.rb
ADDED
@@ -0,0 +1,268 @@
|
|
1
|
+
require 'support'
|
2
|
+
require 'mustermann/simple'
|
3
|
+
require 'mustermann/visualizer'
|
4
|
+
|
5
|
+
describe Mustermann::Simple do
|
6
|
+
extend Support::Pattern
|
7
|
+
|
8
|
+
pattern '' do
|
9
|
+
it { should match('') }
|
10
|
+
it { should_not match('/') }
|
11
|
+
|
12
|
+
it { should_not respond_to(:expand) }
|
13
|
+
it { should_not respond_to(:to_templates) }
|
14
|
+
end
|
15
|
+
|
16
|
+
pattern '/' do
|
17
|
+
it { should match('/') }
|
18
|
+
it { should_not match('/foo') }
|
19
|
+
end
|
20
|
+
|
21
|
+
pattern '/foo' do
|
22
|
+
it { should match('/foo') }
|
23
|
+
it { should_not match('/bar') }
|
24
|
+
it { should_not match('/foo.bar') }
|
25
|
+
end
|
26
|
+
|
27
|
+
pattern '/foo/bar' do
|
28
|
+
it { should match('/foo/bar') }
|
29
|
+
it { should_not match('/foo%2Fbar') }
|
30
|
+
it { should_not match('/foo%2fbar') }
|
31
|
+
end
|
32
|
+
|
33
|
+
pattern '/:foo' do
|
34
|
+
it { should match('/foo') .capturing foo: 'foo' }
|
35
|
+
it { should match('/bar') .capturing foo: 'bar' }
|
36
|
+
it { should match('/foo.bar') .capturing foo: 'foo.bar' }
|
37
|
+
it { should match('/%0Afoo') .capturing foo: '%0Afoo' }
|
38
|
+
it { should match('/foo%2Fbar') .capturing foo: 'foo%2Fbar' }
|
39
|
+
|
40
|
+
it { should_not match('/foo?') }
|
41
|
+
it { should_not match('/foo/bar') }
|
42
|
+
it { should_not match('/') }
|
43
|
+
it { should_not match('/foo/') }
|
44
|
+
end
|
45
|
+
|
46
|
+
pattern '/föö' do
|
47
|
+
it { should match("/f%C3%B6%C3%B6") }
|
48
|
+
end
|
49
|
+
|
50
|
+
pattern "/:foo/:bar" do
|
51
|
+
it { should match('/foo/bar') .capturing foo: 'foo', bar: 'bar' }
|
52
|
+
it { should match('/foo.bar/bar.foo') .capturing foo: 'foo.bar', bar: 'bar.foo' }
|
53
|
+
it { should match('/user@example.com/name') .capturing foo: 'user@example.com', bar: 'name' }
|
54
|
+
it { should match('/10.1/te.st') .capturing foo: '10.1', bar: 'te.st' }
|
55
|
+
it { should match('/10.1.2/te.st') .capturing foo: '10.1.2', bar: 'te.st' }
|
56
|
+
|
57
|
+
it { should_not match('/foo%2Fbar') }
|
58
|
+
it { should_not match('/foo%2fbar') }
|
59
|
+
|
60
|
+
example { pattern.params('/bar/foo').should be == {"foo" => "bar", "bar" => "foo"} }
|
61
|
+
example { pattern.params('').should be_nil }
|
62
|
+
end
|
63
|
+
|
64
|
+
pattern '/hello/:person' do
|
65
|
+
it { should match('/hello/Frank').capturing person: 'Frank' }
|
66
|
+
end
|
67
|
+
|
68
|
+
pattern '/?:foo?/?:bar?' do
|
69
|
+
it { should match('/hello/world') .capturing foo: 'hello', bar: 'world' }
|
70
|
+
it { should match('/hello') .capturing foo: 'hello', bar: nil }
|
71
|
+
it { should match('/') .capturing foo: nil, bar: nil }
|
72
|
+
it { should match('') .capturing foo: nil, bar: nil }
|
73
|
+
|
74
|
+
it { should_not match('/hello/world/') }
|
75
|
+
end
|
76
|
+
|
77
|
+
pattern '/*' do
|
78
|
+
it { should match('/') .capturing splat: '' }
|
79
|
+
it { should match('/foo') .capturing splat: 'foo' }
|
80
|
+
it { should match('/foo/bar') .capturing splat: 'foo/bar' }
|
81
|
+
|
82
|
+
example { pattern.params('/foo').should be == {"splat" => ["foo"]} }
|
83
|
+
end
|
84
|
+
|
85
|
+
pattern '/:foo/*' do
|
86
|
+
it { should match("/foo/bar/baz") .capturing foo: 'foo', splat: 'bar/baz' }
|
87
|
+
it { should match("/foo/") .capturing foo: 'foo', splat: '' }
|
88
|
+
it { should match('/h%20w/h%20a%20y') .capturing foo: 'h%20w', splat: 'h%20a%20y' }
|
89
|
+
it { should_not match('/foo') }
|
90
|
+
|
91
|
+
example { pattern.params('/bar/foo').should be == {"splat" => ["foo"], "foo" => "bar"} }
|
92
|
+
example { pattern.params('/bar/foo/f%20o').should be == {"splat" => ["foo/f o"], "foo" => "bar"} }
|
93
|
+
end
|
94
|
+
|
95
|
+
pattern '/test$/' do
|
96
|
+
it { should match('/test$/') }
|
97
|
+
end
|
98
|
+
|
99
|
+
pattern '/te+st/' do
|
100
|
+
it { should match('/te+st/') }
|
101
|
+
it { should_not match('/test/') }
|
102
|
+
it { should_not match('/teest/') }
|
103
|
+
end
|
104
|
+
|
105
|
+
pattern "/path with spaces" do
|
106
|
+
it { should match('/path%20with%20spaces') }
|
107
|
+
it { should match('/path%2Bwith%2Bspaces') }
|
108
|
+
it { should match('/path+with+spaces') }
|
109
|
+
end
|
110
|
+
|
111
|
+
pattern '/foo&bar' do
|
112
|
+
it { should match('/foo&bar') }
|
113
|
+
end
|
114
|
+
|
115
|
+
pattern '/*/:foo/*/*' do
|
116
|
+
it { should match('/bar/foo/bling/baz/boom') }
|
117
|
+
|
118
|
+
it "should capture all splat parts" do
|
119
|
+
match = pattern.match('/bar/foo/bling/baz/boom')
|
120
|
+
match.captures.should be == ['bar', 'foo', 'bling', 'baz/boom']
|
121
|
+
match.names.should be == ['splat', 'foo']
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'should map to proper params' do
|
125
|
+
pattern.params('/bar/foo/bling/baz/boom').should be == {
|
126
|
+
"foo" => "foo", "splat" => ['bar', 'bling', 'baz/boom']
|
127
|
+
}
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
pattern '/test.bar' do
|
132
|
+
it { should match('/test.bar') }
|
133
|
+
it { should_not match('/test0bar') }
|
134
|
+
end
|
135
|
+
|
136
|
+
pattern '/:file.:ext' do
|
137
|
+
it { should match('/pony.jpg') .capturing file: 'pony', ext: 'jpg' }
|
138
|
+
it { should match('/pony%2Ejpg') .capturing file: 'pony', ext: 'jpg' }
|
139
|
+
it { should match('/pony%2ejpg') .capturing file: 'pony', ext: 'jpg' }
|
140
|
+
|
141
|
+
it { should match('/pony%E6%AD%A3%2Ejpg') .capturing file: 'pony%E6%AD%A3', ext: 'jpg' }
|
142
|
+
it { should match('/pony%e6%ad%a3%2ejpg') .capturing file: 'pony%e6%ad%a3', ext: 'jpg' }
|
143
|
+
it { should match('/pony正%2Ejpg') .capturing file: 'pony正', ext: 'jpg' }
|
144
|
+
it { should match('/pony正%2ejpg') .capturing file: 'pony正', ext: 'jpg' }
|
145
|
+
it { should match('/pony正..jpg') .capturing file: 'pony正.', ext: 'jpg' }
|
146
|
+
|
147
|
+
it { should_not match('/.jpg') }
|
148
|
+
end
|
149
|
+
|
150
|
+
pattern '/:id/test.bar' do
|
151
|
+
it { should match('/3/test.bar') .capturing id: '3' }
|
152
|
+
it { should match('/2/test.bar') .capturing id: '2' }
|
153
|
+
it { should match('/2E/test.bar') .capturing id: '2E' }
|
154
|
+
it { should match('/2e/test.bar') .capturing id: '2e' }
|
155
|
+
it { should match('/%2E/test.bar') .capturing id: '%2E' }
|
156
|
+
end
|
157
|
+
|
158
|
+
pattern '/10/:id' do
|
159
|
+
it { should match('/10/test') .capturing id: 'test' }
|
160
|
+
it { should match('/10/te.st') .capturing id: 'te.st' }
|
161
|
+
end
|
162
|
+
|
163
|
+
pattern '/10.1/:id' do
|
164
|
+
it { should match('/10.1/test') .capturing id: 'test' }
|
165
|
+
it { should match('/10.1/te.st') .capturing id: 'te.st' }
|
166
|
+
end
|
167
|
+
|
168
|
+
pattern '/foo?' do
|
169
|
+
it { should match('/fo') }
|
170
|
+
it { should match('/foo') }
|
171
|
+
it { should_not match('') }
|
172
|
+
it { should_not match('/') }
|
173
|
+
it { should_not match('/f') }
|
174
|
+
it { should_not match('/fooo') }
|
175
|
+
end
|
176
|
+
|
177
|
+
pattern '/:fOO' do
|
178
|
+
it { should match('/a').capturing fOO: 'a' }
|
179
|
+
end
|
180
|
+
|
181
|
+
pattern '/:_X' do
|
182
|
+
it { should match('/a').capturing _X: 'a' }
|
183
|
+
end
|
184
|
+
|
185
|
+
pattern '/:f00' do
|
186
|
+
it { should match('/a').capturing f00: 'a' }
|
187
|
+
end
|
188
|
+
|
189
|
+
pattern '/:foo.?' do
|
190
|
+
it { should match('/a.').capturing foo: 'a.' }
|
191
|
+
it { should match('/xy').capturing foo: 'xy' }
|
192
|
+
end
|
193
|
+
|
194
|
+
pattern '/(a)' do
|
195
|
+
it { should match('/(a)') }
|
196
|
+
it { should_not match('/a') }
|
197
|
+
end
|
198
|
+
|
199
|
+
pattern '/:foo.?', greedy: false do
|
200
|
+
it { should match('/a.').capturing foo: 'a' }
|
201
|
+
it { should match('/xy').capturing foo: 'xy' }
|
202
|
+
end
|
203
|
+
|
204
|
+
pattern '/foo?', uri_decode: false do
|
205
|
+
it { should match('/foo') }
|
206
|
+
it { should match('/fo') }
|
207
|
+
it { should_not match('/foo?') }
|
208
|
+
end
|
209
|
+
|
210
|
+
pattern '/foo/bar', uri_decode: false do
|
211
|
+
it { should match('/foo/bar') }
|
212
|
+
it { should_not match('/foo%2Fbar') }
|
213
|
+
it { should_not match('/foo%2fbar') }
|
214
|
+
end
|
215
|
+
|
216
|
+
pattern "/path with spaces", uri_decode: false do
|
217
|
+
it { should match('/path with spaces') }
|
218
|
+
it { should_not match('/path%20with%20spaces') }
|
219
|
+
it { should_not match('/path%2Bwith%2Bspaces') }
|
220
|
+
it { should_not match('/path+with+spaces') }
|
221
|
+
end
|
222
|
+
|
223
|
+
pattern "/path with spaces", space_matches_plus: false do
|
224
|
+
it { should match('/path%20with%20spaces') }
|
225
|
+
it { should_not match('/path%2Bwith%2Bspaces') }
|
226
|
+
it { should_not match('/path+with+spaces') }
|
227
|
+
end
|
228
|
+
|
229
|
+
context 'error handling' do
|
230
|
+
example '? at beginning of route' do
|
231
|
+
expect { Mustermann::Simple.new('?foobar') }.
|
232
|
+
to raise_error(Mustermann::ParseError)
|
233
|
+
end
|
234
|
+
|
235
|
+
example 'invalid capture name' do
|
236
|
+
expect { Mustermann::Simple.new('/:1a/') }.
|
237
|
+
to raise_error(Mustermann::CompileError)
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
context "peeking" do
|
242
|
+
subject(:pattern) { Mustermann::Simple.new(":name") }
|
243
|
+
|
244
|
+
describe :peek_size do
|
245
|
+
example { pattern.peek_size("foo bar/blah") .should be == "foo bar".size }
|
246
|
+
example { pattern.peek_size("foo%20bar/blah") .should be == "foo%20bar".size }
|
247
|
+
example { pattern.peek_size("/foo bar") .should be_nil }
|
248
|
+
end
|
249
|
+
|
250
|
+
describe :peek_match do
|
251
|
+
example { pattern.peek_match("foo bar/blah") .to_s .should be == "foo bar" }
|
252
|
+
example { pattern.peek_match("foo%20bar/blah") .to_s .should be == "foo%20bar" }
|
253
|
+
example { pattern.peek_match("/foo bar") .should be_nil }
|
254
|
+
end
|
255
|
+
|
256
|
+
describe :peek_params do
|
257
|
+
example { pattern.peek_params("foo bar/blah") .should be == [{"name" => "foo bar"}, "foo bar".size] }
|
258
|
+
example { pattern.peek_params("foo%20bar/blah") .should be == [{"name" => "foo bar"}, "foo%20bar".size] }
|
259
|
+
example { pattern.peek_params("/foo bar") .should be_nil }
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
context "highlighting" do
|
264
|
+
let(:pattern) { Mustermann::Simple.new("/:name?/*") }
|
265
|
+
subject(:sexp) { Mustermann::Visualizer.highlight(pattern).to_sexp }
|
266
|
+
it { should be == "(root (separator /) (capture : (name name)) (optional ?) (separator /) (splat *))" }
|
267
|
+
end
|
268
|
+
end
|
metadata
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mustermann-simple
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.4.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Konstantin Haase
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-11-25 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: mustermann
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.4.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.4.0
|
27
|
+
description: Adds Sinatra 1.x style patterns to Mustermman
|
28
|
+
email: konstantin.mailinglists@googlemail.com
|
29
|
+
executables: []
|
30
|
+
extensions: []
|
31
|
+
extra_rdoc_files: []
|
32
|
+
files:
|
33
|
+
- README.md
|
34
|
+
- lib/mustermann/simple.rb
|
35
|
+
- mustermann-simple.gemspec
|
36
|
+
- spec/simple_spec.rb
|
37
|
+
homepage: https://github.com/rkh/mustermann
|
38
|
+
licenses:
|
39
|
+
- MIT
|
40
|
+
metadata: {}
|
41
|
+
post_install_message:
|
42
|
+
rdoc_options: []
|
43
|
+
require_paths:
|
44
|
+
- lib
|
45
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: 2.1.0
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
requirements: []
|
56
|
+
rubyforge_project:
|
57
|
+
rubygems_version: 2.4.3
|
58
|
+
signing_key:
|
59
|
+
specification_version: 4
|
60
|
+
summary: Simple syntax for Mustermann
|
61
|
+
test_files:
|
62
|
+
- spec/simple_spec.rb
|
63
|
+
has_rdoc:
|