content-type 0.0.1 → 0.0.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: b8464c107af9eddb3aa7fcc295d6d5b30ef0a40e2242b0f2709b50ca5f959e1e
4
+ data.tar.gz: 0d3e0fdb8ac83ab7d711bbff6b96955eb01961e41df565fee21a1e59fbb04614
5
+ SHA512:
6
+ metadata.gz: 6a46e454ac6e9999c570de258b2e58a9144549bfa32e2dedc172d5595d442a92dd7b822ae98d3de184fa95020b9662d1ffd579c4d81f42e2e0fe8f702deaed28
7
+ data.tar.gz: 607d2874c0edabd23c055bf22a550f70206c2e1f36c8f6fb091d494405b6c833d07965a0fc30fa48885b7fc1dadc9cc94ad897002e0f57a448f87deb3cffcd99
data/.editorconfig ADDED
@@ -0,0 +1,7 @@
1
+ root = true
2
+
3
+ [*.rb]
4
+ indent_size = 2
5
+ indent_style = space
6
+ trim_trailing_whitespace = true
7
+ insert_final_newline = true
@@ -0,0 +1,44 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ pull_request:
7
+ branches: [ main ]
8
+
9
+ env:
10
+ BUNDLE_WITHOUT: "development"
11
+
12
+ jobs:
13
+ test:
14
+ runs-on: ${{ matrix.os }}
15
+
16
+ strategy:
17
+ matrix:
18
+ ruby: [ ruby-2.6, ruby-2.7, ruby-3.0, ruby-3.1 ]
19
+ os: [ ubuntu-latest ]
20
+
21
+ steps:
22
+ - uses: actions/checkout@v3
23
+
24
+ - uses: ruby/setup-ruby@v1
25
+ with:
26
+ ruby-version: ${{ matrix.ruby }}
27
+ bundler-cache: true
28
+
29
+ - name: bundle exec rspec
30
+ run: bundle exec rspec --format progress --force-colour
31
+
32
+ lint:
33
+ runs-on: ubuntu-latest
34
+
35
+ steps:
36
+ - uses: actions/checkout@v3
37
+
38
+ - uses: ruby/setup-ruby@v1
39
+ with:
40
+ ruby-version: 2.6
41
+ bundler-cache: true
42
+
43
+ - name: bundle exec rubocop
44
+ run: bundle exec rubocop --format progress --color
data/.gitignore CHANGED
@@ -15,3 +15,4 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
+ spec/examples.txt
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
@@ -0,0 +1,3 @@
1
+ Naming/FileName:
2
+ Exclude:
3
+ - lib/content-type.rb
@@ -0,0 +1,6 @@
1
+ Style/StringLiterals:
2
+ Enabled: true
3
+ EnforcedStyle: double_quotes
4
+
5
+ Style/YodaCondition:
6
+ Enabled: false
data/.rubocop.yml CHANGED
@@ -1,11 +1,16 @@
1
- StringLiterals:
2
- EnforcedStyle: double_quotes
1
+ require:
2
+ - rubocop-performance
3
+ - rubocop-rake
4
+ - rubocop-rspec
3
5
 
4
- EmptyLines:
5
- Enabled: false
6
+ inherit_from:
7
+ - .rubocop_todo.yml
8
+ - .rubocop/naming.yml
9
+ - .rubocop/style.yml
6
10
 
