acceptable 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,4 @@
1
- === DESCRIPTION:
1
+ == DESCRIPTION:
2
2
 
3
3
  Provides definitive support for Accept-* headers, strictly compliant with RFC 2616.
4
4
  Includes negotiation algorithms for Media-Types, Charsets and Content-Codings.
@@ -14,40 +14,73 @@ Also realizes perfectionistic LanguageTags support with basic/extended filtering
14
14
 
15
15
  == EXAMPLES:
16
16
 
17
- === Media
17
+ === Helpers:
18
18
 
19
- env = Rack::MockRequest.env_for('/','HTTP_ACCEPT' => 'text/plain;q=0,text/*')
20
- request = Request.new(env)
21
- p request.accept_media?('text/css') #=> true
22
- p request.accept_media?('text/plain') #=> false
23
- p request.accept_media?('video/quicktime') #=> false
19
+ env = Rack::MockRequest.env_for('/',
20
+ 'HTTP_ACCEPT' => 'text/*;q=0.8,text/x-json;q=0.8,text/html;p=whatever,image/png;q=0.2',
21
+ 'HTTP_ACCEPT_LANGUAGE' => 'de-de,sl-nedis',
22
+ 'HTTP_ACCEPT_CHARSET' => 'utf-8;q=0.9,iso-8859-5;q=0.8'
23
+ )
24
24
 
25
- env = Rack::MockRequest.env_for('/','HTTP_ACCEPT' => 'text/*;q=0.8,text/x-json;q=0.8,text/html;p=whatever')
26
- request = Request.new(env)
27
- p request.preferred_media_from('text/css','text/html') #=> "text/css"
28
- p request.preferred_media_from('text/x-json','text/html;p=whatever') #=> "text/html;p=whatever"
29
- p request.preferred_media_from('text/x-json','text/html;p=Whatever') #=> "text/x-json" #parameter values are case-sensitive.
25
+ request = Rack::Acceptable::Request.new(env)
30
26
 
31
- === LanguageTags
27
+ ==== Media:
28
+
29
+ request.accept_media?('text/css') #=> true
30
+ request.accept_media?('text/plain') #=> true
31
+ request.accept_media?('image/jpeg') #=> false
32
+ request.accept_media?('image/png') #=> true
33
+ request.accept_media?('video/quicktime') #=> false
34
+
35
+ request.preferred_media_from('text/css','text/html') #=> "text/css"
36
+ request.preferred_media_from('text/x-json','text/html;p=whatever') #=> "text/html;p=whatever"
37
+ request.preferred_media_from('text/x-json','text/html;p=Whatever') #=> "text/x-json" #parameter values are case-sensitive.
38
+
39
+ ==== Languages:
40
+
41
+ request.accept_language?("de-de") #=> true
42
+ request.accept_language?("de-DE") #=> true
43
+ request.accept_language?("de-Latn-de") #=> true
44
+ request.accept_language?("de-Latf-DE") #=> true
45
+ request.accept_language?("de-DE-x-goethe") #=> true
46
+ request.accept_language?("de-Latn-DE-1996") #=> true
47
+ request.accept_language?("de-Deva-DE") #=> true
48
+
49
+ request.accept_language?("de") #=> false
50
+ request.accept_language?("de-x-DE") #=> false
51
+ request.accept_language?("de-Deva") #=> false
52
+
53
+ request.accept_language?("sl-nedis") #=> true
54
+ request.accept_language?("sl-Latn-nedis") #=> true
55
+ request.accept_language?("sl-rozaj") #=> false
56
+
57
+ ==== Charsets:
58
+
59
+ request.accept_charset?("utf-8") #=> # true
60
+ request.accept_charset?("iso-8859-1") #=> # true
61
+
62
+ request.preferred_charset_from("utf-8","iso-8859-5") #=> # "utf-8"
63
+ request.preferred_charset_from("utf-8","iso-8859-1") #=> # "iso-8859-1"
64
+
65
+ === LanguageTags:
32
66
 
33
67
  langtag = Rack::Acceptable::LanguageTag.parse('SL-LATN-ROZAJ')
34
68
 
35
- p langtag.variants #=> ["rozaj"]
36
- p langtag.script #=> "Latn"
69
+ langtag.variants #=> ["rozaj"]
70
+ langtag.script #=> "Latn"
37
71
 
