rack-mount 0.6.1 → 0.6.2
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.
- data/lib/rack/mount.rb +3 -13
- data/lib/rack/mount/analysis/frequency.rb +0 -2
- data/lib/rack/mount/analysis/splitting.rb +2 -2
- data/lib/rack/mount/code_generation.rb +113 -0
- data/lib/rack/mount/generatable_regexp.rb +1 -1
- data/lib/rack/mount/route.rb +69 -5
- data/lib/rack/mount/route_set.rb +289 -46
- data/lib/rack/mount/strexp.rb +53 -50
- data/lib/rack/mount/utils.rb +7 -7
- data/lib/rack/mount/vendor/reginald/reginald.rb +2 -1
- data/lib/rack/mount/vendor/reginald/reginald/alternation.rb +11 -1
- data/lib/rack/mount/vendor/reginald/reginald/atom.rb +17 -5
- data/lib/rack/mount/vendor/reginald/reginald/character.rb +11 -2
- data/lib/rack/mount/vendor/reginald/reginald/character_class.rb +8 -20
- data/lib/rack/mount/vendor/reginald/reginald/collection.rb +10 -6
- data/lib/rack/mount/vendor/reginald/reginald/expression.rb +30 -20
- data/lib/rack/mount/vendor/reginald/reginald/group.rb +22 -8
- data/lib/rack/mount/vendor/reginald/reginald/options.rb +47 -0
- data/lib/rack/mount/vendor/reginald/reginald/parser.rb +137 -273
- data/lib/rack/mount/vendor/reginald/reginald/tokenizer.rb +1 -1
- data/lib/rack/mount/vendor/reginald/reginald/version.rb +3 -0
- data/lib/rack/mount/version.rb +1 -1
- metadata +6 -10
- data/lib/rack/mount/exceptions.rb +0 -3
- data/lib/rack/mount/generation/route.rb +0 -59
- data/lib/rack/mount/generation/route_set.rb +0 -200
- data/lib/rack/mount/mixover.rb +0 -60
- data/lib/rack/mount/recognition/code_generation.rb +0 -124
- data/lib/rack/mount/recognition/route.rb +0 -62
- data/lib/rack/mount/recognition/route_set.rb +0 -121
data/lib/rack/mount/strexp.rb
CHANGED
@@ -1,65 +1,68 @@
|
|
1
1
|
require 'rack/mount/strexp/parser'
|
2
2
|
|
3
3
|
module Rack::Mount
|
4
|
-
class Strexp
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
4
|
+
class Strexp
|
5
|
+
class << self
|
6
|
+
# Parses segmented string expression and converts it into a Regexp
|
7
|
+
#
|
8
|
+
# Strexp.compile('foo')
|
9
|
+
# # => %r{\Afoo\Z}
|
10
|
+
#
|
11
|
+
# Strexp.compile('foo/:bar', {}, ['/'])
|
12
|
+
# # => %r{\Afoo/(?<bar>[^/]+)\Z}
|
13
|
+
#
|
14
|
+
# Strexp.compile(':foo.example.com')
|
15
|
+
# # => %r{\A(?<foo>.+)\.example\.com\Z}
|
16
|
+
#
|
17
|
+
# Strexp.compile('foo/:bar', {:bar => /[a-z]+/}, ['/'])
|
18
|
+
# # => %r{\Afoo/(?<bar>[a-z]+)\Z}
|
19
|
+
#
|
20
|
+
# Strexp.compile('foo(.:extension)')
|
21
|
+
# # => %r{\Afoo(\.(?<extension>.+))?\Z}
|
22
|
+
#
|
23
|
+
# Strexp.compile('src/*files')
|
24
|
+
# # => %r{\Asrc/(?<files>.+)\Z}
|
25
|
+
def compile(str, requirements = {}, separators = [], anchor = true)
|
26
|
+
return Regexp.compile(str) if str.is_a?(Regexp)
|
26
27
|
|
27
|
-
|
28
|
-
|
28
|
+
requirements = requirements ? requirements.dup : {}
|
29
|
+
normalize_requirements!(requirements, separators)
|
29
30
|
|
30
|
-
|
31
|
-
|
32
|
-
|
31
|
+
parser = StrexpParser.new
|
32
|
+
parser.anchor = anchor
|
33
|
+
parser.requirements = requirements
|
33
34
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
35
|
+
begin
|
36
|
+
re = parser.scan_str(str)
|
37
|
+
rescue Racc::ParseError => e
|
38
|
+
raise RegexpError, e.message
|
39
|
+
end
|
39
40
|
|
40
|
-
|
41
|
-
|
41
|
+
Regexp.compile(re)
|
42
|
+
end
|
43
|
+
alias_method :new, :compile
|
42
44
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
45
|
+
private
|
46
|
+
def normalize_requirements!(requirements, separators)
|
47
|
+
requirements.each do |key, value|
|
48
|
+
if value.is_a?(Regexp)
|
49
|
+
if regexp_has_modifiers?(value)
|
50
|
+
requirements[key] = value
|
51
|
+
else
|
52
|
+
requirements[key] = value.source
|
53
|
+
end
|
49
54
|
else
|
50
|
-
requirements[key] = value
|
55
|
+
requirements[key] = Regexp.escape(value)
|
51
56
|
end
|
52
|
-
else
|
53
|
-
requirements[key] = Regexp.escape(value)
|
54
57
|
end
|
58
|
+
requirements.default ||= separators.any? ?
|
59
|
+
"[^#{separators.join}]+" : '.+'
|
60
|
+
requirements
|
55
61
|
end
|
56
|
-
requirements.default ||= separators.any? ?
|
57
|
-
"[^#{separators.join}]+" : '.+'
|
58
|
-
requirements
|
59
|
-
end
|
60
62
|
|
61
|
-
|
62
|
-
|
63
|
-
|
63
|
+
def regexp_has_modifiers?(regexp)
|
64
|
+
regexp.options & (Regexp::IGNORECASE | Regexp::EXTENDED) != 0
|
65
|
+
end
|
66
|
+
end
|
64
67
|
end
|
65
68
|
end
|
data/lib/rack/mount/utils.rb
CHANGED
@@ -124,13 +124,13 @@ module Rack::Mount
|
|
124
124
|
|
125
125
|
unless Reginald.regexp_supports_named_captures?
|
126
126
|
tag_captures = Proc.new do |group|
|
127
|
-
group
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
127
|
+
case group
|
128
|
+
when Reginald::Group
|
129
|
+
# TODO: dup instead of mutating
|
130
|
+
group.instance_variable_set('@name', regexp.names[group.index]) if group.index
|
131
|
+
tag_captures.call(group.expression)
|
132
|
+
when Reginald::Expression
|
133
|
+
group.each { |child| tag_captures.call(child) }
|
134
134
|
end
|
135
135
|
end
|
136
136
|
tag_captures.call(expression)
|
@@ -7,6 +7,7 @@ module Reginald
|
|
7
7
|
autoload :Collection, 'reginald/collection'
|
8
8
|
autoload :Expression, 'reginald/expression'
|
9
9
|
autoload :Group, 'reginald/group'
|
10
|
+
autoload :Options, 'reginald/options'
|
10
11
|
autoload :Parser, 'reginald/parser'
|
11
12
|
|
12
13
|
class << self
|
@@ -38,7 +39,7 @@ module Reginald
|
|
38
39
|
def compile(source)
|
39
40
|
regexp = Regexp.compile(source)
|
40
41
|
expression = parse(regexp)
|
41
|
-
Regexp.compile(expression.to_s(true), expression.
|
42
|
+
Regexp.compile(expression.to_s(true), expression.flags)
|
42
43
|
end
|
43
44
|
end
|
44
45
|
end
|
@@ -11,11 +11,17 @@ module Reginald
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def initialize(*args)
|
14
|
+
args, options = extract_options(args)
|
15
|
+
|
14
16
|
if args.length == 1 && args.first.instance_of?(Array)
|
15
17
|
super(args.first)
|
16
18
|
else
|
17
19
|
super(args)
|
18
20
|
end
|
21
|
+
|
22
|
+
if options.key?(:ignorecase)
|
23
|
+
map! { |e| e.dup(:ignorecase => options[:ignorecase]) }
|
24
|
+
end
|
19
25
|
end
|
20
26
|
|
21
27
|
# Returns true if expression could be treated as a literal string.
|
@@ -25,10 +31,14 @@ module Reginald
|
|
25
31
|
false
|
26
32
|
end
|
27
33
|
|
28
|
-
def
|
34
|
+
def flags
|
29
35
|
0
|
30
36
|
end
|
31
37
|
|
38
|
+
def dup(options = {})
|
39
|
+
self.class.new(to_a, options)
|
40
|
+
end
|
41
|
+
|
32
42
|
def to_s(parent = false)
|
33
43
|
map { |e| e.to_s(parent) }.join('|')
|
34
44
|
end
|
@@ -1,10 +1,14 @@
|
|
1
1
|
module Reginald
|
2
|
-
class Atom
|
3
|
-
|
2
|
+
class Atom
|
3
|
+
attr_reader :value, :ignorecase
|
4
4
|
|
5
|
-
def initialize(
|
6
|
-
@
|
7
|
-
|
5
|
+
def initialize(value, options = {})
|
6
|
+
@value = value
|
7
|
+
@ignorecase = options[:ignorecase]
|
8
|
+
end
|
9
|
+
|
10
|
+
def option_names
|
11
|
+
%w( ignorecase )
|
8
12
|
end
|
9
13
|
|
10
14
|
# Returns true if expression could be treated as a literal string.
|
@@ -16,6 +20,14 @@ module Reginald
|
|
16
20
|
ignorecase ? true : false
|
17
21
|
end
|
18
22
|
|
23
|
+
def dup(options = {})
|
24
|
+
original_options = option_names.inject({}) do |h, m|
|
25
|
+
h[m.to_sym] = send(m)
|
26
|
+
h
|
27
|
+
end
|
28
|
+
self.class.new(value, original_options.merge(options))
|
29
|
+
end
|
30
|
+
|
19
31
|
def to_s(parent = false)
|
20
32
|
"#{value}"
|
21
33
|
end
|
@@ -1,6 +1,15 @@
|
|
1
1
|
module Reginald
|
2
2
|
class Character < Atom
|
3
|
-
|
3
|
+
attr_reader :quantifier
|
4
|
+
|
5
|
+
def initialize(value, options = {})
|
6
|
+
@quantifier = options[:quantifier]
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
def option_names
|
11
|
+
%w( quantifier ) + super
|
12
|
+
end
|
4
13
|
|
5
14
|
# Returns true if expression could be treated as a literal string.
|
6
15
|
#
|
@@ -38,7 +47,7 @@ module Reginald
|
|
38
47
|
end
|
39
48
|
|
40
49
|
def freeze #:nodoc:
|
41
|
-
quantifier.freeze
|
50
|
+
quantifier.freeze if quantifier
|
42
51
|
super
|
43
52
|
end
|
44
53
|
end
|
@@ -1,27 +1,15 @@
|
|
1
1
|
module Reginald
|
2
2
|
class CharacterClass < Character
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
CNTRL = new(':cntrl:').freeze
|
8
|
-
DIGIT = new(':digit:').freeze
|
9
|
-
GRAPH = new(':graph:').freeze
|
10
|
-
LOWER = new(':lower:').freeze
|
11
|
-
PRINT = new(':print:').freeze
|
12
|
-
PUNCT = new(':punct:').freeze
|
13
|
-
SPACE = new(':space:').freeze
|
14
|
-
UPPER = new(':upper:').freeze
|
15
|
-
WORD = new(':word:').freeze
|
16
|
-
XDIGIT = new(':xdigit:').freeze
|
3
|
+
def initialize(value, options = {})
|
4
|
+
@negate = options[:negate]
|
5
|
+
super
|
6
|
+
end
|
17
7
|
|
18
|
-
def
|
19
|
-
|
20
|
-
super
|
21
|
-
end
|
8
|
+
def option_names
|
9
|
+
%w( negate ) + super
|
22
10
|
end
|
23
11
|
|
24
|
-
|
12
|
+
attr_reader :negate
|
25
13
|
|
26
14
|
def negated?
|
27
15
|
negate ? true : false
|
@@ -60,7 +48,7 @@ module Reginald
|
|
60
48
|
end
|
61
49
|
|
62
50
|
def freeze #:nodoc:
|
63
|
-
negate.freeze
|
51
|
+
negate.freeze if negate
|
64
52
|
super
|
65
53
|
end
|
66
54
|
end
|
@@ -1,12 +1,7 @@
|
|
1
1
|
module Reginald
|
2
2
|
class Collection < Array
|
3
|
-
def ignorecase=(ignorecase)
|
4
|
-
each { |e| e.ignorecase = ignorecase }
|
5
|
-
ignorecase
|
6
|
-
end
|
7
|
-
|
8
3
|
def to_regexp
|
9
|
-
Regexp.compile("\\A#{to_s(true)}\\Z",
|
4
|
+
Regexp.compile("\\A#{to_s(true)}\\Z", flags)
|
10
5
|
end
|
11
6
|
|
12
7
|
def match(char)
|
@@ -36,5 +31,14 @@ module Reginald
|
|
36
31
|
each { |e| e.freeze }
|
37
32
|
super
|
38
33
|
end
|
34
|
+
|
35
|
+
protected
|
36
|
+
def extract_options(args)
|
37
|
+
if args.last.is_a?(Hash)
|
38
|
+
return args[0..-2], args.last
|
39
|
+
else
|
40
|
+
return args, {}
|
41
|
+
end
|
42
|
+
end
|
39
43
|
end
|
40
44
|
end
|
@@ -15,6 +15,8 @@ module Reginald
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def initialize(*args)
|
18
|
+
args, options = extract_options(args)
|
19
|
+
|
18
20
|
@multiline = @ignorecase = @extended = nil
|
19
21
|
|
20
22
|
if args.length == 1 && args.first.instance_of?(Array)
|
@@ -23,15 +25,10 @@ module Reginald
|
|
23
25
|
args = args.map { |e| e.instance_of?(String) ? Character.new(e) : e }
|
24
26
|
super(args)
|
25
27
|
end
|
26
|
-
end
|
27
28
|
|
28
|
-
|
29
|
-
if
|
30
|
-
|
31
|
-
@ignorecase = ignorecase
|
32
|
-
else
|
33
|
-
false
|
34
|
-
end
|
29
|
+
self.multiline = options[:multiline] if options.key?(:multiline)
|
30
|
+
self.ignorecase = options[:ignorecase] if options.key?(:ignorecase)
|
31
|
+
self.extended = options[:extended] if options.key?(:extended)
|
35
32
|
end
|
36
33
|
|
37
34
|
# Returns true if expression could be treated as a literal string.
|
@@ -65,23 +62,24 @@ module Reginald
|
|
65
62
|
anchored_to_end? || (last.is_a?(Anchor) && last == '$')
|
66
63
|
end
|
67
64
|
|
68
|
-
def options
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
65
|
+
def options?
|
66
|
+
options.any?(true)
|
67
|
+
end
|
68
|
+
|
69
|
+
def flags
|
70
|
+
options.to_i
|
74
71
|
end
|
75
72
|
|
76
|
-
def options=
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
73
|
+
def dup(options = {})
|
74
|
+
expression = super()
|
75
|
+
expression.multiline = options[:multiline] if options.key?(:multiline)
|
76
|
+
expression.ignorecase = options[:ignorecase] if options.key?(:ignorecase)
|
77
|
+
expression.extended = options[:extended] if options.key?(:extended)
|
78
|
+
expression
|
81
79
|
end
|
82
80
|
|
83
81
|
def to_s(parent = false)
|
84
|
-
if parent || options
|
82
|
+
if parent || !options?
|
85
83
|
map { |e| e.to_s(parent) }.join
|
86
84
|
else
|
87
85
|
with, without = [], []
|
@@ -110,5 +108,17 @@ module Reginald
|
|
110
108
|
!!self.ignorecase == !!other.ignorecase &&
|
111
109
|
!!self.extended == !!other.extended
|
112
110
|
end
|
111
|
+
|
112
|
+
protected
|
113
|
+
def options
|
114
|
+
Options.new(multiline, ignorecase, extended)
|
115
|
+
end
|
116
|
+
|
117
|
+
def ignorecase=(ignorecase)
|
118
|
+
if @ignorecase.nil?
|
119
|
+
map! { |e| e.dup(:ignorecase => ignorecase) }
|
120
|
+
@ignorecase = ignorecase
|
121
|
+
end
|
122
|
+
end
|
113
123
|
end
|
114
124
|
end
|
@@ -1,14 +1,20 @@
|
|
1
1
|
module Reginald
|
2
|
-
class Group
|
3
|
-
|
2
|
+
class Group
|
3
|
+
attr_reader :expression, :quantifier, :capture, :index, :name
|
4
4
|
|
5
|
-
def initialize(
|
5
|
+
def initialize(expression, options = {})
|
6
|
+
@quantifier = @index = @name = nil
|
6
7
|
@capture = true
|
7
|
-
|
8
|
+
@expression = expression.dup(options)
|
9
|
+
|
10
|
+
@quantifier = options[:quantifier] if options.key?(:quantifier)
|
11
|
+
@capture = options[:capture] if options.key?(:capture)
|
12
|
+
@index = options[:index] if options.key?(:index)
|
13
|
+
@name = options[:name] if options.key?(:name)
|
8
14
|
end
|
9
15
|
|
10
|
-
def
|
11
|
-
|
16
|
+
def option_names
|
17
|
+
%w( quantifier capture index name )
|
12
18
|
end
|
13
19
|
|
14
20
|
# Returns true if expression could be treated as a literal string.
|
@@ -19,7 +25,7 @@ module Reginald
|
|
19
25
|
end
|
20
26
|
|
21
27
|
def to_s(parent = false)
|
22
|
-
if expression.options
|
28
|
+
if !expression.options?
|
23
29
|
"(#{capture ? '' : '?:'}#{expression.to_s(parent)})#{quantifier}"
|
24
30
|
elsif capture == false
|
25
31
|
"#{expression.to_s}#{quantifier}"
|
@@ -32,6 +38,14 @@ module Reginald
|
|
32
38
|
Regexp.compile("\\A#{to_s}\\Z")
|
33
39
|
end
|
34
40
|
|
41
|
+
def dup(options = {})
|
42
|
+
original_options = option_names.inject({}) do |h, m|
|
43
|
+
h[m.to_sym] = send(m)
|
44
|
+
h
|
45
|
+
end
|
46
|
+
self.class.new(expression, original_options.merge(options))
|
47
|
+
end
|
48
|
+
|
35
49
|
def inspect #:nodoc:
|
36
50
|
to_s.inspect
|
37
51
|
end
|
@@ -67,7 +81,7 @@ module Reginald
|
|
67
81
|
end
|
68
82
|
|
69
83
|
def freeze #:nodoc:
|
70
|
-
expression.freeze
|
84
|
+
expression.freeze if expression
|
71
85
|
super
|
72
86
|
end
|
73
87
|
end
|