mustermann 1.1.1 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d7fdfa1980b36632e06c011f926b33f0d6d8812f72286004b2398a4f31dd9a82
4
- data.tar.gz: 7daa22487d1a56e826fef04f5f63ecef1d67484151612304402e5a01c7f4be33
3
+ metadata.gz: ea330a8bf09165e676628df2668f0afa5d8fd32372bb7b07ed6a286cf274f74c
4
+ data.tar.gz: 58b0252ef3ba1d5bd06b3dceab50c06ba011d98b9e2bc54c6caa314443fa722b
5
5
  SHA512:
6
- metadata.gz: 8d80afba1b13c99bcafc6862ad7dc195a0b8c0ac80279498fb9b8b75ecf6ea290cbe4b90f3f6f60d4e3c52f2f517f5a6059d05993c23179b6b2be22aaca320b8
7
- data.tar.gz: f109d137a09eeb9781c92bfd366b1b421b118753b20ff905f1ab7d161946f254de2e376541c9e74215a7215f30ce0589992a0790d6e6861ae8d5c9606beda08a
6
+ metadata.gz: f9e8638a1cb73cf39256c6cb422d4d1a4601a2d9348aba8361d31083103e0495a843d595b579f08d2614ba1b665b41959a79eaffd869348551a2cb558c1cf1ea
7
+ data.tar.gz: 5b569063e6dd7d3beb3bdd983d4f5c30a9d12ce7b5e06d0f1f215e56004ba678011df824d26a94d5dc136d957c7835e5bcc38081cbbda2d838cfe78b3ca00ec7
data/README.md CHANGED
@@ -377,30 +377,7 @@ mapper['/foo/bar'] # => "/foo/bar"
377
377
  <a name="-sinatra-integration"></a>
378
378
  ## Sinatra Integration
379
379
 