38
72
  # basic filtering (RFC 4647)
39
- p langtag.has_prefix?('sl-Latn') #=> true
40
- p langtag.matched_by_basic_range?('sl-Latn') #=> true
41
- p langtag.has_prefix?('sl-Latn-ro') #=> false
42
- p langtag.has_prefix?('sl') #=> true
73
+ langtag.has_prefix?('sl-Latn') #=> true
74
+ langtag.matched_by_basic_range?('sl-Latn') #=> true
75
+ langtag.has_prefix?('sl-Latn-ro') #=> false
76
+ langtag.has_prefix?('sl') #=> true
43
77
 
44
78
  # extended filtering (RFC 4647)
45
- p langtag.matched_by_extended_range?('*') #=> true
46
- p langtag.matched_by_extended_range?('sl-*') #=> true
47
- p langtag.matched_by_extended_range?('*-Latn') #=> true
48
- p langtag.matched_by_extended_range?('sl-rozaj') #=> true
49
- p langtag.matched_by_extended_range?('sl-nedis') #=> false
50
-
79
+ langtag.matched_by_extended_range?('*') #=> true
80
+ langtag.matched_by_extended_range?('sl-*') #=> true
81
+ langtag.matched_by_extended_range?('*-Latn') #=> true
82
+ langtag.matched_by_extended_range?('sl-rozaj') #=> true
83
+ langtag.matched_by_extended_range?('sl-nedis') #=> false
51
84
 
52
85
  == INSTALLATION:
53
86
 
@@ -13,6 +13,9 @@ module Rack #:nodoc:
13
13
 
14
14
  # request and mixins
15
15
  autoload :Headers , 'rack/acceptable/mixin/headers'
16
+ autoload :Encodings , 'rack/acceptable/mixin/encodings'
17
+ autoload :Charsets , 'rack/acceptable/mixin/charsets'
18
+ autoload :Languages , 'rack/acceptable/mixin/languages'
16
19
  autoload :Media , 'rack/acceptable/mixin/media'
17
20
  autoload :Request , 'rack/acceptable/request'
18
21
 
@@ -39,6 +39,7 @@ module Rack #:nodoc:
39
39
  }.freeze
40
40
 
41
41
  attr_accessor :primary, :extlang, :script, :region, :variants, :extensions, :privateuse
42
+ attr_reader :length
42
43
 
43
44
  #--
44
45
  # RFC 5646, sec. 2.2.2:
@@ -51,7 +52,7 @@ module Rack #:nodoc:
51
52
  # always remain, invalid.
52
53
  #++
53
54
 
54
- language = '([a-z]{2,8}|[a-z]{2,3}(?:-[a-z]{3})?)'
55
+ language = '([a-z]{2,8}|[a-z]{2,3}(?:-[a-z]{3}){0,3})'
55
56
  script = '(?:-([a-z]{4}))?'
56
57
  region = '(?:-([a-z]{2}|\d{3}))?'
57
58
  variants = '(?:-[a-z\d]{5,8}|-\d[a-z\d]{3})*'
@@ -66,14 +67,14 @@ module Rack #:nodoc:
66
67
 
67
68
  class << self
68
69
 
69
- # Checks if the +String+ passed could be treated as 'privateuse' Language-Tag.
70
+ # Checks if the +String+ passed represents a 'privateuse' Language-Tag.
70
71
  # Works case-insensitively.
71
72
  #
72
73
  def privateuse?(tag)
73
74
  PRIVATEUSE_REGEX === tag
74
75
  end
75
76
 
76
- # Checks if the +String+ passed represents a 'grandgathered' Language-Tag.
77
+ # Checks if the +String+ passed represents a 'grandfathered' Language-Tag.
77
78
  # Works case-insensitively.
78
79
  #
79
80
  def grandfathered?(tag)
@@ -81,13 +82,13 @@ module Rack #:nodoc:
81
82
  end
82
83
 
83
84
  # ==== Parameters
84
- # langtag<String>:: The Language-Tag snippet.
85
+ # langtag<String>:: The LangTag snippet.
85
86
  #
86
87
  # ==== Returns
87
88
  # Array or nil::
88
- # It returns +nil+, when the Language-Tag passed:
89
+ # It returns +nil+, when the snipped passed:
89
90
  # * does not conform the Language-Tag ABNF (malformed)