7
- Alias:
8
- Enabled: false
9
-
10
- Documentation:
11
- Enabled: false
11
+ AllCops:
12
+ NewCops: enable
13
+ DisplayCopNames: true
14
+ DisplayStyleGuide: true
15
+ ExtraDetails: true
16
+ TargetRubyVersion: 2.6
data/.rubocop_todo.yml ADDED
@@ -0,0 +1,64 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2022-07-10 04:12:46 UTC using RuboCop version 1.31.2.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 1
10
+ # Configuration parameters: Include.
11
+ # Include: **/*.gemspec
12
+ Gemspec/RequiredRubyVersion:
13
+ Exclude:
14
+ - 'content_type.gemspec'
15
+
16
+ # Offense count: 2
17
+ # Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods.
18
+ # IgnoredMethods: refine
19
+ Metrics/BlockLength:
20
+ Max: 49
21
+
22
+ # Offense count: 1
23
+ # Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames.
24
+ # AllowedNames: at, by, db, id, in, io, ip, of, on, os, pp, to
25
+ Naming/MethodParameterName:
26
+ Exclude:
27
+ - 'lib/content_type/parser.rb'
28
+
29
+ # Offense count: 3
30
+ # This cop supports safe autocorrection (--autocorrect).
31
+ # Configuration parameters: EnforcedStyle.
32
+ # SupportedStyles: prefer_alias, prefer_alias_method
33
+ Style/Alias:
34
+ Exclude:
35
+ - 'lib/content_type.rb'
36
+ - 'lib/content_type/parser.rb'
37
+
38
+ # Offense count: 1
39
+ # This cop supports safe autocorrection (--autocorrect).
40
+ Style/ExpandPathArguments:
41
+ Exclude:
42
+ - 'content_type.gemspec'
43
+
44
+ # Offense count: 2
45
+ # This cop supports safe autocorrection (--autocorrect).
46
+ # Configuration parameters: EnforcedShorthandSyntax, UseHashRocketsWithSymbolValues, PreferHashRocketsForNonAlnumEndingSymbols.
47
+ # SupportedStyles: ruby19, hash_rockets, no_mixed_keys, ruby19_no_mixed_keys
48
+ # SupportedShorthandSyntax: always, never, either
49
+ Style/HashSyntax:
50
+ EnforcedStyle: hash_rockets
51
+
52
+ # Offense count: 2
53
+ # This cop supports safe autocorrection (--autocorrect).
54
+ # Configuration parameters: EnforcedStyle, AllowInnerSlashes.
55
+ # SupportedStyles: slashes, percent_r, mixed
56
+ Style/RegexpLiteral:
57
+ Exclude:
58
+ - 'content_type.gemspec'
59
+
60
+ # Offense count: 1
61
+ # This cop supports unsafe autocorrection (--autocorrect-all).
62
+ Style/SlicingWithRange:
63
+ Exclude:
64
+ - 'lib/content_type.rb'
data/Gemfile CHANGED
@@ -1,19 +1,30 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source "https://rubygems.org"
2
4
 
5
+ gem "rake"
6
+
3
7
  group :development do
4
- gem "rake"
5
8
  gem "guard"
6
9
  gem "guard-rspec"
10
+
11
+ # RSpec formatter
12
+ gem "fuubar", :require => false
7
13
  end
8
14
 
9
15
  group :test do
10
- gem "coveralls", :require => false
11
- gem "simplecov", :require => false
16
+ gem "rspec"
17
+ gem "rspec-its"
18
+
19
+ gem "rubocop", "~> 1.31.2"
20
+ gem "rubocop-performance"
21
+ gem "rubocop-rake"
22
+ gem "rubocop-rspec"
23
+ end
12
24
 
13
- gem "rspec", ">= 2.14"
14
- gem "rubocop", ">= 0.16"
15
- gem "yardstick"
25
+ group :doc do
26
+ gem "yard"
16
27
  end
17
28
 
18
- # Specify your gem's dependencies in content-type.gemspec
29
+ # Specify your gem"s dependencies in content-type.gemspec
19
30
  gemspec
data/Guardfile CHANGED
@@ -1,9 +1,16 @@
1
- # A sample Guardfile
2
- # More info at https://github.com/guard/guard#readme
1
+ # frozen_string_literal: true
3
2
 
4
- guard :rspec do
5
- watch(%r{^spec/.+_spec\.rb$})
6
- watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
- watch('spec/spec_helper.rb') { "spec" }
8
- end
3
+ guard :rspec, :cmd => "bundle exec rspec" do
4
+ require "guard/rspec/dsl"
5
+ dsl = Guard::RSpec::Dsl.new(self)
6
+
7
+ # RSpec files
8
+ rspec = dsl.rspec
9
+ watch(rspec.spec_helper) { rspec.spec_dir }
10
+ watch(rspec.spec_support) { rspec.spec_dir }
11
+ watch(rspec.spec_files)
9
12
 
13
+ # Ruby files
14
+ ruby = dsl.ruby
15
+ dsl.watch_spec_files_for(ruby.lib_files)
16
+ end
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2014 Aleksey V Zapparov
1
+ Copyright (c) 2015-2022 Alexey V Zapparov
2
2
 
3
3
  MIT License
4
4
 
