rack-mount 0.6.1 → 0.6.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|