90
- # * grandfathered
91
+ # * represents a 'grandfathered' Language-Tag
91
92
  # * starts with 'x' singleton ('privateuse').
92
93
  #
93
94
  # Otherwise you'll get an +Array+ with:
@@ -112,7 +113,7 @@ module Rack #:nodoc:
112
113
  region = $3
113
114
  variants = $4.split(Utils::HYPHEN_SPLITTER)[1..-1]
114
115
 
115
- primary, extlang = primary.split(Utils::HYPHEN_SPLITTER) if primary.include?(Const::HYPHEN)
116
+ primary, *extlang = primary.split(Utils::HYPHEN_SPLITTER) if primary.include?(Const::HYPHEN)
116
117
  script.capitalize! if script
117
118
  region.upcase! if region
118
119
 
@@ -130,17 +131,10 @@ module Rack #:nodoc:
130
131
  # Checks if self has a variant passed.
131
132
  # Works case-insensitively.
132
133
  #
133
- # ==== Notes
134
- # *Destructively* downcases current set of variants, if necessary.
135
- # Just note, that variants are case-insensitive, and 'convenient' form
136
- # of the Languge-Tag assumes they're in 'lowercase' notation.
137
- #
138
134
  def has_variant?(variant)
139
135
  return false unless @variants
140
- @variants.include?(variant) || begin
141
- @variants.map { |v| v.downcase! }
142
- @variants.include?(variant.downcase)
143
- end
136
+ v = variant.downcase
137
+ @variants.any? { |var| v == var || v == var.downcase }
144
138
  end
145
139
 
146
140
  # Checks if self has a singleton passed.
@@ -174,6 +168,20 @@ module Rack #:nodoc:
174
168
 
175
169
  attr_reader :tag # the most recent 'build' of tag
176
170
 
171
+ # Returns the number of subtags in self.
172
+ # Does *not* perform validation or recomposition.
173
+ #
174
+ def length
175
+ length = 1 #@primary
176
+ length += @extlang.length if @extlang
177
+ length += 1 if @script
178
+ length += 1 if @region
179
+ length += @variants.length if @variants
180
+ @extensions.each { |_,e| length += e.length+1 } if @extensions # length += @extenstions.to_a.flatten.length if @extensions
181
+ length += @privateuse.length+1 if @privateuse
182
+ length
183
+ end
184
+
177
185
  def nicecased
178
186
  recompose # we could not conveniently format malformed or invalid tags
179
187
  @nicecased #.dup #uuuuugh
@@ -181,7 +189,7 @@ module Rack #:nodoc:
181
189
 
182
190
  def to_a
183
191
  ary = [@primary]
184
- ary << @extlang if @extlang
192
+ ary.concat @extlang if @extlang
185
193
  ary << @script if @script
186
194
  ary << @region if @region
187
195
  ary.concat @variants if @variants
@@ -218,7 +226,8 @@ module Rack #:nodoc:
218
226
  # de-Deva ('Deva' not equal to 'DE')
219
227
  #++
220
228
 
221
- # Checks if the *extended* Language-Range passed matches self.
229
+ # Checks if the *extended* Language-Range (in the shortest notation)
230
+ # passed matches self.
222
231
  def matched_by_extended_range?(range)
223
232
  recompose
224
233
  subtags = @composition.split(Const::HYPHEN)
@@ -324,16 +333,16 @@ module Rack #:nodoc:
324
333
 
325
334
  # ==== Parameters
326
335
  # thing<String, optional>::
327
- # The Language-Tag snippet
336
+ # The LangTag snippet
328
337
  #
329
338
  # ==== Returns
330
339
  # +self+
331
340
  #
332
341
  # ==== Raises
333
342
  # ArgumentError::
334
- # The Language-Tag composition:
343
+ # The snippet passed:
335
344
  # * does not conform the Language-Tag ABNF (malformed)
336
- # * grandfathered
345
+ # * represents a 'grandfathered' Language-Tag
337
346
  # * starts with 'x' singleton ('privateuse').
338
347
  # * contains duplicate variants
339
348
  # * contains duplicate singletons
@@ -359,7 +368,7 @@ module Rack #:nodoc:
359
368
  components = $'.split(Utils::HYPHEN_SPLITTER)
360
369
  components.shift
361
370
 
