uri_template 0.1.1 → 0.1.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/CHANGELOG CHANGED
@@ -1,3 +1,9 @@
1
+ # 0.1.2 - 10.11.2011
2
+ + added a new template-type: Colon
3
+ this should allow (some day) to rails-like routing tables
4
+ + made the tokens-method mandatory and added two interfaces for tokens.
5
+ this allows cross-type features like variable anaylisis
6
+
1
7
  # 0.1.1 - 4.11.2011
2
8
  + added a bunch of useful helper methods
3
9
 
@@ -0,0 +1,153 @@
1
+ # -*- encoding : utf-8 -*-
2
+ # This program is free software: you can redistribute it and/or modify
3
+ # it under the terms of the Affero GNU General Public License as published by
4
+ # the Free Software Foundation, either version 3 of the License, or
5
+ # (at your option) any later version.
6
+ #
7
+ # This program is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
+ # GNU General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU General Public License
13
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
14
+ #
15
+ # (c) 2011 by Hannes Georg
16
+ #
17
+
18
+ require 'forwardable'
19
+
20
+ require 'uri_template'
21
+ require 'uri_template/utils'
22
+
23
+ # A colon based template denotes variables with a colon.
24
+ # This template type is realy basic but having just on template type was a bit weird.
25
+ module URITemplate
26
+
27
+ class Colon
28
+
29
+ include URITemplate
30
+
31
+ VAR = /(?:\{:(?<name>[a-z]+)\}|:(?<name>[a-z]+)(?![a-z]))/
32
+
33
+ class Token
34
+
35
+ class Variable < self
36
+
37
+ include URITemplate::Expression
38
+
39
+ attr_reader :name
40
+
41
+ def initialize(name)
42
+ @name = name
43
+ @variables = [name]
44
+ end
45
+
46
+ def expand(vars)
47
+ return Utils.pct(vars[@name])
48
+ end
49
+
50
+ def to_r
51
+ return ['(?<', name, '>[^/]*?)'].join
52
+ end
53
+
54
+ end
55
+
56
+ class Static < self
57
+
58
+ include URITemplate::Literal
59
+
60
+ def initialize(str)
61
+ @string = str
62
+ end
63
+
64
+ def expand(_)
65
+ return @string
66
+ end
67
+
68
+ def to_r
69
+ return Regexp.escape(@string)
70
+ end
71
+
72
+ end
73
+
74
+ end
75
+
76
+ attr_reader :pattern
77
+
78
+ # Tries to convert the value into a colon-template.
79
+ # @example
80
+ # URITemplate::Colon.try_convert('/foo/:bar/').pattern #=> '/foo/:bar/'
81
+ # URITemplate::Colon.try_convert(URITemplate::Draft7.new('/foo/{bar}/')).pattern #=> '/foo/{:bar}/'
82
+ def self.try_convert(x)
83
+ if x.kind_of? String
84
+ return new(x)
85
+ elsif x.kind_of? self
86
+ return x
87
+ elsif x.kind_of? URITemplate::Draft7 and x.level == 1
88
+ return new( x.pattern.gsub(/\{(.*?)\}/){ "{:#{$1}}" } )
89
+ else
90
+ return nil
91
+ end
92
+ end
93
+
94
+ def initialize(pattern)
95
+ @pattern = pattern
96
+ end
97
+
98
+ # Extracts variables from an uri.
99
+ #
100
+ # @param String uri
101
+ # @return nil,Hash
102
+ def extract(uri)
103
+ return self.to_r.match(uri) do |md|
104
+ Hash[ *self.variables.map{|v|
105
+ [v, Utils.dpct(md[v])]
106
+ }.flatten(1) ]
107
+ end
108
+ end
109
+
110
+ def type
111
+ :colon
112
+ end
113
+
114
+ def to_r
115
+ @regexp ||= Regexp.new('\A' + tokens.map(&:to_r).join + '\z')
116
+ end
117
+
118
+ def tokens
119
+ @tokens ||= tokenize!
120
+ end
121
+
122
+ # Tries to concatenate two templates, as if they were path segments.
123
+ # Removes double slashes or inserts one if they are missing.
124
+ #
125
+ # @example
126
+ # tpl = URITemplate::Colon.new('/xy/')
127
+ # (tpl / '/z/' ).pattern #=> '/xy/z/'
128
+ # (tpl / 'z/' ).pattern #=> '/xy/z/'
129
+ # (tpl / ':z' ).pattern #=> '/xy/:z'
130
+ # (tpl / ':a' / 'b' ).pattern #=> '/xy/:a/b'
131
+ #
132
+ def /(o)
133
+ this, other, this_converted, other_converted = URITemplate.coerce( self, o )
134
+ if this_converted
135
+ return this / other
136
+ end
137
+ return self.class.new( File.join( this.pattern, other.pattern ) )
138
+ end
139
+
140
+ protected
141
+
142
+ def tokenize!
143
+ RegexpEnumerator.new(VAR).each(@pattern).map{|x|
144
+ if x.kind_of? String
145
+ Token::Static.new(x)
146
+ else
147
+ Token::Variable.new(x['name'])
148
+ end
149
+ }.to_a
150
+ end
151
+
152
+ end
153
+ end
@@ -109,22 +109,18 @@ __REGEXP__
109
109
  # @private