380
- All patterns implement `match`, which means they can be dropped into Sinatra and other Rack routers:
381
-
382
- ``` ruby
383
- require 'sinatra'
384
- require 'mustermann'
385
-
386
- get Mustermann.new('/:foo') do
387
- params[:foo]
388
- end
389
- ```
390
-
391
- In fact, since using this with Sinatra is the main use case, it comes with a build-in extension for **Sinatra 1.x**.
392
-
393
- ``` ruby
394
- require 'sinatra'
395
- require 'mustermann'
396
-
397
- register Mustermann
398
-
399
- # this will use Mustermann rather than the built-in pattern matching
400
- get '/:slug(.ext)?' do
401
- params[:slug]
402
- end
403
- ```
380
+ Mustermann is used in Sinatra by default since version 2.0, for previous versions an [extension](https://github.com/sinatra/mustermann-sinatra-extension) is available.
404
381
 
405
382
  ### Configuration
406
383
 
@@ -12,11 +12,11 @@ module Mustermann
12
12
  class Expander < Translator
13
13
  raises ExpandError
14
14
 
15
- translate Array do |*args|
15
+ translate(Array, &-> (*args) do
16
16
  inject(t.pattern) do |pattern, element|
17
17
  t.add_to(pattern, t(element, *args))
18
18
  end
19
- end
19
+ end.ruby2_keywords)
20
20
 
21
21
  translate :capture do |**options|
22
22
  t.for_capture(node, **options)
@@ -124,6 +124,8 @@ module Mustermann
124
124
  # @see Mustermann::AST::Translator#expand
125
125
  # @!visibility private
126
126
  ruby2_keywords def escape(string, *args)
127
+ return super unless string.respond_to?(:=~)
128
+
127
129
  # URI::Parser is pretty slow, let's not send every string to it, even if it's unnecessary
128
130
  string =~ /\A\w*\Z/ ? string : super
129
131
  end
@@ -35,8 +35,8 @@ module Mustermann
35
35
  # Helper for creating a new instance and calling #parse on it.
36
36
  # @return [Mustermann::AST::Node]
37
37
  # @!visibility private
38
- def self.parse(*args, &block)
39
- new(*args).tap { |n| n.parse(&block) }
38
+ def self.parse(payload = nil, **options, &block)
39
+ new(payload, **options).tap { |n| n.parse(&block) }
40
40
  end
41
41
 
42
42
  # @!visibility private
@@ -108,7 +108,7 @@ module Mustermann
108
108
  # @see Mustermann::AST::Node#parse
109
109
  # @!visibility private
110
110
  def parse
111
- self.payload ||= ""
111
+ self.payload ||= String.new
112
112
  super
113
113
  end
114
114
 
@@ -120,7 +120,7 @@ module Mustermann
120
120
  # @!visibility private
121
121
  def escape(char, parser: URI::DEFAULT_PARSER, escape: parser.regexp[:UNSAFE], also_escape: nil)
122
122
  escape = Regexp.union(also_escape, escape) if also_escape
123
- char =~ escape ? parser.escape(char, Regexp.union(*escape)) : char
123
+ char.to_s =~ escape ? parser.escape(char, Regexp.union(*escape)) : char
124
124
  end
125
125
  end
126
126
  end
@@ -1,50 +1,3 @@
1
1
  # frozen_string_literal: true
2
- require 'sinatra/version'
3
- fail "no need to load the Mustermann extension for #{::Sinatra::VERSION}" if ::Sinatra::VERSION >= '2.0.0'
4
2
 
5
- require 'mustermann'
6
-
7
- module Mustermann
8
- # Sinatra 1.x extension switching default pattern parsing over to Mustermann.
9
- #
10
- # @example With classic Sinatra application
11
- # require 'sinatra'
12
- # require 'mustermann'
13
- #
14
- # register Mustermann
15
- # get('/:id', capture: /\d+/) { ... }
16
- #
17
- # @example With modular Sinatra application
18
- # require 'sinatra/base'
19
- # require 'mustermann'
20
- #
21
- # class MyApp < Sinatra::Base
22
- # register Mustermann
23
- # get('/:id', capture: /\d+/) { ... }
24
- # end
25
- #
26
- # @see file:README.md#Sinatra_Integration "Sinatra Integration" in the README
27
- module Extension
28
- def compile!(verb, path, block, except: nil, capture: nil, pattern: { }, **options)
29
- if path.respond_to? :to_str
30
- pattern[:except] = except if except
31
- pattern[:capture] = capture if capture
32
-
33
- if settings.respond_to? :pattern and settings.pattern?
34
- pattern.merge! settings.pattern do |key, local, global|
35
- next local unless local.is_a? Hash
36
- next global.merge(local) if global.is_a? Hash
37
- Hash.new(global).merge! local
38
- end
39
- end
40
-
41
- path = Mustermann.new(path, **pattern)
42
- condition { params.merge! path.params(captures: Array(params[:captures]), offset: -1) }
43
- end
44
-
45
- super(verb, path, block, options)
46
- end
47
-
48
- private :compile!
49
- end
50
- end
3
+ fail "Mustermann extension for Sinatra has been extracted into its own gem. More information at https://github.com/sinatra/mustermann-sinatra-extension"
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Mustermann
3
- VERSION ||= '1.1.1'
3
+ VERSION ||= '3.0.0'
4
4
  end
data/lib/mustermann.rb CHANGED
@@ -75,8 +75,8 @@ module Mustermann
75
75
  end
76
76
  end
77
77
 
78
- @mutex ||= Mutex.new
79
- @types ||= {}
78
+ @mutex = Mutex.new
79
+ @types = {}
80
80
 
81
81
  # Maps a type to its factory.
82
82
  #
@@ -120,7 +120,6 @@ module Mustermann
120
120
  def self.extend_object(object)
121
121
  return super unless defined? ::Sinatra::Base and object.is_a? Class and object < ::Sinatra::Base
122
122
  require 'mustermann/extension'
123
- object.register Extension
124
123
  end
125
124
  end
126
125
 
data/mustermann.gemspec CHANGED
@@ -10,10 +10,9 @@ Gem::Specification.new do |s|
10
10
  s.summary = %q{Your personal string matching expert.}
11
11
  s.description = %q{A library implementing patterns that behave like regular expressions.}
12
12
  s.license = 'MIT'
13
- s.required_ruby_version = '>= 2.2.0'
13
+ s.required_ruby_version = '>= 2.6.0'
14
14
  s.files = `git ls-files`.split("\n")
15
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
16
 
18
17
  s.add_runtime_dependency('ruby2_keywords', '~> 0.0.1')
19
18
  end
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  require 'support'
3
3
  require 'mustermann'
4
- require 'mustermann/extension'
5
4
  require 'sinatra/base'
6
5
 
7
6
  describe Mustermann do
@@ -70,11 +69,9 @@ describe Mustermann do
70
69
  describe :extend_object do
71
70
  context 'special behavior for Sinatra only' do
72
71
  example { Object .new.extend(Mustermann).should be_a(Mustermann) }
73
- example { Object .new.extend(Mustermann).should_not be_a(Mustermann::Extension) }
74
72
  example { Class .new.extend(Mustermann).should be_a(Mustermann) }
75
- example { Class .new.extend(Mustermann).should_not be_a(Mustermann::Extension) }
76
- example { Sinatra .new.extend(Mustermann).should_not be_a(Mustermann) }
77
- example { Sinatra .new.extend(Mustermann).should be_a(Mustermann::Extension) }
73
+
74
+ example { expect { Sinatra.new.extend(Mustermann) }.to raise_error(RuntimeError, "Mustermann extension for Sinatra has been extracted into its own gem. More information at https://github.com/sinatra/mustermann-sinatra-extension") }
78
75
  end
79
76
  end
80
77
 
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mustermann
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Konstantin Haase
8
8
  - Zachary Scott
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2020-01-03 00:00:00.000000000 Z
12
+ date: 2022-07-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ruby2_keywords
@@ -76,7 +76,6 @@ files:
76
76
  - spec/concat_spec.rb
77
77
  - spec/equality_map_spec.rb
78
78
  - spec/expander_spec.rb
79
- - spec/extension_spec.rb
80
79
  - spec/identity_spec.rb
81
80
  - spec/mapper_spec.rb
82
81
  - spec/mustermann_spec.rb
@@ -90,7 +89,7 @@ homepage: https://github.com/sinatra/mustermann
90
89
  licenses:
91
90
  - MIT
92
91
  metadata: {}
93
- post_install_message:
92
+ post_install_message:
94
93
  rdoc_options: []
95
94
  require_paths:
96
95
  - lib
@@ -98,16 +97,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
98
97
  requirements:
99
98
  - - ">="
100
99
  - !ruby/object:Gem::Version
101
- version: 2.2.0
100
+ version: 2.6.0
102
101
  required_rubygems_version: !ruby/object:Gem::Requirement
103
102
  requirements:
104
103
  - - ">="
105
104
  - !ruby/object:Gem::Version
106
105
  version: '0'
107
106
  requirements: []
108
- rubyforge_project:
109
- rubygems_version: 2.7.3
110
- signing_key:
107
+ rubygems_version: 3.0.3.1
108
+ signing_key:
111
109
  specification_version: 4
112
110
  summary: Your personal string matching expert.
113
111
  test_files:
@@ -116,7 +114,6 @@ test_files:
116
114
  - spec/concat_spec.rb
117
115
  - spec/equality_map_spec.rb
118
116
  - spec/expander_spec.rb
119
- - spec/extension_spec.rb
120
117
  - spec/identity_spec.rb
121
118
  - spec/mapper_spec.rb
122
119
  - spec/mustermann_spec.rb
@@ -1,297 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'support'
3
- require 'mustermann/extension'
4
- require 'sinatra/base'
5
- require 'rack/test'
6
-
7
- describe Mustermann::Extension do
8
- include Rack::Test::Methods
9
-
10
- subject :app do
11
- Sinatra.new do
12
- set :environment, :test
13
- register Mustermann
14
- end
15
- end
16
-
17
- it 'sets up the extension' do
18
- app.should be_a(Mustermann::Extension)
19
- end
20
-
21
- context 'uses Sinatra-style patterns by default' do
22
- before { app.get('/:slug(.:extension)?') { params[:slug] } }
23
- example { get('/foo') .body.should be == 'foo' }
24
- example { get('/foo.') .body.should be == 'foo.' }
25
- example { get('/foo.bar') .body.should be == 'foo' }
26
- example { get('/a%20b') .body.should be == 'a b' }
27
- end
28
-
29
- describe :except do
30
- before { app.get('/auth/*', except: '/auth/login') { 'ok' } }
31
- example { get('/auth/dunno').should be_ok }
32
- example { get('/auth/login').should_not be_ok }
33
- end
34
-
35
- describe :capture do
36
- context 'global' do
37
- before do
38
- app.set(:pattern, capture: { ext: %w[png jpg gif] })
39
- app.get('/:slug(.:ext)?') { params[:slug] }
40
- end
41
-
42
- example { get('/foo.bar').body.should be == 'foo.bar' }
43
- example { get('/foo.png').body.should be == 'foo' }
44
- end
45
-
46
- context 'route local' do
47
- before do
48
- app.set(:pattern, nil)
49
- app.get('/:id', capture: /\d+/) { 'ok' }
50
- end
51
-
52
- example { get('/42').should be_ok }
53
- example { get('/foo').should_not be_ok }
54
- end
55
-
56
- context 'global and route local' do
57
- context 'global is a hash' do
58
- before do
59
- app.set(:pattern, capture: { id: /\d+/ })
60
- app.get('/:id(.:ext)?', capture: { ext: 'png' }) { ?a }
61
- app.get('/:id', capture: { id: 'foo' }) { ?b }
62
- app.get('/:id', capture: :alpha) { ?c }
63
- end
64
-
65
- example { get('/20') .body.should be == ?a }
66
- example { get('/20.png') .body.should be == ?a }
67
- example { get('/foo') .body.should be == ?b }
68
- example { get('/bar') .body.should be == ?c }
69
- end
70
-
71
- context 'global is not a hash' do
72
- before do
73
- app.set(:pattern, capture: /\d+/)
74
- app.get('/:slug(.:ext)?', capture: { ext: 'png' }) { params[:slug] }
75
- app.get('/:slug', capture: :alpha) { 'ok' }
76
- end
77
-
78
- example { get('/20.png').should be_ok }
79
- example { get('/foo.png').should_not be_ok }
80
- example { get('/foo').should be_ok }
81
-
82
- example { get('/20.png') .body.should be == '20' }
83
- example { get('/42') .body.should be == '42' }
84
- example { get('/foo') .body.should be == 'ok' }
85
- end
86
- end
87
- end
88
-
89
- describe :pattern do
90
- describe :except do
91
- before { app.get('/auth/*', pattern: { except: '/auth/login' }) { 'ok' } }
92
- example { get('/auth/dunno').should be_ok }
93
- example { get('/auth/login').should_not be_ok }
94
- end
95
-
96
- describe :capture do
97
- context 'route local' do
98
- before do
99
- app.set(:pattern, nil)
100
- app.get('/:id', pattern: { capture: /\d+/ }) { 'ok' }
101
- end
102
-
103
- example { get('/42').should be_ok }
104
- example { get('/foo').should_not be_ok }
105
- end
106
-
107
- context 'global and route local' do
108
- context 'global is a hash' do
109
- before do
110
- app.set(:pattern, capture: { id: /\d+/ })
111
- app.get('/:id(.:ext)?', pattern: { capture: { ext: 'png' }}) { ?a }
112
- app.get('/:id', pattern: { capture: { id: 'foo' }}) { ?b }
113
- app.get('/:id', pattern: { capture: :alpha }) { ?c }
114
- end
115
-
116
- example { get('/20') .body.should be == ?a }
117
- example { get('/20.png') .body.should be == ?a }
118
- example { get('/foo') .body.should be == ?b }
119
- example { get('/bar') .body.should be == ?c }
120
- end
121
-
122
- context 'global is not a hash' do
123
- before do
124
- app.set(:pattern, capture: /\d+/)
125
- app.get('/:slug(.:ext)?', pattern: { capture: { ext: 'png' }}) { params[:slug] }
126
- app.get('/:slug', pattern: { capture: :alpha }) { 'ok' }
127
- end
128
-
129
- example { get('/20.png').should be_ok }
130
- example { get('/foo.png').should_not be_ok }
131
- example { get('/foo').should be_ok }
132
-
133
- example { get('/20.png') .body.should be == '20' }
134
- example { get('/42') .body.should be == '42' }
135
- example { get('/foo') .body.should be == 'ok' }
136
- end
137
- end
138
- end
139
-
140
- describe :greedy do
141
- context 'default' do
142
- before { app.get('/:name.:ext') { params[:name] }}
143
- example { get('/foo.bar') .body.should be == 'foo' }
144
- example { get('/foo.bar.baz') .body.should be == 'foo.bar' }
145
- end
146
-
147
- context 'enabled' do
148
- before { app.get('/:name.:ext', pattern: { greedy: true }) { params[:name] }}
149
- example { get('/foo.bar') .body.should be == 'foo' }
150
- example { get('/foo.bar.baz') .body.should be == 'foo.bar' }
151
- end
152
-
153
- context 'disabled' do
154
- before { app.get('/:name.:ext', pattern: { greedy: false }) { params[:name] }}
155
- example { get('/foo.bar') .body.should be == 'foo' }
156
- example { get('/foo.bar.baz') .body.should be == 'foo' }
157
- end
158
-
159
- context 'global' do
160
- before do
161
- app.set(:pattern, greedy: false)
162
- app.get('/:name.:ext') { params[:name] }
163
- end
164
-
165
- example { get('/foo.bar') .body.should be == 'foo' }
166
- example { get('/foo.bar.baz') .body.should be == 'foo' }
167
- end
168
- end
169
-
170
- describe :space_matches_plus do
171
- context 'default' do
172
- before { app.get('/foo bar') { 'ok' }}
173
- example { get('/foo%20bar') .should be_ok }
174
- example { get('/foo+bar') .should be_ok }
175
- end
176
-
177
- context 'enabled' do
178
- before { app.get('/foo bar', pattern: { space_matches_plus: true }) { 'ok' }}
179
- example { get('/foo%20bar') .should be_ok }
180
- example { get('/foo+bar') .should be_ok }
181
- end
182
-
183
- context 'disabled' do
184
- before { app.get('/foo bar', pattern: { space_matches_plus: false }) { 'ok' }}
185
- example { get('/foo%20bar') .should be_ok }
186
- example { get('/foo+bar') .should_not be_ok }
187
- end
188
-
189
- context 'global' do
190
- before do
191
- app.set(:pattern, space_matches_plus: false)
192
- app.get('/foo bar') { 'ok' }
193
- end
194
-
195
- example { get('/foo%20bar') .should be_ok }
196
- example { get('/foo+bar') .should_not be_ok }
197
- end
198
- end
199
-
200
- describe :uri_decode do
201
- context 'default' do
202
- before { app.get('/&') { 'ok' }}
203
- example { get('/&') .should be_ok }
204
- example { get('/%26') .should be_ok }
205
- end
206
-
207
- context 'enabled' do
208
- before { app.get('/&', pattern: { uri_decode: true }) { 'ok' }}
209
- example { get('/&') .should be_ok }
210
- example { get('/%26') .should be_ok }
211
- end
212
-
213
- context 'disabled' do
214
- before { app.get('/&', pattern: { uri_decode: false }) { 'ok' }}
215
- example { get('/&') .should be_ok }
216
- example { get('/%26') .should_not be_ok }
217
- end
218
-
219
- context 'global' do
220
- before do
221
- app.set(:pattern, uri_decode: false)
222
- app.get('/&') { 'ok' }
223
- end
224
-
225
- example { get('/&') .should be_ok }
226
- example { get('/%26') .should_not be_ok }
227
- end
228
- end
229
- end
230
-
231
- describe :type do
232
- describe :identity do
233
- before do
234
- app.set(:pattern, type: :identity)
235
- app.get('/:foo') { 'ok' }
236
- end
237
-
238
- example { get('/:foo').should be_ok }
239
- example { get('/foo').should_not be_ok }
240
- end
241
-
242
- describe :rails do
243
- before do
244
- app.set(:pattern, type: :rails)
245
- app.get('/:slug(.:extension)') { params[:slug] }
246
- end
247
-
248
- example { get('/foo') .body.should be == 'foo' }
249
- example { get('/foo.') .body.should be == 'foo.' }
250
- example { get('/foo.bar') .body.should be == 'foo' }
251
- example { get('/a%20b') .body.should be == 'a b' }
252
- end
253
-
254
- describe :shell do
255
- before do
256
- app.set(:pattern, type: :shell)
257
- app.get('/{foo,bar}') { 'ok' }
258
- end
259
-
260
- example { get('/foo').should be_ok }
261
- example { get('/bar').should be_ok }
262
- end
263
-
264
- describe :simple do
265
- before do
266
- app.set(:pattern, type: :simple)
267
- app.get('/(a)') { 'ok' }
268
- end
269
-
270
- example { get('/(a)').should be_ok }
271
- example { get('/a').should_not be_ok }
272
- end
273
-
274
- describe :simple do
275
- before do
276
- app.set(:pattern, type: :template)
277
- app.get('/foo{/segments*}{.ext}') { "%p %p" % [params[:segments], params[:ext]] }
278
- end
279
-
280
- example { get('/foo/a.png').should be_ok }
281
- example { get('/foo/a').should_not be_ok }
282
-
283
- example { get('/foo/a.png').body.should be == '["a"] "png"' }
284
- example { get('/foo/a/b.png').body.should be == '["a", "b"] "png"' }
285
- end
286
- end
287
-
288
- context 'works with filters' do
289
- before do
290
- app.before('/auth/*', except: '/auth/login') { halt 'auth required' }
291
- app.get('/auth/login') { 'please log in' }
292
- end
293
-
294
- example { get('/auth/dunno').body.should be == 'auth required' }
295
- example { get('/auth/login').body.should be == 'please log in' }
296
- end
297
- end