362
- @primary, @extlang = @primary.split(Utils::HYPHEN_SPLITTER) if @primary.include?(Const::HYPHEN)
371
+ @primary, *@extlang = @primary.split(Utils::HYPHEN_SPLITTER) if @primary.include?(Const::HYPHEN)
363
372
 
364
373
  @script.capitalize! if @script
365
374
  @region.upcase! if @region
@@ -0,0 +1,55 @@
1
+ require 'rack/acceptable/utils'
2
+
3
+ module Rack #:nodoc:
4
+ module Acceptable #:nodoc:
5
+ module Charsets
6
+
7
+ # ==== Returns
8
+ # An Array with wildcards / *downcased* Charsets and
9
+ # associated quality factors (qvalues). Default qvalue is 1.0.
10
+ #
11
+ # ==== Raises
12
+ # ArgumentError::
13
+ # Syntax of the Accept-Charset request-header is bad.
14
+ # For example, one of Charsets is not a 'token',
15
+ # one of quality factors is malformed etc.
16
+ #
17
+ def acceptable_charsets
18
+ Utils.parse_header(
19
+ env[Const::ENV_HTTP_ACCEPT_CHARSET].to_s.downcase,
20
+ Utils::HTTP_ACCEPT_TOKEN_REGEX)
21
+ rescue
22
+ raise ArgumentError,
23
+ "Malformed Accept-Charset header: #{env[Const::ENV_HTTP_ACCEPT_CHARSET].inspect}"
24
+ end
25
+
26
+ # Checks if the Charset (as a +String+) passed acceptable.
27
+ # Works case-insensitively.
28
+ #
29
+ def accept_charset?(chs)
30
+ chs = chs.downcase
31
+ return true if (accepts = acceptable_charsets).empty?
32
+ if ch = accepts.assoc(chs) || accepts.assoc(Const::WILDCARD)
33
+ ch.last > 0
34
+ else
35
+ chs == Const::ISO_8859_1
36
+ end
37
+ rescue
38
+ false
39
+ end
40
+
41
+ # Detects the best Charset.
42
+ # Works case-insensitively.
43
+ #
44
+ def negotiate_charset(*things)
45
+ things.map!{|t| t.downcase}
46
+ Utils.detect_best_charset(things, acceptable_charsets)
47
+ end
48
+
49
+ alias :preferred_charset_from :negotiate_charset
50
+
51
+ end
52
+ end
53
+ end
54
+
55
+ # EOF
@@ -0,0 +1,30 @@
1
+ require 'rack/acceptable/utils'
2
+
3
+ module Rack #:nodoc:
4
+ module Acceptable #:nodoc:
5
+ module Encodings
6
+
7
+ # ==== Returns
8
+ # An Array with wildcards / *downcased* Content-Codings
9
+ # and associated quality factors (qvalues). Default qvalue is 1.0.
10
+ #
11
+ # ==== Raises
12
+ # ArgumentError::
13
+ # Syntax of the Accept-Encoding request-header is bad.
14
+ # For example, one of Content-Codings is not a 'token',
15
+ # one of quality factors is malformed etc.
16
+ #
17
+ def acceptable_encodings
18
+ Utils.parse_header(
19
+ env[Const::ENV_HTTP_ACCEPT_ENCODING].to_s.downcase,
20
+ Utils::HTTP_ACCEPT_TOKEN_REGEX)
21
+ rescue
22
+ raise ArgumentError,
23
+ "Malformed Accept-Encoding header: #{env[Const::ENV_HTTP_ACCEPT_ENCODING].inspect}"
24
+ end
25
+
26
+ end
27
+ end
28
+ end
29
+
30
+ # EOF
@@ -1,84 +1,14 @@
1
- require 'rack/acceptable/utils'
1
+ require 'rack/acceptable/mixin/charsets'
2
+ require 'rack/acceptable/mixin/encodings'
3
+ require 'rack/acceptable/mixin/languages'
4
+ require 'rack/acceptable/mixin/media'
2
5
 
3
6
  module Rack #:nodoc:
4
7
  module Acceptable #:nodoc:
5
8
  module Headers
6
9
 