110
110
  class Literal < Token
111
111
 
112
- attr_reader :string
113
-
112
+ include URITemplate::Literal
113
+
114
114
  def initialize(string)
115
115
  @string = string
116
116
  end
117
117
 
118
- def size
119
- 0
120
- end
121
-
122
118
  def level
123
119
  1
124
120
  end
125
121
 
126
- def expand(*_)
127
- return @string
122
+ def arity
123
+ 0
128
124
  end
129
125
 
130
126
  def to_r_source(*_)
@@ -139,11 +135,15 @@ __REGEXP__
139
135
 
140
136
  # @private
141
137
  class Expression < Token
138
+
139
+ include URITemplate::Expression
142
140
 
143
141
  attr_reader :variables, :max_length
144
142
 
145
143
  def initialize(vars)
146
- @variables = vars
144
+ @variable_specs = vars
145
+ @variables = vars.map(&:first)
146
+ @variables.uniq!
147
147
  end
148
148
 
149
149
  PREFIX = ''.freeze
@@ -158,13 +158,9 @@ __REGEXP__
158
158
  NAMED = false
159
159
  OPERATOR = ''
160
160
 
161
- def size
162
- @variables.size
163
- end
164
-
165
161
  def level
166
- if @variables.none?{|_,expand,ml| expand || (ml > 0) }
167
- if @variables.size == 1
162
+ if @variable_specs.none?{|_,expand,ml| expand || (ml > 0) }
163
+ if @variable_specs.size == 1
168
164
  return self.class::BASE_LEVEL
169
165
  else
170
166
  return 3
@@ -174,9 +170,13 @@ __REGEXP__
174
170
  end
175
171
  end
176
172
 
177
- def expand( vars, options )
173
+ def arity
174
+ @variable_specs.size
175
+ end
176
+
177
+ def expand( vars )
178
178
  result = []