data/README.adoc ADDED
@@ -0,0 +1,89 @@
1
+ = ContentType
2
+
3
+ :gem-image: image:https://img.shields.io/gem/v/content-type?logo=ruby[Last Release]
4
+ :gem-link: https://rubygems.org/gems/content-type
5
+ :license-image: image:https://img.shields.io/badge/license-MIT-blue.svg[MIT License]
6
+ :license-link: https://github.com/httprb/content-type.rb/blob/main/LICENSE.txt
7
+ :ci-image: image:https://github.com/httprb/content_type.rb/actions/workflows/ci.yml/badge.svg[CI Status]
8
+ :ci-link: https://github.com/httprb/content_type.rb/actions/workflows/ci.yml
9
+ :rfc-link: http://tools.ietf.org/html/rfc2045#section-5.1
10
+ :parslet-link: https://kschiess.github.io/parslet/
11
+
12
+ {gem-link}[{gem-image}]
13
+ {license-link}[{license-image}]
14
+ {ci-link}[{ci-image}]
15
+
16
+ {rfc-link}[RFC]-compliant HTTP Content-Type parser.
17
+
18
+ WARNING: I've started this project simply to play with {parslet-link}[parslet].
19
+ It's fully functional, but because of using parslet under the hood, it works
20
+ less efficient than it could.
21
+
22
+
23
+ == Installation
24
+
25
+ Add this line to your application's Gemfile:
26
+
27
+ gem "content-type"
28
+
29
+ And then execute:
30
+
31
+
32
+ $ bundle
33
+
34
+ Or install it yourself as:
35
+
36
+ $ gem install content-type
37
+
38
+
39
+ == Usage
40
+
41
+ [source,ruby]
42
+ ----
43
+ content_type = ContentType.parse "application/JSON; charset=utf-8; foo=bar"
44
+ content_type.mime_type # => "application/json"
45
+ content_type.type # => "application"
46
+ content_type.subtype # => "json"
47
+ content_type.charset # => "utf-8"
48
+ content_type.parameters["charset"] # => "utf-8"
49
+ content_type.parameters["foo"] # => "bar"
50
+ ----
51
+
52
+
53
+ == Supported Ruby Versions
54
+
55
+ This library aims to support and is {ci-link}[tested against] the following Ruby
56
+ versions:
57
+
58
+ * Ruby 2.6
59
+ * Ruby 2.7
60
+ * Ruby 3.0
61
+ * Ruby 3.1
62
+
63
+ If something doesn't work on one of these versions, it's a bug.
64
+
65
+ This library may inadvertently work (or seem to work) on other Ruby versions,
66
+ however support will only be provided for the versions listed above.
67
+
68
+ If you would like this library to support another Ruby version or
69
+ implementation, you may volunteer to be a maintainer. Being a maintainer
70
+ entails making sure all tests run and pass on that implementation. When
71
+ something breaks on your implementation, you will be responsible for providing
72
+ patches in a timely fashion. If critical issues for a particular implementation
73
+ exist at the time of a major release, support for that Ruby version may be
74
+ dropped.
75
+
76
+
77
+ == Contributing
78
+
79
+ . Fork it ( http://github.com/httprb/content-type/fork )
80
+ . Create your feature branch (`git checkout -b my-new-feature`)
81
+ . Commit your changes (`git commit -am 'Add some feature'`)
82
+ . Push to the branch (`git push origin my-new-feature`)
83
+ . Create new Pull Request
84
+
85
+
86
+ == Copyright
87
+
88
+ Copyright © 2015-2022 Alexey Zapparov.
89
+ See LICENSE.txt for further details.
data/Rakefile CHANGED
@@ -1,28 +1,12 @@
1
1
  #!/usr/bin/env rake
2
- require 'bundler/gem_tasks'
2
+ # frozen_string_literal: true
3
3
 
4
- require 'rspec/core/rake_task'
5
- RSpec::Core::RakeTask.new
6
-
7
- task :test => :spec
4
+ require "bundler/gem_tasks"
8
5
 
9
- begin
10
- require 'rubocop/rake_task'
11
- Rubocop::RakeTask.new
12
- rescue LoadError
13
- task :rubocop do
14
- $stderr.puts 'Rubocop is disabled'
15
- end
16
- end
17
-
18
- require 'yardstick/rake/measurement'
19
- Yardstick::Rake::Measurement.new do |measurement|
20
- measurement.output = 'measurement/report.txt'
21
- end
6
+ require "rspec/core/rake_task"
7
+ RSpec::Core::RakeTask.new
22
8
 
23
- require 'yardstick/rake/verify'
24
- Yardstick::Rake::Verify.new do |verify|
25
- verify.threshold = 52.0
26
- end
9
+ require "rubocop/rake_task"
10
+ RuboCop::RakeTask.new
27
11
 
28
- task :default => [:spec, :rubocop, :verify_measurements]
12
+ task :default => %i[spec rubocop]
data/content-type.gemspec CHANGED
@@ -1,24 +1,24 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'content_type/version'
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "./lib/content_type/version"
5
4
 
6
5
  Gem::Specification.new do |spec|
7
6
  spec.name = "content-type"
8
7
  spec.version = ContentType::VERSION
8
+ spec.homepage = "https://github.com/httprb/content-type"
9
9
  spec.authors = ["Aleksey V Zapparov"]
10
10
  spec.email = ["ixti@member.fsf.org"]
11
- spec.summary = "content-type-#{ContentType::VERSION}"
12
- spec.description = %q{ContentType parser}
13
- spec.homepage = "https://github.com/ixti/content-type"
14
11
  spec.license = "MIT"
12
+ spec.summary = "content-type-#{ContentType::VERSION}"
13
+ spec.description = "HTTP ContentType header parser"
15
14
 
16
15
  spec.files = `git ls-files -z`.split("\x0")
17
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
16
  spec.require_paths = ["lib"]
20
17
 
21
- spec.add_runtime_dependency "parslet", "~> 1.5"
18
+ spec.required_ruby_version = ">= 2.6"
19
+
20
+ spec.add_runtime_dependency "parslet", "~> 2.0"
22
21
 
23
- spec.add_development_dependency "bundler", "~> 1.5"
22
+ spec.add_development_dependency "bundler", "~> 2.0"
23
+ spec.metadata["rubygems_mfa_required"] = "true"
24
24
  end
data/lib/content-type.rb CHANGED
@@ -1,2 +1,3 @@
1
- # coding: utf-8
2
- require "content_type"
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "content_type"
@@ -1,75 +1,63 @@
1
- # coding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
-
4
- # 3-rd party
5
3
  require "parslet"
6
4
 
7
-
8
5
  class ContentType
9
6
  # ContentType string parser
10
7
  class Parser < ::Parslet::Parser
11
- class CharList # :nodoc:
12
- def initialize(list = nil)
13
- @list = list || yield
14
- end
8
+ class Stri < ::Parslet::Atoms::Str # :nodoc:
9
+ def initialize(*)
10
+ super
15
11
 
16
- def -(other)
17
- CharList.new @list - other.to_a
12
+ @pat = Regexp.new(@pat.source, Regexp::IGNORECASE)
18
13
  end
14
+ end
19
15
 
20
- def +(other)
21
- CharList.new @list + other.to_a
22
- end
16
+ # rubocop:disable Layout/LineLength
17
+
18
+ CHARS = (0..127).map { |it| it.chr.freeze }.freeze
19
+ CTLS = [*(0..31), 127].map { |it| it.chr.freeze }.freeze
20
+ SPACE = " "
21
+ HTAB = 9.chr.freeze
22
+ SPECIALS = ["(", ")", "<", ">", "@", ",", ";", ":", "\\", "\"", ".", "[", "]"].freeze
23
+ TSPECIALS = (SPECIALS | ["/", "?", "="]).freeze
24
+
25
+ rule(:quoted_pair) { str("\\") >> any_of(CHARS) }
26
+ rule(:linear_ws) { (str("\r\n").repeat(0, 1) >> (str(SPACE) | str(HTAB))).repeat(1) }
27
+ rule(:qtext) { any_of(CHARS - ["\"", "\\", "\r"]) }
28
+ rule(:quoted_string) { str("\"") >> (qtext | quoted_pair).repeat.as(:value) >> str("\"") }
29
+ rule(:token) { any_of(CHARS - [SPACE, *CTLS, *TSPECIALS]).repeat(1) }
30
+ rule(:type_token) { (any_of(CHARS - [SPACE, *CTLS, *TSPECIALS]) | str(".")).repeat(1) }
31
+ rule(:space) { str(SPACE) }
23
32
 
24
- def to_a
25
- @list.dup
26
- end
27
- alias :to_ary :to_a
33
+ # This could probably be simplified, in that as per RFC 6838 the entire expression could
34
+ # just be `type_token`; the RFC names a partial but not exhaustive list of media type trees
35
+ # and all of `x_token | vendor_token | prs_token` are really just `type_token`s in a first
36
+ # place.
37
+ rule(:x_token) { stri("x-") >> type_token } # DEPRECATED - see RFC 6838
38
+ rule(:vendor_token) { stri("vnd.") >> type_token } # vendor tree - see RFC 6838
39
+ rule(:prs_token) { stri("prs.") >> type_token } # personal/vanity tree - see RFC 6838
40
+ rule(:type) { stri("application") | stri("audio") | stri("image") | stri("message") | stri("multipart") | stri("text") | stri("video") | x_token | vendor_token | prs_token }
41
+
42
+ rule(:subtype) { type_token }
43
+ rule(:attribute) { token }
44
+ rule(:value) { token.as(:value) | quoted_string }
45
+ rule(:parameter) { attribute.as(:attribute) >> str("=") >> value }
46
+ rule(:parameters) { space.repeat >> str(";") >> space.repeat >> parameter.as(:parameter) }
47
+ rule(:content_type) { type.as(:type) >> str("/") >> subtype.as(:subtype) >> parameters.repeat }
28
48
 
29
- def to_s
30
- @list.join
31
- end
32
- alias :to_str :to_s
49
+ root(:content_type)
33
50
 
34
- def size
35
- to_s.size
36
- end
37
- end
51
+ # rubocop:enable Layout/LineLength
38
52
 
53
+ private
39
54
 
40
- def stri(s)
41
- s.split(//).map { |c| match["#{c.upcase}#{c.downcase}"] }.reduce :>>
55
+ def any_of(chars)
56
+ chars.map { |char| str(char) }.inject(:|)
42
57
  end
43
58
 
44
-
45
- # rubocop:disable LineLength
46
- # rubocop:disable Blocks
47
- # rubocop:disable BlockAlignment
48
-
49
- CHAR = CharList.new { (0..127).to_a.map(&:chr) }
50
- CTLS = CharList.new { (0..31).to_a.map(&:chr) << 127.chr }
51
- CR = CharList.new { [13.chr] }
52
- LF = CharList.new { [10.chr] }
53
- SPACE = CharList.new { [" "] }
54
- HTAB = CharList.new { [9.chr] }
55
- CRLF = CharList.new { [13.chr + 10.chr] }
56
- SPECIALS = CharList.new { ["(", ")", "<", ">", "@", ",", ";", ":", "\\", "\"", ".", "[", "]"] }
57
- TSPECIALS = CharList.new { SPECIALS + ["/", "?", "="] }
58
-
59
- rule(:quoted_pair) { str("\\") >> match[Regexp.escape CHAR] }
60
- rule(:linear_ws) { (str(CRLF).repeat(0, 1) >> (str(SPACE) | str(HTAB))).repeat(1) }
61
- rule(:qtext) { match[Regexp.escape CHAR - ["\"", "\\"] - CR] }
62
- rule(:quoted_string) { str('"') >> (qtext | quoted_pair).repeat.as(:value) >> str("\"") }
63
- rule(:token) { match[Regexp.escape CHAR - SPACE - CTLS - TSPECIALS].repeat(1) }
64
- rule(:space) { str(SPACE) }
65
- rule(:x_token) { stri("x") >> str("-") >> token }
66
- rule(:type) { stri("application") | stri("audio") | stri("mage") | stri("message") | stri("multipart") | stri("text") | stri("video") | x_token }
67
- rule(:subtype) { token }
68
- rule(:attribute) { token }
69
- rule(:value) { token.as(:value) | quoted_string }
70
- rule(:parameter) { attribute.as(:attribute) >> str("=") >> value }
71
- rule(:parameters) { space.repeat >> str(";") >> space.repeat >> parameter.as(:parameter) }
72
- rule(:content_type) { type.as(:type) >> str("/") >> subtype.as(:subtype) >> parameters.repeat }
73
- root(:content_type)
59
+ def stri(str)
60
+ Stri.new(str)
61
+ end
74
62
  end
75
63
  end
@@ -1,6 +1,5 @@
1
- # coding: utf-8
2
-
1
+ # frozen_string_literal: true
3
2
 
4
3
  class ContentType
5
- VERSION = "0.0.1"
4
+ VERSION = "0.0.2"
6
5
  end
data/lib/content_type.rb CHANGED
@@ -1,9 +1,7 @@
1
- # coding: utf-8
2
-
3
-
4
- require "content_type/parser"
5
- require "content_type/version"
1
+ # frozen_string_literal: true
6
2
 
3
+ require_relative "./content_type/parser"
4
+ require_relative "./content_type/version"
7
5
 
8
6
  # ContentType structure
9
7
  class ContentType
@@ -14,7 +12,7 @@ class ContentType
14
12
 
15
13
  @type = parsed.first[:type].to_s.downcase
16
14
  @subtype = parsed.first[:subtype].to_s.downcase
17
- @parameters = Hash[parse_parameters parsed[1..-1]]
15
+ @parameters = (parse_parameters parsed[1..-1]).to_h
18
16
  end
19
17
 
20
18
  def mime_type
@@ -30,7 +28,7 @@ class ContentType
30
28
  end
31
29
 
32
30
  def to_s
33
- (["#{mime_type}"] + parameters.map { |k, v| "#{k}=#{v.to_s.inspect}" })
31
+ ([mime_type.to_s] + parameters.map { |k, v| "#{k}=#{v.to_s.inspect}" })
34
32
  .compact.join("; ")
35
33
  end
36
34
  alias :to_str :to_s
@@ -39,7 +37,7 @@ class ContentType
39
37
  new Parser.new.parse str
40
38
  end
41
39
 
42
- protected
40
+ private
43
41
 
44
42
  def parse_parameters(list)
45
43
  Array(list).map do |hash|
@@ -1,40 +1,51 @@
1
- # coding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
-
4
- require "spec_helper"
5
-
6
-
7
- describe ContentType do
8
- subject(:content_type) { ContentType.parse raw }
3
+ RSpec.describe ContentType do
4
+ subject(:content_type) { described_class.parse raw }
9
5
 
10
6
  describe ".parse" do
11
- context "application/json" do
7
+ context "with ‹application/json" do
12
8
  let(:raw) { "application/json" }
13
9
 
14
- its(:type) { should eq "application" }
15
- its(:subtype) { should eq "json" }
16
- its(:charset) { should be_nil }
10
+ its(:type) { is_expected.to eq "application" }
11
+ its(:subtype) { is_expected.to eq "json" }
12
+ its(:charset) { is_expected.to be_nil }
17
13
  end
18
14
 
19
- context "application/json; charset=utf-8" do
15
+ context "with ‹application/json; charset=utf-8" do
20
16
  let(:raw) { "application/json; charset=utf-8" }
21
17
 
22
- its(:type) { should eq "application" }
23
- its(:subtype) { should eq "json" }
24
- its(:charset) { should eq "utf-8" }
18
+ its(:type) { is_expected.to eq "application" }
19
+ its(:subtype) { is_expected.to eq "json" }
20
+ its(:charset) { is_expected.to eq "utf-8" }
25
21
  end
26
22
 
27
- context "x-dead/beef; any=thing" do
23
+ context "with ‹x-dead/beef; any=thing" do
28
24
  let(:raw) { "x-dead/beef; any=thing" }
29
25
 
30
- its(:type) { should eq "x-dead" }
31
- its(:subtype) { should eq "beef" }
32
- its(:parameters) { should eq "any" => "thing" }
26
+ its(:type) { is_expected.to eq "x-dead" }
27
+ its(:subtype) { is_expected.to eq "beef" }
28
+ its(:parameters) { is_expected.to eq "any" => "thing" }
29
+ end
30
+
31
+ context "with ‹application/vnd.oasis.opendocument.text›" do
32
+ let(:raw) { "application/vnd.oasis.opendocument.text" }
33
+
34
+ its(:type) { is_expected.to eq "application" }
35
+ its(:subtype) { is_expected.to eq "vnd.oasis.opendocument.text" }
36
+ end
37
+
38
+ context "with ‹vnd.android.cursor.dir/vnd.myexample.whatever›" do
39
+ let(:raw) { "vnd.android.cursor.dir/vnd.myexample.whatever" }
40
+
41
+ its(:type) { is_expected.to eq "vnd.android.cursor.dir" }
42
+ its(:subtype) { is_expected.to eq "vnd.myexample.whatever" }
33
43
  end
34
44
  end
35
45
 
36
46
  describe "#type" do
37
47
  let(:raw) { "APPLICATION/jSOn" }
48
+
38
49
  it "is downcased" do
39
50
  expect(content_type.type).to eq "application"
40
51
  end
@@ -42,6 +53,7 @@ describe ContentType do
42
53
 
43
54
  describe "#subtype" do
44
55
  let(:raw) { "APPLICATION/jSOn" }
56
+
45
57
  it "is downcased" do
46
58
  expect(content_type.subtype).to eq "json"
47
59
  end
@@ -49,6 +61,7 @@ describe ContentType do
49
61
 
50
62
  describe "#parameters keys" do
51
63
  let(:raw) { "APPLICATION/jSOn; CHARset=utf-8" }
64
+
52
65
  it "are downcased" do
53
66
  expect(content_type.parameters).to include "charset"
54
67
  end
data/spec/spec_helper.rb CHANGED
@@ -1,2 +1,99 @@
1
- # coding: utf-8
1
+ # frozen_string_literal: true
2
+
2
3
  require "content_type"
4
+ require "rspec/its"
5
+
6
+ # This file was generated by the `rspec --init` command. Conventionally, all
7
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
8
+ # The generated `.rspec` file contains `--require spec_helper` which will cause
9
+ # this file to always be loaded, without a need to explicitly require it in any
10
+ # files.
11
+ #
12
+ # Given that it is always loaded, you are encouraged to keep this file as
13
+ # light-weight as possible. Requiring heavyweight dependencies from this file
14
+ # will add to the boot time of your test suite on EVERY test run, even for an
15
+ # individual file that may not need all of that loaded. Instead, consider making
16
+ # a separate helper file that requires the additional dependencies and performs
17
+ # the additional setup, and require it from the spec files that actually need
18
+ # it.
19
+ #
20
+ # See https://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
21
+ RSpec.configure do |config|
22
+ # rspec-expectations config goes here. You can use an alternate
23
+ # assertion/expectation library such as wrong or the stdlib/minitest
24
+ # assertions if you prefer.
25
+ config.expect_with :rspec do |expectations|
26
+ # This option will default to `true` in RSpec 4. It makes the `description`
27
+ # and `failure_message` of custom matchers include text for helper methods
28
+ # defined using `chain`, e.g.:
29
+ # be_bigger_than(2).and_smaller_than(4).description
30
+ # # => "be bigger than 2 and smaller than 4"
31
+ # ...rather than:
32
+ # # => "be bigger than 2"
33
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
34
+ end
35
+
36
+ # rspec-mocks config goes here. You can use an alternate test double
37
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
38
+ config.mock_with :rspec do |mocks|
39
+ # Prevents you from mocking or stubbing a method that does not exist on
40
+ # a real object. This is generally recommended, and will default to
41
+ # `true` in RSpec 4.
42
+ mocks.verify_partial_doubles = true
43
+ end
44
+
45
+ # This option will default to `:apply_to_host_groups` in RSpec 4 (and will
46
+ # have no way to turn it off -- the option exists only for backwards
47
+ # compatibility in RSpec 3). It causes shared context metadata to be
48
+ # inherited by the metadata hash of host groups and examples, rather than
49
+ # triggering implicit auto-inclusion in groups with matching metadata.
50
+ config.shared_context_metadata_behavior = :apply_to_host_groups
51
+
52
+ # This allows you to limit a spec run to individual examples or groups
53
+ # you care about by tagging them with `:focus` metadata. When nothing
54
+ # is tagged with `:focus`, all examples get run. RSpec also provides
55
+ # aliases for `it`, `describe`, and `context` that include `:focus`
56
+ # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
57
+ config.filter_run_when_matching :focus
58
+
59
+ # Allows RSpec to persist some state between runs in order to support
60
+ # the `--only-failures` and `--next-failure` CLI options. We recommend
61
+ # you configure your source control system to ignore this file.
62
+ config.example_status_persistence_file_path = "spec/examples.txt"
63
+
64
+ # Limits the available syntax to the non-monkey patched syntax that is
65
+ # recommended. For more details, see:
66
+ # https://relishapp.com/rspec/rspec-core/docs/configuration/zero-monkey-patching-mode
67
+ config.disable_monkey_patching!
68
+
69
+ # This setting enables warnings. It's recommended, but in some cases may
70
+ # be too noisy due to issues in dependencies.
71
+ config.warnings = true
72
+
73
+ # Many RSpec users commonly either run the entire suite or an individual
74
+ # file, and it's useful to allow more verbose output when running an
75
+ # individual spec file.
76
+ if config.files_to_run.one?
77
+ # Use the documentation formatter for detailed output,
78
+ # unless a formatter has already been configured
79
+ # (e.g. via a command-line flag).
80
+ config.default_formatter = "doc"
81
+ end
82
+
83
+ # Print the 10 slowest examples and example groups at the
84
+ # end of the spec run, to help surface which specs are running
85
+ # particularly slow.
86
+ config.profile_examples = 10
87
+
88
+ # Run specs in random order to surface order dependencies. If you find an
89
+ # order dependency and want to debug it, you can fix the order by providing
90
+ # the seed, which is printed after each run.
91
+ # --seed 1234
92
+ config.order = :random
93
+
94
+ # Seed global randomization in this process using the `--seed` CLI option.
95
+ # Setting this allows you to use `--seed` to deterministically reproduce
96
+ # test failures related to randomization by passing the same `--seed` value
97
+ # as the one that triggered the failure.
98
+ Kernel.srand config.seed
99
+ end
metadata CHANGED
@@ -1,62 +1,62 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: content-type
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
5
- prerelease:
4
+ version: 0.0.2
6
5
  platform: ruby
7
6
  authors:
8
7
  - Aleksey V Zapparov
9
- autorequire:
8
+ autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2014-01-26 00:00:00.000000000 Z
11
+ date: 2022-07-10 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: parslet
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ~>
17
+ - - "~>"
20
18
  - !ruby/object:Gem::Version
21
- version: '1.5'
19
+ version: '2.0'
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ~>
24
+ - - "~>"
28
25
  - !ruby/object:Gem::Version
29
- version: '1.5'
26
+ version: '2.0'
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: bundler
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ~>
31
+ - - "~>"
36
32
  - !ruby/object:Gem::Version
37
- version: '1.5'
33
+ version: '2.0'
38
34
  type: :development
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ~>
38
+ - - "~>"
44
39
  - !ruby/object:Gem::Version
45
- version: '1.5'
46
- description: ContentType parser
40
+ version: '2.0'
41
+ description: HTTP ContentType header parser
47
42
  email:
48
43
  - ixti@member.fsf.org
49
44
  executables: []
50
45
  extensions: []
51
46
  extra_rdoc_files: []
52
47
  files:
53
- - .gitignore
54
- - .rubocop.yml
55
- - .travis.yml
48
+ - ".editorconfig"
49
+ - ".github/workflows/ci.yml"
50
+ - ".gitignore"
51
+ - ".rspec"
52
+ - ".rubocop.yml"
53
+ - ".rubocop/naming.yml"
54
+ - ".rubocop/style.yml"
55
+ - ".rubocop_todo.yml"
56
56
  - Gemfile
57
57
  - Guardfile
58
58
  - LICENSE.txt
59
- - README.md
59
+ - README.adoc
60
60
  - Rakefile
61
61
  - content-type.gemspec
62
62
  - lib/content-type.rb
@@ -65,38 +65,28 @@ files:
65
65
  - lib/content_type/version.rb
66
66
  - spec/lib/content_type_spec.rb
67
67
  - spec/spec_helper.rb
68
- homepage: https://github.com/ixti/content-type
68
+ homepage: https://github.com/httprb/content-type
69
69
  licenses:
70
70
  - MIT
71
- post_install_message:
71
+ metadata:
72
+ rubygems_mfa_required: 'true'
73
+ post_install_message:
72
74
  rdoc_options: []
73
75
  require_paths:
74
76
  - lib
75
77
  required_ruby_version: !ruby/object:Gem::Requirement
76
- none: false
77
78
  requirements:
78
- - - ! '>='
79
+ - - ">="
79
80
  - !ruby/object:Gem::Version
80
- version: '0'
81
- segments:
82
- - 0
83
- hash: -979255587859896353
81
+ version: '2.6'
84
82
  required_rubygems_version: !ruby/object:Gem::Requirement
85
- none: false
86
83
  requirements:
87
- - - ! '>='
84
+ - - ">="
88
85
  - !ruby/object:Gem::Version
89
86
  version: '0'
90
- segments:
91
- - 0
92
- hash: -979255587859896353
93
87
  requirements: []
94
- rubyforge_project:
95
- rubygems_version: 1.8.23
96
- signing_key:
97
- specification_version: 3
98
- summary: content-type-0.0.1
99
- test_files:
100
- - spec/lib/content_type_spec.rb
101
- - spec/spec_helper.rb
102
- has_rdoc:
88
+ rubygems_version: 3.1.6
89
+ signing_key:
90
+ specification_version: 4
91
+ summary: content-type-0.0.2
92
+ test_files: []
data/.travis.yml DELETED
@@ -1,2 +0,0 @@
1
- language: ruby
2
- rvm: [ 1.9.3, 2.0.0, 2.1.0 ]
data/README.md DELETED
@@ -1,37 +0,0 @@
1
- # Content::Type
2
-
3
- RFC-compliant Content-Type parser.
4
-
5
- ## Installation
6
-
7
- Add this line to your application's Gemfile:
8
-
9
- gem 'content-type'
10
-
11
- And then execute:
12
-
13
- $ bundle
14
-
15
- Or install it yourself as:
16
-
17
- $ gem install content-type
18
-
19
- ## Usage
20
-
21
- ``` ruby
22
- content_type = ContentType.parse "application/JSON; charset=utf-8; foo=bar"
23
- content_type.mime_type # => "application/json"
24
- content_type.type # => "application"
25
- content_type.subtype # => "json"
26
- content_type.charset # => "utf-8"
27
- content_type.parameters["charset"] # => "utf-8"
28
- content_type.parameters["foo"] # => "bar"
29
- ```
30
-
31
- ## Contributing
32
-
33
- 1. Fork it ( http://github.com/<my-github-username>/content-type/fork )
34
- 2. Create your feature branch (`git checkout -b my-new-feature`)
35
- 3. Commit your changes (`git commit -am 'Add some feature'`)
36
- 4. Push to the branch (`git push origin my-new-feature`)
37
- 5. Create new Pull Request