7
- # ==== Returns
8
- # An Array with wildcards / *downcased* Content-Codings
9
- # and associated quality factors (qvalues). Default qvalue is 1.0.
10
- #
11
- # ==== Raises
12
- # ArgumentError::
13
- # Syntax of the Accept-Encoding request-header is bad.
14
- # For example, one of Content-Codings is not a 'token',
15
- # one of quality factors is malformed etc.
16
- #
17
- def acceptable_encodings
18
- Utils.parse_header(
19
- env[Const::ENV_HTTP_ACCEPT_ENCODING].to_s.downcase,
20
- Utils::HTTP_ACCEPT_TOKEN_REGEX)
21
- rescue
22
- raise ArgumentError,
23
- "Malformed Accept-Encoding header: #{env[Const::ENV_HTTP_ACCEPT_ENCODING].inspect}"
24
- end
25
-
26
- # ==== Returns
27
- # An Array with wildcards / *downcased* Charsets and
28
- # associated quality factors (qvalues). Default qvalue is 1.0.
29
- #
30
- # ==== Raises
31
- # ArgumentError::
32
- # Syntax of the Accept-Charset request-header is bad.
33
- # For example, one of Charsets is not a 'token',
34
- # one of quality factors is malformed etc.
35
- #
36
- def acceptable_charsets
37
- Utils.parse_header(
38
- env[Const::ENV_HTTP_ACCEPT_CHARSET].to_s.downcase,
39
- Utils::HTTP_ACCEPT_TOKEN_REGEX)
40
- rescue
41
- raise ArgumentError,
42
- "Malformed Accept-Charset header: #{env[Const::ENV_HTTP_ACCEPT_CHARSET].inspect}"
43
- end
44
-
45
- # ==== Returns
46
- # An Array with wildcards / Language-Tags (as +Strings+)
47
- # and associated quality factors (qvalues). Default qvalue is 1.0.
48
- #
49
- # ==== Raises
50
- # ArgumentError::
51
- # Syntax of the Accept-Language request-header is bad.
52
- # For example, one of Language-Ranges is not in a RFC 'Language-Range'
53
- # pattern, one of quality factors is malformed etc.
54
- #
55
- # ==== Notes
56
- # * It uses {Extended Language-Range pattern}[http://tools.ietf.org/html/rfc4647#section-2.2].
57
- # * It does *not* perform 'convenient transformations' (downcasing of primary tags etc).
58
- # In other words, it parses Accept-Language header in unpretentious manner.
59
- #
60
- def acceptable_language_ranges
61
- Utils.parse_header(
62
- env[Const::ENV_HTTP_ACCEPT_LANGUAGE].to_s,
63
- Utils::HTTP_ACCEPT_LANGUAGE_REGEX)
64
- rescue
65
- raise ArgumentError,
66
- "Malformed Accept-Language header: #{env[Const::ENV_HTTP_ACCEPT_LANGUAGE].inspect}"
67
- end
68
-
69
- # ==== Returns
70
- # An Array with Media-Ranges (as +Strings+) / wildcards and
71
- # associated qvalues. Default qvalue is 1.0.
72
- #
73
- # ==== Raises
74
- # ArgumentError::
75
- # There's a malformed qvalue in header.
76
- #
77
- def acceptable_media_ranges
78
- Utils.extract_qvalues(env[Const::ENV_HTTP_ACCEPT].to_s)
79
- rescue
80
- raise ArgumentError,
81
- "Malformed Accept header: #{env[Const::ENV_HTTP_ACCEPT].inspect}"
10
+ def self.included(mod)
11
+ mod.send :include, Charsets, Encodings, Languages, Media
82
12
  end
83
13
 
84
14
  end