179
- variables.each{| var, expand , max_length |
179
+ @variable_specs.each{| var, expand , max_length |
180
180
  unless vars[var].nil?
181
181
  if vars[var].kind_of? Hash
182
182
  result.push( *transform_hash(var, vars[var], expand, max_length) )
@@ -199,7 +199,7 @@ __REGEXP__
199
199
  end
200
200
 
201
201
  def to_s
202
- '{' + self.class::OPERATOR + @variables.map{|name,expand,max_length| name +(expand ? '*': '') + (max_length > 0 ? ':'+max_length.to_s : '') }.join(',') + '}'
202
+ '{' + self.class::OPERATOR + @variable_specs.map{|name,expand,max_length| name +(expand ? '*': '') + (max_length > 0 ? ':'+max_length.to_s : '') }.join(',') + '}'
203
203
  end
204
204
 
205
205
  #TODO: certain things after a slurpy variable will never get matched. therefore, it's pointless to add expressions for them
@@ -207,10 +207,10 @@ __REGEXP__
207
207
  def to_r_source(base_counter = 0)
208
208
  source = []
209
209
  first = true
210
- vs = variables.size - 1
210
+ vs = @variable_specs.size - 1
211
211
  i = 0
212
212
  if self.class::NAMED
213
- variables.each{| var, expand , max_length |
213
+ @variable_specs.each{| var, expand , max_length |
214
214
  last = (vs == i)
215
215
  value = "(?:\\g<#{self.class::CHARACTER_CLASS[:class_name]}>|,)#{(max_length > 0)?'{,'+max_length.to_s+'}':'*'}"
216
216
  if expand
@@ -240,7 +240,7 @@ __REGEXP__
240
240
  i = i+1
241
241
  }
242
242
  else
243
- variables.each{| var, expand , max_length |
243
+ @variable_specs.each{| var, expand , max_length |
244
244
  last = (vs == i)
245
245
  if expand
246
246
  # could be list or map, too
@@ -272,12 +272,12 @@ __REGEXP__
272
272
  end
273
273
 
274
274
  def extract(position,matched)
275
- name, expand, max_length = @variables[position]
275
+ name, expand, max_length = @variable_specs[position]
276
276
  if matched.nil?
277
277
  return [[ name , matched ]]
278
278
  end
279
279
  if expand
280
- ex = self.hash_extractor(max_length)
280
+ ex = self.class.hash_extractor(max_length)
281
281
  rest = matched
282
282
  splitted = []
283
283
  found_value = false
@@ -310,22 +310,25 @@ __REGEXP__
310
310
 
311
311
  return [ [ name, decode( matched ) ] ]
312
312
  end
313
-
314
- def variable_names
315
- @variables.collect(&:first)
316
- end
317
313
 
318
314
  protected
319
315
 
320
- def hash_extractor(max_length)
321
- value = "\\g<#{self.class::CHARACTER_CLASS[:class_name]}>#{(max_length > 0)?'{,'+max_length.to_s+'}':'*?'}"
322
-
323
- pair = "(?<name>\\g<c_vn_>#{Regexp.escape(self.class::PAIR_CONNECTOR)})?(?<value>#{value})"
316
+ module ClassMethods
324
317
 
325
- return Regexp.new( CHARACTER_CLASSES[:varname][:class] + "{0}\n" + self.class::CHARACTER_CLASS[:class] + "{0}\n" + "^#{Regexp.escape(self.class::SEPARATOR)}?" + pair + "(?<rest>$|#{Regexp.escape(self.class::SEPARATOR)}(?!#{Regexp.escape(self.class::SEPARATOR)}))" ,Regexp::EXTENDED)
318
+ def hash_extractor(max_length)
319
+ @hash_extractors ||= {}
320
+ @hash_extractors[max_length] ||= begin
321
+ value = "\\g<#{self::CHARACTER_CLASS[:class_name]}>#{(max_length > 0)?'{,'+max_length.to_s+'}':'*?'}"
322
+ pair = "(?<name>\\g<c_vn_>#{Regexp.escape(self::PAIR_CONNECTOR)})?(?<value>#{value})"
323
+
324
+ Regexp.new( CHARACTER_CLASSES[:varname][:class] + "{0}\n" + self::CHARACTER_CLASS[:class] + "{0}\n" + "^#{Regexp.escape(self::SEPARATOR)}?" + pair + "(?<rest>$|#{Regexp.escape(self::SEPARATOR)}(?!#{Regexp.escape(self::SEPARATOR)}))" ,Regexp::EXTENDED)
325
+ end
326
+ end
326
327
 
327
328
  end
328
329
 
330
+ extend ClassMethods
331
+
329
332
  def encode(x)
330
333
  Utils.pct(Utils.object_to_param(x), self.class::CHARACTER_CLASS[:unencoded])
331
334
  end
@@ -544,6 +547,7 @@ __REGEXP__
544
547
  # tpl = URITemplate::Draft7.new('{foo}')
545
548
  # URITemplate::Draft7.try_convert( tpl ) #=> tpl
546
549
  # URITemplate::Draft7.try_convert('{foo}') #=> tpl
550
+ # URITemplate::Draft7.try_convert(URITemplate.new(:colon, ':foo')) #=> tpl
547
551
  # # This pattern is invalid, so it wont be parsed:
548
552
  # URITemplate::Draft7.try_convert('{foo') #=> nil
549
553
  #
@@ -552,6 +556,14 @@ __REGEXP__
552
556
  return x
553
557
  elsif x.kind_of? String and valid? x
554
558
  return new(x)
559
+ elsif x.kind_of? URITemplate::Colon
560
+ return new( x.tokens.map{|tk|
561
+ if tk.literal?
562
+ Literal.new(tk.string)
563
+ else
564
+ Expression.new([[tk.variables.first, false, 0]])
565
+ end
566
+ })
555
567
  else
556
568
  return nil
557
569
  end
@@ -606,6 +618,7 @@ __REGEXP__
606
618
  end
607
619
  end
608
620
 
621
+ # @method expand(variables = {})
609
622
  # Expands the template with the given variables.
610
623
  # The expansion should be compatible to uritemplate spec draft 7 ( http://tools.ietf.org/html/draft-gregorio-uritemplate-07 ).
611
624
  # @note
@@ -619,31 +632,6 @@ __REGEXP__
619
632
  #
620
633
  # @param variables Hash
621
634
  # @return String
622
- def expand(variables = {})
623
- tokens.map{|part|
624
- part.expand(variables, {})
625
- }.join
626
- end
627
-
628
- # Returns an array containing all variables. Repeated variables are ignored, but the order will be kept intact.
629
- # @example
630
- # URITemplate::Draft7.new('{foo}{bar}{baz}').variables #=> ['foo','bar','baz']
631
- # URITemplate::Draft7.new('{a}{c}{a}{b}').variables #=> ['c','a','b']
632
- #
633
- # @return Array
634
- def variables
635
- @variables ||= begin
636
- vars = []
637
- tokens.each{|token|
638
- if token.respond_to? :variable_names
639
- vn = token.variable_names.uniq
640
- vars -= vn
641
- vars.push(*vn)
642
- end
643
- }
644
- vars
645
- end
646
- end
647
635
 
648
636
  # Compiles this template into a regular expression which can be used to test whether a given uri matches this template. This template is also used for {#===}.
649
637
  #
@@ -659,7 +647,7 @@ __REGEXP__
659
647
  bc = 0
660
648
  @regexp ||= Regexp.new(classes.join + '\A' + tokens.map{|part|
661
649
  r = part.to_r_source(bc)
662
- bc += part.size
650
+ bc += part.arity
663
651
  r
664
652
  }.join + '\z' , Regexp::EXTENDED)
665
653
  end
@@ -803,7 +791,7 @@ __REGEXP__
803
791
  tokens.map(&:level).max
804
792
  end
805
793
 
806
- # Tries to conatenate two templates, as if they were path segments.
794
+ # Tries to concatenate two templates, as if they were path segments.
807
795
  # Removes double slashes or insert one if they are missing.
808
796
  #
809
797
  # @example
@@ -886,20 +874,6 @@ __REGEXP__
886
874
 
887
875
  return false
888
876
  end
889
-
890
- # Returns the number of static characters in this template.
891
- # This method is useful for routing, since it's often pointful to use the url with fewer variable characters.
892
- # For example 'static' and 'sta{var}' both match 'static', but in most cases 'static' should be prefered over 'sta{var}' since it's more specific.
893
- #
894
- # @example
895
- # URITemplate::Draft7.new('/xy/').static_characters #=> 4
896
- # URITemplate::Draft7.new('{foo}').static_characters #=> 0
897
- # URITemplate::Draft7.new('a{foo}b').static_characters #=> 2
898
- #
899
- # @return Numeric
900
- def static_characters
901
- @static_characters ||= tokens.select{|t| t.kind_of?(Literal) }.map{|t| t.string.size }.inject(0,:+)
902
- end
903
877
 
904
878
  protected
905
879
  # @private
@@ -917,7 +891,7 @@ protected
917
891
  vars = []
918
892
  tokens.each{|part|
919
893
  i = 0
920
- while i < part.size
894
+ while i < part.arity
921
895
  vars.push(*part.extract(i, matchdata["v#{bc}"]))
922
896
  bc += 1
923
897
  i += 1
@@ -17,6 +17,41 @@
17
17
 
18
18
  module URITemplate
19
19
 
20
+ # An awesome little helper which helps iterating over a string.
21
+ # Initialize with a regexp and pass a string to :each.
22
+ # It will yield a string or a MatchData
23
+ class RegexpEnumerator
24
+
25
+ include Enumerable
26
+
27
+ def initialize(regexp)
28
+ @regexp = regexp
29
+ end
30
+
31
+ def each(str)
32
+ return Enumerator.new(self,:each,str) unless block_given?
33
+ rest = str
34
+ loop do
35
+ m = @regexp.match(rest)
36
+ if m.nil?
37
+ yield rest
38
+ break
39
+ end
40
+ yield m.pre_match if m.pre_match.size > 0
41
+ yield m
42
+ if m[0].size == 0
43
+ # obviously matches empty string, so post_match will equal rest
44
+ # terminate or this will loop forever
45
+ yield m.post_match
46
+ break
47
+ end
48
+ rest = m.post_match
49
+ end
50
+ return self
51
+ end
52
+
53
+ end
54
+
20
55
  # This error will be raised whenever an object could not be converted to a param string.
21
56
  class Unconvertable < StandardError
22
57
 
data/lib/uri_template.rb CHANGED
@@ -18,8 +18,65 @@
18
18
  # A base module for all implementations of a uri template.
19
19
  module URITemplate
20
20
 
21
+ # This should make it possible to do basic analysis independently from the concrete type.
22
+ module Token
23
+
24
+ def size
25
+ variables.size
26
+ end
27
+
28
+ end
29
+
30
+ # A module which all literal tokens should include.
31
+ module Literal
32
+
33
+ include Token
34
+
35
+ attr_reader :string
36
+
37
+ def literal?
38
+ true
39
+ end
40
+
41
+ def expression?
42
+ false
43
+ end
44
+
45
+ def variables
46
+ []
47
+ end
48
+
49
+ def size
50
+ 0
51
+ end
52
+
53
+ def expand(*_)
54
+ return string
55
+ end
56
+
57
+ end
58
+
59
+
60
+ # A module which all non-literal tokens should include.
61
+ module Expression
62
+
63
+ include Token
64
+
65
+ attr_reader :variables
66
+
67
+ def literal?
68
+ false
69
+ end
70
+
71
+ def expression?
72
+ true
73
+ end
74
+
75
+ end
76
+
21
77
  autoload :Utils, 'uri_template/utils'
22
78
  autoload :Draft7, 'uri_template/draft7'
79
+ autoload :Colon, 'uri_template/colon'
23
80
 
24
81
  # A hash with all available implementations.
25
82
  # Currently the only implementation is :draft7. But there also aliases :default and :latest available. This should make it possible to add newer specs later.
@@ -27,6 +84,7 @@ module URITemplate
27
84
  VERSIONS = {
28
85
  :draft7 => :Draft7,
29
86
  :default => :Draft7,
87
+ :colon => :Colon,
30
88
  :latest => :Draft7
31
89
  }
32
90
 
@@ -95,6 +153,7 @@ module URITemplate
95
153
  #
96
154
  # @example
97
155
  # URITemplate.coerce( URITemplate.new(:draft7,'{x}'), '{y}' ) #=> [URITemplate.new(:draft7,'{x}'), URITemplate.new(:draft7,'{y}'), false, true]
156
+ # URITemplate.coerce( '{y}', URITemplate.new(:draft7,'{x}') ) #=> [URITemplate.new(:draft7,'{y}'), URITemplate.new(:draft7,'{x}'), true, false]
98
157
  def self.coerce(a,b)
99
158
  if a.kind_of? URITemplate
100
159
  if a.class == b.class
@@ -140,12 +199,15 @@ module URITemplate
140
199
  module Invalid
141
200
  end
142
201
 
143
- # @abstract
144
202
  # Expands this uri template with the given variables.
145
203
  # The variables should be converted to strings using {Utils#object_to_param}.
146
204
  # @raise {Unconvertable} if a variable could not be converted to a string.
147
- def expand(variables={})
148
- raise "Please implement #expand on #{self.class.inspect}."
205
+ # @param variables Hash
206
+ # @return String
207
+ def expand(variables = {})
208
+ tokens.map{|part|
209
+ part.expand(variables)
210
+ }.join
149
211
  end
150
212
 
151
213
  # @abstract
@@ -153,5 +215,35 @@ module URITemplate
153
215
  def type
154
216
  raise "Please implement #type on #{self.class.inspect}."
155
217
  end
218
+
219
+ # @abstract
220
+ # Returns the tokens of this templates. Tokens should include either {Static} or {Expression}.
221
+ def tokens
222
+ raise "Please implement #tokens on #{self.class.inspect}."
223
+ end
224
+
225
+ # Returns an array containing all variables. Repeated variables are ignored. The concrete order of the variables may change.
226
+ # @example
227
+ # URITemplate.new('{foo}{bar}{baz}').variables #=> ['foo','bar','baz']
228
+ # URITemplate.new('{a}{c}{a}{b}').variables #=> ['a','c','b']
229
+ #
230
+ # @return Array
231
+ def variables
232
+ @variables ||= tokens.select(&:expression?).map(&:variables).flatten.uniq
233
+ end
234
+
235
+ # Returns the number of static characters in this template.
236
+ # This method is useful for routing, since it's often pointful to use the url with fewer variable characters.
237
+ # For example 'static' and 'sta\{var\}' both match 'static', but in most cases 'static' should be prefered over 'sta{var}' since it's more specific.
238
+ #
239
+ # @example
240
+ # URITemplate.new('/xy/').static_characters #=> 4
241
+ # URITemplate.new('{foo}').static_characters #=> 0
242
+ # URITemplate.new('a{foo}b').static_characters #=> 2
243
+ #
244
+ # @return Numeric
245
+ def static_characters
246
+ @static_characters ||= tokens.select(&:literal?).map{|t| t.string.size }.inject(0,:+)
247
+ end
156
248
 
157
249
  end
data/uri_template.gemspec CHANGED
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'uri_template'
3
- s.version = '0.1.1'
4
- s.date = '2011-11-04'
3
+ s.version = '0.1.2'
4
+ s.date = '2011-11-10'
5
5
  s.authors = ["HannesG"]
6
6
  s.email = %q{hannes.georg@googlemail.com}
7
7
  s.summary = 'A templating system for URIs.'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: uri_template
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-11-04 00:00:00.000000000Z
12
+ date: 2011-11-10 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &17225100 !ruby/object:Gem::Requirement
16
+ requirement: &14750900 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *17225100
24
+ version_requirements: *14750900
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: yard
27
- requirement: &17224520 !ruby/object:Gem::Requirement
27
+ requirement: &14750460 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,7 +32,7 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *17224520
35
+ version_requirements: *14750460
36
36
  description: ! 'A templating system for URIs, which implements http://tools.ietf.org/html/draft-gregorio-uritemplate-07
37
37
  . An implementation of an older version of that spec is known as addressable. This
38
38
  gem however is intended to be extended when newer specs evolve. For now only draft
@@ -43,6 +43,7 @@ extensions: []
43
43
  extra_rdoc_files: []
44
44
  files:
45
45
  - lib/uri_template.rb
46
+ - lib/uri_template/colon.rb
46
47
  - lib/uri_template/draft7.rb
47
48
  - lib/uri_template/utils.rb
48
49
  - uri_template.gemspec