mustermann 3.0.4 → 3.1.1
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 +113 -1
- data/lib/mustermann/ast/expander.rb +4 -5
- data/lib/mustermann/ast/parser.rb +2 -3
- data/lib/mustermann/ast/translator.rb +4 -5
- data/lib/mustermann/expander.rb +1 -1
- data/lib/mustermann/pattern.rb +1 -1
- data/lib/mustermann/rails.rb +47 -0
- data/lib/mustermann/sinatra/safe_renderer.rb +1 -1
- data/lib/mustermann/version.rb +1 -1
- data/lib/mustermann/versions.rb +47 -0
- data/lib/mustermann.rb +0 -9
- metadata +6 -38
- data/bench/capturing.rb +0 -57
- data/bench/regexp.rb +0 -21
- data/bench/simple_vs_sinatra.rb +0 -23
- data/bench/template_vs_addressable.rb +0 -26
- data/bench/uri_parser_object.rb +0 -16
- data/mustermann.gemspec +0 -18
- data/spec/ast_spec.rb +0 -15
- data/spec/composite_spec.rb +0 -163
- data/spec/concat_spec.rb +0 -127
- data/spec/equality_map_spec.rb +0 -42
- data/spec/expander_spec.rb +0 -123
- data/spec/identity_spec.rb +0 -127
- data/spec/mapper_spec.rb +0 -77
- data/spec/mustermann_spec.rb +0 -81
- data/spec/pattern_spec.rb +0 -54
- data/spec/regexp_based_spec.rb +0 -9
- data/spec/regular_spec.rb +0 -119
- data/spec/simple_match_spec.rb +0 -11
- data/spec/sinatra_spec.rb +0 -836
- data/spec/to_pattern_spec.rb +0 -70
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b56ff4d495f7e79eb6deff2145be811154fa646813a21af4de4f21de27666bb1
|
|
4
|
+
data.tar.gz: fc15e2c23029429dbcf0fe0ba17d4189304edd60d50e9f010312fa1d198ebbbf
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fa699c65cb5921435ed6e8f210bbf07110e8babedc5aa71efb0f012eb094cf4d6f530511e1bc08ff54b324a4fd5608078fa01bffd23846a6dee7f65cd40c6793
|
|
7
|
+
data.tar.gz: a0a8c22f1d075e3c980830fa2c3e16f56b2b19cb333f625c27f2c6160b9e8fe83b0bdb3fb16f1f8682d9683f73884ed589a2f07ff38a522634065b859e2dbc2b
|
data/README.md
CHANGED
|
@@ -311,7 +311,7 @@ require 'mustermann'
|
|
|
311
311
|
|
|
312
312
|
Mustermann.new("/:name").to_templates # => ["/{name}"]
|
|
313
313
|
Mustermann.new("/:foo(@:bar)?/*baz").to_templates # => ["/{foo}@{bar}/{+baz}", "/{foo}/{+baz}"]
|
|
314
|
-
Mustermann.new("/{name}", type: :template).to_templates # => ["/{name}"
|
|
314
|
+
Mustermann.new("/{name}", type: :template).to_templates # => ["/{name}"]
|
|
315
315
|
```
|
|
316
316
|
|
|
317
317
|
Union Composite patterns (with the | operator) support template generation if all patterns they are composed of also support it.
|
|
@@ -828,3 +828,115 @@ Using anchors will break [peeking](#-peeking) and [concatenation](#-concatenatio
|
|
|
828
828
|
</tr>
|
|
829
829
|
</tbody>
|
|
830
830
|
</table>
|
|
831
|
+
|
|
832
|
+
<a name="-rails-pattern"></a>
|
|
833
|
+
### `rails`
|
|
834
|
+
|
|
835
|
+
Mustermann also implements the `rails` pattern. It is compatible with [Ruby on Rails](http://rubyonrails.org/), [Journey](https://github.com/rails/journey), the [http_router gem](https://github.com/joshbuddy/http_router), [Lotus](http://lotusrb.org/) and [Scalatra](http://scalatra.org/) (if [configured](http://scalatra.org/2.3/guides/http/routes.html#toc_248))</td>
|
|
836
|
+
|
|
837
|
+
**Supported options:**
|
|
838
|
+
[`capture`](#-available-options--capture),
|
|
839
|
+
[`except`](#-available-options--except),
|
|
840
|
+
[`greedy`](#-available-options--greedy),
|
|
841
|
+
[`space_matches_plus`](#-available-options--space_matches_plus),
|
|
842
|
+
[`uri_decode`](#-available-options--uri_decode),
|
|
843
|
+
[`version`](#-rails-pattern--version),
|
|
844
|
+
[`ignore_unknown_options`](#-available-options--ignore_unknown_options).
|
|
845
|
+
|
|
846
|
+
**External documentation:**
|
|
847
|
+
[Ruby on Rails Guides: Routing](http://guides.rubyonrails.org/routing.html).
|
|
848
|
+
|
|
849
|
+
``` ruby
|
|
850
|
+
require 'mustermann'
|
|
851
|
+
|
|
852
|
+
pattern = Mustermann.new('/:example', type: :rails)
|
|
853
|
+
pattern === "/foo.bar" # => true
|
|
854
|
+
pattern === "/foo/bar" # => false
|
|
855
|
+
pattern.params("/foo.bar") # => { "example" => "foo.bar" }
|
|
856
|
+
pattern.params("/foo/bar") # => nil
|
|
857
|
+
|
|
858
|
+
pattern = Mustermann.new('/:example(/:optional)', type: :rails)
|
|
859
|
+
pattern === "/foo.bar" # => true
|
|
860
|
+
pattern === "/foo/bar" # => true
|
|
861
|
+
pattern.params("/foo.bar") # => { "example" => "foo.bar", "optional" => nil }
|
|
862
|
+
pattern.params("/foo/bar") # => { "example" => "foo", "optional" => "bar" }
|
|
863
|
+
|
|
864
|
+
pattern = Mustermann.new('/*example', type: :rails)
|
|
865
|
+
pattern === "/foo.bar" # => true
|
|
866
|
+
pattern === "/foo/bar" # => true
|
|
867
|
+
pattern.params("/foo.bar") # => { "example" => "foo.bar" }
|
|
868
|
+
pattern.params("/foo/bar") # => { "example" => "foo/bar" }
|
|
869
|
+
```
|
|
870
|
+
|
|
871
|
+
<a name="-rails-pattern--version"></a>
|
|
872
|
+
#### `version`
|
|
873
|
+
|
|
874
|
+
Rails syntax changed over time. You can target different Ruby on Rails versions by setting the `version` option to the desired Rails version.
|
|
875
|
+
|
|
876
|
+
The default is `5.0`. Versions prior to `2.3` are not supported.
|
|
877
|
+
|
|
878
|
+
``` ruby
|
|
879
|
+
require 'mustermann'
|
|
880
|
+
Mustermann.new('/', type: :rails, version: "2.3")
|
|
881
|
+
Mustermann.new('/', type: :rails, version: "3.0.0")
|
|
882
|
+
|
|
883
|
+
require 'rails'
|
|
884
|
+
Mustermann.new('/', type: :rails, version: Rails::VERSION::STRING)
|
|
885
|
+
```
|
|
886
|
+
|
|
887
|
+
#### Syntax
|
|
888
|
+
|
|
889
|
+
|
|
890
|
+
<table>
|
|
891
|
+
<thead>
|
|
892
|
+
<tr>
|
|
893
|
+
<th>Syntax Element</th>
|
|
894
|
+
<th>Description</th>
|
|
895
|
+
</tr>
|
|
896
|
+
</thead>
|
|
897
|
+
<tbody>
|
|
898
|
+
<tr>
|
|
899
|
+
<td><b>:</b><i>name</i></td>
|
|
900
|
+
<td>
|
|
901
|
+
Captures anything but a forward slash in a semi-greedy fashion. Capture is named <i>name</i>.
|
|
902
|
+
Capture behavior can be modified with <tt>capture</tt> and <tt>greedy</tt> option.
|
|
903
|
+
</td>
|
|
904
|
+
</tr>
|
|
905
|
+
<tr>
|
|
906
|
+
<td><b>*</b><i>name</i></td>
|
|
907
|
+
<td>
|
|
908
|
+
Captures anything in a non-greedy fashion. Capture is named <i>name</i>.
|
|
909
|
+
</td>
|
|
910
|
+
</tr>
|
|
911
|
+
<tr>
|
|
912
|
+
<td><b>(</b><i>expression</i><b>)</b></td>
|
|
913
|
+
<td>Enclosed <i>expression</i> is optional. Not available in 2.3 compatibility mode.</td>
|
|
914
|
+
</tr>
|
|
915
|
+
<tr>
|
|
916
|
+
<td><b>/</b></td>
|
|
917
|
+
<td>
|
|
918
|
+
Matches forward slash. Does not match URI encoded version of forward slash.
|
|
919
|
+
</td>
|
|
920
|
+
</tr>
|
|
921
|
+
<tr>
|
|
922
|
+
<td><b>\</b><i>x</i></td>
|
|
923
|
+
<td>
|
|
924
|
+
In 3.x compatibility mode and starting with 4.2:
|
|
925
|
+
Matches <i>x</i> or URI encoded version of <i>x</i>. For instance <tt>\*</tt> matches <tt>*</tt>.<br>
|
|
926
|
+
In 4.0 or 4.1 compatibility mode:
|
|
927
|
+
<b>\</b> is ignored, <i>x</i> is parsed normally.<br>
|
|
928
|
+
</td>
|
|
929
|
+
</tr>
|
|
930
|
+
<tr>
|
|
931
|
+
<td><i>expression</i> <b>|</b> <i>expression</i></td>
|
|
932
|
+
<td>
|
|
933
|
+
3.2+ mode: This will raise a `Mustermann::ParseError`. While Ruby on Rails happily parses this character, it will result in broken routes due to a buggy implementation.<br>
|
|
934
|
+
5.0 mode: It will match if any of the nested expressions matches.
|
|
935
|
+
</td>
|
|
936
|
+
</tr>
|
|
937
|
+
<tr>
|
|
938
|
+
<td><i>any other character</i></td>
|
|
939
|
+
<td>Matches exactly that character or a URI encoded version of it.</td>
|
|
940
|
+
</tr>
|
|
941
|
+
</tbody>
|
|
942
|
+
</table>
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
require 'mustermann/ast/translator'
|
|
3
3
|
require 'mustermann/ast/compiler'
|
|
4
|
-
require 'ruby2_keywords'
|
|
5
4
|
|
|
6
5
|
module Mustermann
|
|
7
6
|
module AST
|
|
@@ -12,11 +11,11 @@ module Mustermann
|
|
|
12
11
|
class Expander < Translator
|
|
13
12
|
raises ExpandError
|
|
14
13
|
|
|
15
|
-
translate
|
|
14
|
+
translate Array do |*args, **options|
|
|
16
15
|
inject(t.pattern) do |pattern, element|
|
|
17
|
-
t.add_to(pattern, t(element, *args))
|
|
16
|
+
t.add_to(pattern, t(element, *args, **options))
|
|
18
17
|
end
|
|
19
|
-
end
|
|
18
|
+
end
|
|
20
19
|
|
|
21
20
|
translate :capture do |**options|
|
|
22
21
|
t.for_capture(node, **options)
|
|
@@ -123,7 +122,7 @@ module Mustermann
|
|
|
123
122
|
|
|
124
123
|
# @see Mustermann::AST::Translator#expand
|
|
125
124
|
# @!visibility private
|
|
126
|
-
|
|
125
|
+
def escape(string, *args, **options)
|
|
127
126
|
return super unless string.respond_to?(:=~)
|
|
128
127
|
|
|
129
128
|
# URI::Parser is pretty slow, let's not send every string to it, even if it's unnecessary
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
require 'mustermann/ast/node'
|
|
3
3
|
require 'forwardable'
|
|
4
|
-
require 'ruby2_keywords'
|
|
5
4
|
require 'strscan'
|
|
6
5
|
|
|
7
6
|
module Mustermann
|
|
@@ -65,10 +64,10 @@ module Mustermann
|
|
|
65
64
|
# @param [Symbol] type node type
|
|
66
65
|
# @return [Mustermann::AST::Node]
|
|
67
66
|
# @!visibility private
|
|
68
|
-
|
|
67
|
+
def node(type, *args, **options, &block)
|
|
69
68
|
type = Node[type] unless type.respond_to? :new
|
|
70
69
|
start = pos
|
|
71
|
-
node = block ? type.parse(*args, &block) : type.new(*args)
|
|
70
|
+
node = block ? type.parse(*args, **options, &block) : type.new(*args, **options)
|
|
72
71
|
min_size(start, pos, node)
|
|
73
72
|
end
|
|
74
73
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
require 'mustermann/ast/node'
|
|
3
3
|
require 'mustermann/error'
|
|
4
|
-
require 'ruby2_keywords'
|
|
5
4
|
require 'delegate'
|
|
6
5
|
|
|
7
6
|
module Mustermann
|
|
@@ -40,9 +39,9 @@ module Mustermann
|
|
|
40
39
|
|
|
41
40
|
# shorthand for translating a nested object
|
|
42
41
|
# @!visibility private
|
|
43
|
-
|
|
42
|
+
def t(*args, **options, &block)
|
|
44
43
|
return translator unless args.any?
|
|
45
|
-
translator.translate(*args, &block)
|
|
44
|
+
translator.translate(*args, **options, &block)
|
|
46
45
|
end
|
|
47
46
|
|
|
48
47
|
# @!visibility private
|
|
@@ -113,8 +112,8 @@ module Mustermann
|
|
|
113
112
|
|
|
114
113
|
# Start the translation dance for a (sub)tree.
|
|
115
114
|
# @!visibility private
|
|
116
|
-
|
|
117
|
-
result = decorator_for(node).translate(*args, &block)
|
|
115
|
+
def translate(node, *args, **options, &block)
|
|
116
|
+
result = decorator_for(node).translate(*args, **options, &block)
|
|
118
117
|
result = result.node while result.is_a? NodeTranslator
|
|
119
118
|
result
|
|
120
119
|
end
|
data/lib/mustermann/expander.rb
CHANGED
data/lib/mustermann/pattern.rb
CHANGED
|
@@ -110,7 +110,7 @@ module Mustermann
|
|
|
110
110
|
# Used by Ruby internally for hashing.
|
|
111
111
|
# @return [Integer] same has value for patterns that are equal
|
|
112
112
|
def hash
|
|
113
|
-
self.class.hash
|
|
113
|
+
self.class.hash ^ @string.hash ^ options.hash
|
|
114
114
|
end
|
|
115
115
|
|
|
116
116
|
# Two patterns are considered equal if they are of the same type, have the same pattern string
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require 'mustermann'
|
|
3
|
+
require 'mustermann/ast/pattern'
|
|
4
|
+
require 'mustermann/versions'
|
|
5
|
+
|
|
6
|
+
module Mustermann
|
|
7
|
+
# Rails style pattern implementation.
|
|
8
|
+
#
|
|
9
|
+
# @example
|
|
10
|
+
# Mustermann.new('/:foo', type: :rails) === '/bar' # => true
|
|
11
|
+
#
|
|
12
|
+
# @see Mustermann::Pattern
|
|
13
|
+
# @see file:README.md#rails Syntax description in the README
|
|
14
|
+
class Rails < AST::Pattern
|
|
15
|
+
extend Versions
|
|
16
|
+
register :rails
|
|
17
|
+
|
|
18
|
+
# first parser, no optional parts
|
|
19
|
+
version('2.3') do
|
|
20
|
+
on(nil) { |c| unexpected(c) }
|
|
21
|
+
on(?*) { |c| node(:named_splat) { scan(/\w+/) } }
|
|
22
|
+
on(?:) { |c| node(:capture) { scan(/\w+/) } }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# rack-mount
|
|
26
|
+
version('3.0', '3.1') do
|
|
27
|
+
on(?)) { |c| unexpected(c) }
|
|
28
|
+
on(?() { |c| node(:optional, node(:group) { read unless scan(?)) }) }
|
|
29
|
+
on(?\\) { |c| node(:char, expect(/./)) }
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# stand-alone journey
|
|
33
|
+
version('3.2') do
|
|
34
|
+
on(?|) { |c| raise ParseError, "the implementation of | is broken in ActionDispatch, cannot compile compatible pattern" }
|
|
35
|
+
on(?\\) { |c| node(:char, c) }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# embedded journey, broken (ignored) escapes
|
|
39
|
+
version('4.0', '4.1') { on(?\\) { |c| read } }
|
|
40
|
+
|
|
41
|
+
# escapes got fixed in 4.2
|
|
42
|
+
version('4.2') { on(?\\) { |c| node(:char, expect(/./)) } }
|
|
43
|
+
|
|
44
|
+
# Rails 5.0 fixes |
|
|
45
|
+
version('5.0') { on(?|) { |c| node(:or) }}
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
module Mustermann
|
|
3
3
|
class Sinatra < AST::Pattern
|
|
4
4
|
# Generates a string that can safely be concatenated with other strings
|
|
5
|
-
# without
|
|
5
|
+
# without changing its semantics
|
|
6
6
|
# @see #safe_string
|
|
7
7
|
# @!visibility private
|
|
8
8
|
SafeRenderer = AST::Translator.create do
|
data/lib/mustermann/version.rb
CHANGED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Mustermann
|
|
3
|
+
# Mixin that adds support for multiple versions of the same type.
|
|
4
|
+
# @see Mustermann::Rails
|
|
5
|
+
# @!visibility private
|
|
6
|
+
module Versions
|
|
7
|
+
# Checks if class has mulitple versions available and picks one that matches the version option.
|
|
8
|
+
# @!visibility private
|
|
9
|
+
def new(*args, version: nil, **options)
|
|
10
|
+
return super(*args, **options) unless versions.any?
|
|
11
|
+
self[version].new(*args, **options)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# @return [Hash] version to subclass mapping.
|
|
15
|
+
# @!visibility private
|
|
16
|
+
def versions
|
|
17
|
+
@versions ||= {}
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Defines a new version.
|
|
21
|
+
# @!visibility private
|
|
22
|
+
def version(*list, inherit_from: nil, &block)
|
|
23
|
+
superclass = self[inherit_from] || self
|
|
24
|
+
subclass = Class.new(superclass, &block)
|
|
25
|
+
list.each { |v| versions[v] = subclass }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Resolve a subclass for a given version string.
|
|
29
|
+
# @!visibility private
|
|
30
|
+
def [](version)
|
|
31
|
+
return versions.values.last unless version
|
|
32
|
+
detected = versions.detect { |v,_| version.start_with?(v) }
|
|
33
|
+
raise ArgumentError, 'unsupported version %p' % version unless detected
|
|
34
|
+
detected.last
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# @!visibility private
|
|
38
|
+
def name
|
|
39
|
+
super || superclass.name
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# @!visibility private
|
|
43
|
+
def inspect
|
|
44
|
+
name
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
data/lib/mustermann.rb
CHANGED
|
@@ -122,12 +122,3 @@ module Mustermann
|
|
|
122
122
|
require 'mustermann/extension'
|
|
123
123
|
end
|
|
124
124
|
end
|
|
125
|
-
|
|
126
|
-
# :nocov:
|
|
127
|
-
begin
|
|
128
|
-
require 'mustermann/visualizer' if defined?(Pry) or defined?(IRB)
|
|
129
|
-
rescue LoadError => error
|
|
130
|
-
raise error unless error.path == 'mustermann/visualizer'
|
|
131
|
-
$stderr.puts(error.message) if caller_locations[1].absolute_path =~ %r{/lib/pry/|/irb/|^\((?:irb|pry)\)$}
|
|
132
|
-
end
|
|
133
|
-
# :nocov:
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mustermann
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.1.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Konstantin Haase
|
|
@@ -9,21 +9,7 @@ authors:
|
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
11
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
|
-
dependencies:
|
|
13
|
-
- !ruby/object:Gem::Dependency
|
|
14
|
-
name: ruby2_keywords
|
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
|
16
|
-
requirements:
|
|
17
|
-
- - "~>"
|
|
18
|
-
- !ruby/object:Gem::Version
|
|
19
|
-
version: 0.0.1
|
|
20
|
-
type: :runtime
|
|
21
|
-
prerelease: false
|
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
-
requirements:
|
|
24
|
-
- - "~>"
|
|
25
|
-
- !ruby/object:Gem::Version
|
|
26
|
-
version: 0.0.1
|
|
12
|
+
dependencies: []
|
|
27
13
|
description: A library implementing patterns that behave like regular expressions.
|
|
28
14
|
email: sinatrarb@googlegroups.com
|
|
29
15
|
executables: []
|
|
@@ -32,11 +18,6 @@ extra_rdoc_files: []
|
|
|
32
18
|
files:
|
|
33
19
|
- LICENSE
|
|
34
20
|
- README.md
|
|
35
|
-
- bench/capturing.rb
|
|
36
|
-
- bench/regexp.rb
|
|
37
|
-
- bench/simple_vs_sinatra.rb
|
|
38
|
-
- bench/template_vs_addressable.rb
|
|
39
|
-
- bench/uri_parser_object.rb
|
|
40
21
|
- lib/mustermann.rb
|
|
41
22
|
- lib/mustermann/ast/boundaries.rb
|
|
42
23
|
- lib/mustermann/ast/compiler.rb
|
|
@@ -60,6 +41,7 @@ files:
|
|
|
60
41
|
- lib/mustermann/mapper.rb
|
|
61
42
|
- lib/mustermann/pattern.rb
|
|
62
43
|
- lib/mustermann/pattern_cache.rb
|
|
44
|
+
- lib/mustermann/rails.rb
|
|
63
45
|
- lib/mustermann/regexp.rb
|
|
64
46
|
- lib/mustermann/regexp_based.rb
|
|
65
47
|
- lib/mustermann/regular.rb
|
|
@@ -70,21 +52,7 @@ files:
|
|
|
70
52
|
- lib/mustermann/sinatra/try_convert.rb
|
|
71
53
|
- lib/mustermann/to_pattern.rb
|
|
72
54
|
- lib/mustermann/version.rb
|
|
73
|
-
- mustermann.
|
|
74
|
-
- spec/ast_spec.rb
|
|
75
|
-
- spec/composite_spec.rb
|
|
76
|
-
- spec/concat_spec.rb
|
|
77
|
-
- spec/equality_map_spec.rb
|
|
78
|
-
- spec/expander_spec.rb
|
|
79
|
-
- spec/identity_spec.rb
|
|
80
|
-
- spec/mapper_spec.rb
|
|
81
|
-
- spec/mustermann_spec.rb
|
|
82
|
-
- spec/pattern_spec.rb
|
|
83
|
-
- spec/regexp_based_spec.rb
|
|
84
|
-
- spec/regular_spec.rb
|
|
85
|
-
- spec/simple_match_spec.rb
|
|
86
|
-
- spec/sinatra_spec.rb
|
|
87
|
-
- spec/to_pattern_spec.rb
|
|
55
|
+
- lib/mustermann/versions.rb
|
|
88
56
|
homepage: https://github.com/sinatra/mustermann
|
|
89
57
|
licenses:
|
|
90
58
|
- MIT
|
|
@@ -96,14 +64,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
96
64
|
requirements:
|
|
97
65
|
- - ">="
|
|
98
66
|
- !ruby/object:Gem::Version
|
|
99
|
-
version: 2.
|
|
67
|
+
version: 2.7.0
|
|
100
68
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
101
69
|
requirements:
|
|
102
70
|
- - ">="
|
|
103
71
|
- !ruby/object:Gem::Version
|
|
104
72
|
version: '0'
|
|
105
73
|
requirements: []
|
|
106
|
-
rubygems_version:
|
|
74
|
+
rubygems_version: 4.0.6
|
|
107
75
|
specification_version: 4
|
|
108
76
|
summary: Your personal string matching expert.
|
|
109
77
|
test_files: []
|
data/bench/capturing.rb
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
$:.unshift File.expand_path('../lib', __dir__)
|
|
2
|
-
|
|
3
|
-
require 'benchmark'
|
|
4
|
-
require 'mustermann'
|
|
5
|
-
require 'mustermann/regexp_based'
|
|
6
|
-
require 'addressable/template'
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
Mustermann.register(:regexp, Class.new(Mustermann::RegexpBased) {
|
|
10
|
-
def compile(**options)
|
|
11
|
-
Regexp.new(@string)
|
|
12
|
-
end
|
|
13
|
-
}, load: false)
|
|
14
|
-
|
|
15
|
-
Mustermann.register(:addressable, Class.new(Mustermann::RegexpBased) {
|
|
16
|
-
def compile(**options)
|
|
17
|
-
Addressable::Template.new(@string)
|
|
18
|
-
end
|
|
19
|
-
}, load: false)
|
|
20
|
-
|
|
21
|
-
list = [
|
|
22
|
-
[:sinatra, '/*/:name' ],
|
|
23
|
-
[:rails, '/*prefix/:name' ],
|
|
24
|
-
[:simple, '/*/:name' ],
|
|
25
|
-
[:template, '{/prefix*}/{name}' ],
|
|
26
|
-
[:regexp, '\A\/(?<splat>.*?)\/(?<name>[^\/\?#]+)\Z' ],
|
|
27
|
-
[:addressable, '{/prefix*}/{name}' ]
|
|
28
|
-
]
|
|
29
|
-
|
|
30
|
-
def self.assert(value)
|
|
31
|
-
fail unless value
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
string = '/a/b/c/d'
|
|
35
|
-
name = 'd'
|
|
36
|
-
|
|
37
|
-
GC.disable
|
|
38
|
-
|
|
39
|
-
puts "Compilation:"
|
|
40
|
-
Benchmark.bmbm do |x|
|
|
41
|
-
list.each do |type, pattern|
|
|
42
|
-
x.report(type) { 1_000.times { Mustermann.new(pattern, type: type) } }
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
puts "", "Matching with two captures (one splat, one normal):"
|
|
47
|
-
Benchmark.bmbm do |x|
|
|
48
|
-
list.each do |type, pattern|
|
|
49
|
-
pattern = Mustermann.new(pattern, type: type)
|
|
50
|
-
x.report type do
|
|
51
|
-
10_000.times do
|
|
52
|
-
match = pattern.match(string)
|
|
53
|
-
assert match[:name] == name
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
end
|
data/bench/regexp.rb
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
require 'benchmark'
|
|
2
|
-
|
|
3
|
-
puts " atomic vs normal segments ".center(52, '=')
|
|
4
|
-
|
|
5
|
-
types = {
|
|
6
|
-
normal: /\A\/(?:a|%61)\/(?<b>[^\/\?#]+)(?:\/(?<c>[^\/\?#]+))?\Z/,
|
|
7
|
-
atomic: /\A\/(?:a|%61)\/(?<b>(?>[^\/\?#]+))(?:\/(?<c>(?>[^\/\?#]+)))?\Z/
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
Benchmark.bmbm do |x|
|
|
11
|
-
types.each do |name, regexp|
|
|
12
|
-
string = "/a/" << ?a * 10000 << "/" << ?a * 5000
|
|
13
|
-
fail unless regexp.match(string)
|
|
14
|
-
string << "/"
|
|
15
|
-
fail if regexp.match(string)
|
|
16
|
-
|
|
17
|
-
x.report name.to_s do
|
|
18
|
-
100.times { regexp.match(string) }
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
data/bench/simple_vs_sinatra.rb
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
$:.unshift File.expand_path('../lib', __dir__)
|
|
2
|
-
|
|
3
|
-
require 'benchmark'
|
|
4
|
-
require 'mustermann/simple'
|
|
5
|
-
require 'mustermann/sinatra'
|
|
6
|
-
|
|
7
|
-
[Mustermann::Simple, Mustermann::Sinatra].each do |klass|
|
|
8
|
-
puts "", " #{klass} ".center(64, '=')
|
|
9
|
-
Benchmark.bmbm do |x|
|
|
10
|
-
no_capture = klass.new("/simple")
|
|
11
|
-
x.report("no captures, match") { 1_000.times { no_capture.match('/simple') } }
|
|
12
|
-
x.report("no captures, miss") { 1_000.times { no_capture.match('/miss') } }
|
|
13
|
-
|
|
14
|
-
simple = klass.new("/:name")
|
|
15
|
-
x.report("simple, match") { 1_000.times { simple.match('/simple').captures } }
|
|
16
|
-
x.report("simple, miss") { 1_000.times { simple.match('/mi/ss') } }
|
|
17
|
-
|
|
18
|
-
splat = klass.new("/*")
|
|
19
|
-
x.report("splat, match") { 1_000.times { splat.match("/a/b/c").captures } }
|
|
20
|
-
x.report("splat, miss") { 1_000.times { splat.match("/a/b/c.miss") } }
|
|
21
|
-
end
|
|
22
|
-
puts
|
|
23
|
-
end
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
$:.unshift File.expand_path('../lib', __dir__)
|
|
2
|
-
|
|
3
|
-
require 'benchmark'
|
|
4
|
-
require 'mustermann/template'
|
|
5
|
-
require 'addressable/template'
|
|
6
|
-
|
|
7
|
-
[Mustermann::Template, Addressable::Template].each do |klass|
|
|
8
|
-
puts "", " #{klass} ".center(64, '=')
|
|
9
|
-
Benchmark.bmbm do |x|
|
|
10
|
-
no_capture = klass.new("/simple")
|
|
11
|
-
x.report("no captures, match") { 1_000.times { no_capture.match('/simple') } }
|
|
12
|
-
x.report("no captures, miss") { 1_000.times { no_capture.match('/miss') } }
|
|
13
|
-
|
|
14
|
-
simple = klass.new("/{match}")
|
|
15
|
-
x.report("simple, match") { 1_000.times { simple.match('/simple').captures } }
|
|
16
|
-
x.report("simple, miss") { 1_000.times { simple.match('/mi/ss') } }
|
|
17
|
-
|
|
18
|
-
explode = klass.new("{/segments*}")
|
|
19
|
-
x.report("explode, match") { 1_000.times { explode.match("/a/b/c").captures } }
|
|
20
|
-
x.report("explode, miss") { 1_000.times { explode.match("/a/b/c.miss") } }
|
|
21
|
-
|
|
22
|
-
expand = klass.new("/prefix/{foo}/something/{bar}")
|
|
23
|
-
x.report("expand") { 100.times { expand.expand(foo: 'foo', bar: 'bar').to_s } }
|
|
24
|
-
end
|
|
25
|
-
puts
|
|
26
|
-
end
|
data/bench/uri_parser_object.rb
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
require "objspace"
|
|
2
|
-
require "uri"
|
|
3
|
-
require_relative "../lib/mustermann/ast/translator"
|
|
4
|
-
|
|
5
|
-
translator = Mustermann::AST::Translator.new
|
|
6
|
-
translator.escape("foo")
|
|
7
|
-
|
|
8
|
-
h1 = ObjectSpace.each_object.inject(Hash.new 0) { |h, o| h[o.class] += 1; h }
|
|
9
|
-
|
|
10
|
-
100.times do
|
|
11
|
-
translator.escape("foo")
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
h2 = ObjectSpace.each_object.inject(Hash.new 0) { |h, o| h[o.class] += 1; h }
|
|
15
|
-
|
|
16
|
-
raise if (h2[URI::RFC2396_Parser] - h1[URI::RFC2396_Parser] != 0)
|
data/mustermann.gemspec
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
$:.unshift File.expand_path("../lib", __FILE__)
|
|
2
|
-
require "mustermann/version"
|
|
3
|
-
|
|
4
|
-
Gem::Specification.new do |s|
|
|
5
|
-
s.name = "mustermann"
|
|
6
|
-
s.version = Mustermann::VERSION
|
|
7
|
-
s.authors = ["Konstantin Haase", "Zachary Scott"]
|
|
8
|
-
s.email = "sinatrarb@googlegroups.com"
|
|
9
|
-
s.homepage = "https://github.com/sinatra/mustermann"
|
|
10
|
-
s.summary = %q{Your personal string matching expert.}
|
|
11
|
-
s.description = %q{A library implementing patterns that behave like regular expressions.}
|
|
12
|
-
s.license = 'MIT'
|
|
13
|
-
s.required_ruby_version = '>= 2.6.0'
|
|
14
|
-
s.files = `git ls-files`.split("\n")
|
|
15
|
-
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
16
|
-
|
|
17
|
-
s.add_runtime_dependency('ruby2_keywords', '~> 0.0.1')
|
|
18
|
-
end
|
data/spec/ast_spec.rb
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
require 'support'
|
|
3
|
-
require 'mustermann/ast/node'
|
|
4
|
-
|
|
5
|
-
describe Mustermann::AST do
|
|
6
|
-
describe :type do
|
|
7
|
-
example { Mustermann::AST::Node[:char].type .should be == :char }
|
|
8
|
-
example { Mustermann::AST::Node[:char].new.type .should be == :char }
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
describe :min_size do
|
|
12
|
-
example { Mustermann::AST::Node[:char].new.min_size.should be == 1 }
|
|
13
|
-
example { Mustermann::AST::Node[:node].new.min_size.should be == 0 }
|
|
14
|
-
end
|
|
15
|
-
end
|