@@ -0,0 +1,46 @@
1
+ require 'rack/acceptable/language_tag'
2
+
3
+ module Rack #:nodoc:
4
+ module Acceptable #:nodoc:
5
+ module Languages
6
+
7
+ # ==== Returns
8
+ # An Array with wildcards / Language-Tags (as +Strings+)
9
+ # and associated quality factors (qvalues). Default qvalue is 1.0.
10
+ #
11
+ # ==== Raises
12
+ # ArgumentError::
13
+ # Syntax of the Accept-Language request-header is bad.
14
+ # For example, one of Language-Ranges is not in a RFC 'Language-Range'
15
+ # pattern, one of quality factors is malformed etc.
16
+ #
17
+ # ==== Notes
18
+ # * It uses {Extended Language-Range pattern}[http://tools.ietf.org/html/rfc4647#section-2.2].
19
+ # * It does *not* perform 'convenient transformations' (downcasing of primary tags etc).
20
+ # In other words, it parses Accept-Language header in unpretentious manner.
21
+ #
22
+ def acceptable_language_ranges
23
+ Utils.parse_header(
24
+ env[Const::ENV_HTTP_ACCEPT_LANGUAGE].to_s,
25
+ Utils::HTTP_ACCEPT_LANGUAGE_REGEX)
26
+ rescue
27
+ raise ArgumentError,
28
+ "Malformed Accept-Language header: #{env[Const::ENV_HTTP_ACCEPT_LANGUAGE].inspect}"
29
+ end
30
+
31
+ # Checks if the Language-Tag (as a +String+ or
32
+ # +Rack::Acceptable::LanguageTag+) passed acceptable.
33
+ # Works case-insensitively.
34
+ #
35
+ def accept_language?(tag)
36
+ langtag = LanguageTag.parse(tag)
37
+ acceptable_language_ranges.any? { |l,q| q > 0 && langtag.matched_by_extended_range?(l) }
38
+ rescue
39
+ false
40
+ end
41
+
42
+ end
43
+ end
44
+ end
45
+
46
+ # EOF
@@ -4,6 +4,21 @@ module Rack #:nodoc:
4
4
  module Acceptable #:nodoc:
5
5
  module Media
6
6
 
7
+ # ==== Returns
8
+ # An Array with Media-Ranges (as +Strings+) / wildcards and
9
+ # associated qvalues. Default qvalue is 1.0.
10
+ #
11
+ # ==== Raises
12
+ # ArgumentError::
13
+ # There's a malformed qvalue in header.
14
+ #
15
+ def acceptable_media_ranges
16
+ Utils.extract_qvalues(env[Const::ENV_HTTP_ACCEPT].to_s)
17
+ rescue
18
+ raise ArgumentError,
19
+ "Malformed Accept header: #{env[Const::ENV_HTTP_ACCEPT].inspect}"
20
+ end
21
+
7
22
  # ==== Returns
8
23
  # An Array with *completely* parsed MIME-Types (incl. qvalues
9
24
  # and accept-extensions; see Rack::Acceptable::MIMETypes).
@@ -17,16 +32,13 @@ module Rack #:nodoc:
17
32
  # or, at last, one of MIME-Types has malformed qvalue.
18
33
  #
19
34
  def acceptable_media
20
- @_acceptable_media ||= begin
21
- header = env[Const::ENV_HTTP_ACCEPT].to_s
22
- header.split(Utils::COMMA_SPLITTER).map! { |entry| MIMETypes.parse_mime_type(entry) }
23
- end
35
+ header = env[Const::ENV_HTTP_ACCEPT].to_s
36
+ header.split(Utils::COMMA_SPLITTER).map! { |entry| MIMETypes.parse_mime_type(entry) }
24
37
  end
25
38
 
26
39
  # Checks if the MIME-Type passed acceptable.
27
40
  def accept_media?(thing)
28
- qvalue = MIMETypes.weigh_mime_type(thing, acceptable_media).first
29
- qvalue > 0
41
+ MIMETypes.weigh_mime_type(thing, acceptable_media).first > 0
30
42
  rescue
31
43
  false
32
44
  end
@@ -1,28 +1,18 @@
1
1
  require 'rack/request'
2
2
  require 'rack/acceptable/mixin/headers'
3
- require 'rack/acceptable/mixin/media'
4
3
 
5
4
  module Rack #:nodoc:
6
5
  module Acceptable #:nodoc:
7
6
  class Request < Rack::Request
7
+
8
8
  include Rack::Acceptable::Headers
9
- include Rack::Acceptable::Media
10
9
 
11
- def acceptable_charsets
12
- @_acceptable_charsets ||= super
10
+ def acceptable_media
11
+ @_acceptable_media ||= super
13
12
  end
14
13
 
15
- def accept_charset?(chs)
16
- chs = chs.downcase
17
- accepts = acceptable_charsets
18
- return true if accepts.empty?
19
- if ch = accepts.assoc(chs) || accepts.assoc(Const::WILDCARD)
20
- ch.last > 0
21
- else
22
- chs == Const::ISO_8859_1
23
- end
24
- rescue
25
- false
14
+ def acceptable_charsets
15
+ @_acceptable_charsets ||= super
26
16
  end
27
17
 
28
18
  def accept_content?(content_type)
@@ -23,8 +23,8 @@ module Rack #:nodoc:
23
23
  if RUBY_VERSION < '1.9.1'
24
24
 
25
25
  PAIR_SPLITTER = /\=/.freeze
26
- HYPHEN_SPLITTER = /-/
27
- COMMA_SPLITTER = /,/
26
+ HYPHEN_SPLITTER = /-/.freeze
27
+ COMMA_SPLITTER = /,/.freeze
28
28
  SEMICOLON_SPLITTER = /;/.freeze
29
29
 
30
30
  else
@@ -211,6 +211,7 @@ module Rack #:nodoc:
211
211
  # use of digits anywhere in the 'language-range' (see [RFC2616errata]).
212
212
  #++
213
213
 
214
+ # TODO: move to LanguageTag or Languages
214
215
  HTTP_ACCEPT_LANGUAGE_REGEX = /^\s*(\*|[a-z]{1,8}(?:-[a-z\d]{1,8}|-\*)*)#{Utils::QUALITY_PATTERN}\s*$/io.freeze
215
216
 
216
217
  def normalize_header(header)
@@ -1,6 +1,6 @@
1
1
  module Rack #:nodoc:
2
2
  module Acceptable #:nodoc:
3
- VERSION = '0.2.2'
3
+ VERSION = '0.2.3'
4
4
  end
5
5
  end
6
6
 
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acceptable
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 17
4
5
  prerelease: false
5
6
  segments:
6
7
  - 0
7
8
  - 2
8
- - 2
9
- version: 0.2.2
9
+ - 3
10
+ version: 0.2.3
10
11
  platform: ruby
11
12
  authors:
12
13
  - SSDany
@@ -14,16 +15,18 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2010-04-17 00:00:00 +04:00
18
+ date: 2010-07-01 00:00:00 +04:00
18
19
  default_executable:
19
20
  dependencies:
20
21
  - !ruby/object:Gem::Dependency
21
22
  name: rack
22
23
  prerelease: false
23
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
24
26
  requirements:
25
27
  - - ">="
26
28
  - !ruby/object:Gem::Version
29
+ hash: 23
27
30
  segments:
28
31
  - 1
29
32
  - 0
@@ -47,11 +50,14 @@ files:
47
50
  - README.rdoc
48
51
  - lib/rack/acceptable/const.rb
49
52
  - lib/rack/acceptable/language_tag.rb
53
+ - lib/rack/acceptable/middleware/fake_accept.rb
50
54
  - lib/rack/acceptable/middleware/formats.rb
51
55
  - lib/rack/acceptable/middleware/provides.rb
52
- - lib/rack/acceptable/middleware/fake_accept.rb
53
56
  - lib/rack/acceptable/mimetypes.rb
57
+ - lib/rack/acceptable/mixin/charsets.rb
58
+ - lib/rack/acceptable/mixin/encodings.rb
54
59
  - lib/rack/acceptable/mixin/headers.rb
60
+ - lib/rack/acceptable/mixin/languages.rb
55
61
  - lib/rack/acceptable/mixin/media.rb
56
62
  - lib/rack/acceptable/request.rb
57
63
  - lib/rack/acceptable/utils.rb
@@ -68,23 +74,27 @@ rdoc_options: []
68
74
  require_paths:
69
75
  - lib
70
76
  required_ruby_version: !ruby/object:Gem::Requirement
77
+ none: false
71
78
  requirements:
72
79
  - - ">="
73
80
  - !ruby/object:Gem::Version
81
+ hash: 3
74
82
  segments:
75
83
  - 0
76
84
  version: "0"
77
85
  required_rubygems_version: !ruby/object:Gem::Requirement
86
+ none: false
78
87
  requirements:
79
88
  - - ">="
80
89
  - !ruby/object:Gem::Version
90
+ hash: 3
81
91
  segments:
82
92
  - 0
83
93
  version: "0"
84
94
  requirements: []
85
95
 
86
96
  rubyforge_project: acceptable
87
- rubygems_version: 1.3.6
97
+ rubygems_version: 1.3.7
88
98
  signing_key:
89
99
  specification_version: 3
90
100
  summary: HTTP Accept parsers for Rack.