diff --git a/lib/linguist/blob_helper.rb b/lib/linguist/blob_helper.rb index 8050d37b..49fa3ca7 100644 --- a/lib/linguist/blob_helper.rb +++ b/lib/linguist/blob_helper.rb @@ -53,7 +53,7 @@ module Linguist # # Returns a content type String. def content_type - @content_type ||= binary? ? mime_type : + @content_type ||= (binary_mime_type? || binary?) ? mime_type : (encoding ? "text/plain; charset=#{encoding.downcase}" : "text/plain") end diff --git a/lib/linguist/mime.rb b/lib/linguist/mime.rb index 613e0914..e280209f 100644 --- a/lib/linguist/mime.rb +++ b/lib/linguist/mime.rb @@ -1,6 +1,10 @@ require 'mime/types' require 'yaml' +class MIME::Type + attr_accessor :override +end + # Register additional mime type extensions # # Follows same format as mime-types data file @@ -33,6 +37,8 @@ File.read(File.expand_path("../mimes.yml", __FILE__)).lines.each do |line| mime_type.encoding = encoding end + mime_type.override = true + # Kind of hacky, but we need to reindex the mime type after making changes MIME::Types.add_type_variant(mime_type) MIME::Types.index_extensions(mime_type) @@ -72,8 +78,11 @@ module Linguist guesses = ::MIME::Types.type_for(ext_or_mime_type) end - # Prefer text mime types over binary - guesses.detect { |type| type.ascii? } || + # Use custom override first + guesses.detect { |type| type.override } || + + # Prefer text mime types over binary + guesses.detect { |type| type.ascii? } || # Otherwise use the first guess guesses.first diff --git a/linguist.gemspec b/linguist.gemspec index 12c7e765..b6dd8b5b 100644 --- a/linguist.gemspec +++ b/linguist.gemspec @@ -10,7 +10,7 @@ Gem::Specification.new do |s| s.add_dependency 'charlock_holmes', '~> 0.6.6' s.add_dependency 'escape_utils', '~> 0.2.3' - s.add_dependency 'mime-types', '~> 1.16' + s.add_dependency 'mime-types', '~> 1.18' s.add_dependency 'pygments.rb', '~> 0.2.8' s.add_development_dependency 'rake' end diff --git a/test/test_blob.rb b/test/test_blob.rb index f62ad060..fe8dce62 100644 --- a/test/test_blob.rb +++ b/test/test_blob.rb @@ -33,6 +33,7 @@ class TestBlob < Test::Unit::TestCase def test_mime_type assert_equal "application/octet-stream", blob("dog.o").mime_type + assert_equal "application/ogg", blob("foo.ogg").mime_type assert_equal "application/postscript", blob("octocat.ai").mime_type assert_equal "application/x-ruby", blob("grit.rb").mime_type assert_equal "application/x-sh", blob("script.sh").mime_type @@ -42,6 +43,7 @@ class TestBlob < Test::Unit::TestCase def test_content_type assert_equal "application/octet-stream", blob("dog.o").content_type + assert_equal "application/ogg", blob("foo.ogg").content_type assert_equal "application/pdf", blob("foo.pdf").content_type assert_equal "image/png", blob("foo.png").content_type assert_equal "text/plain; charset=iso-8859-2", blob("README").content_type diff --git a/test/test_mime.rb b/test/test_mime.rb index 454bee81..b18a6600 100644 --- a/test/test_mime.rb +++ b/test/test_mime.rb @@ -14,6 +14,20 @@ class TestMime < Test::Unit::TestCase # in mimes.yml. Its still useful to test even trivial cases since # MIME::Type's extension lookup may return multiple matches and we # only pick one of them. Please keep this list alphabetized. + assert_equal 'application/javascript', Mime.mime_for('.js') + assert_equal 'application/octet-stream', Mime.mime_for('.dll') + assert_equal 'application/octet-stream', Mime.mime_for('.dmg') + assert_equal 'application/octet-stream', Mime.mime_for('.exe') + assert_equal 'application/ogg', Mime.mime_for('.ogg') + assert_equal 'application/postscript', Mime.mime_for('.ai') + assert_equal 'application/postscript', Mime.mime_for('.eps') + assert_equal 'application/postscript', Mime.mime_for('.ps') + assert_equal 'application/vnd.adobe.air-application-installer-package+zip', Mime.mime_for('.air') + assert_equal 'application/vnd.oasis.opendocument.presentation', Mime.mime_for('.odp') + assert_equal 'application/vnd.oasis.opendocument.spreadsheet', Mime.mime_for('.ods') + assert_equal 'application/vnd.oasis.opendocument.text', Mime.mime_for('.odt') + assert_equal 'application/vnd.openofficeorg.extension', Mime.mime_for('.oxt') + assert_equal 'application/vnd.openxmlformats-officedocument.presentationml.presentation', Mime.mime_for('.pptx') assert_equal 'application/x-chrome-extension', Mime.mime_for('.crx') assert_equal 'application/x-debian-package', Mime.mime_for('.deb') assert_equal 'application/x-iwork-keynote-sffkey', Mime.mime_for('.key') @@ -22,37 +36,19 @@ class TestMime < Test::Unit::TestCase assert_equal 'application/x-java-archive', Mime.mime_for('.ear') assert_equal 'application/x-java-archive', Mime.mime_for('.jar') assert_equal 'application/x-java-archive', Mime.mime_for('.war') - assert_equal 'application/javascript', Mime.mime_for('.js') assert_equal 'application/x-latex', Mime.mime_for('.latex') assert_equal 'application/x-ms-xbap', Mime.mime_for('.xbap') - assert_equal 'application/octet-stream', Mime.mime_for('.dll') - assert_equal 'application/octet-stream', Mime.mime_for('.dmg') - assert_equal 'application/octet-stream', Mime.mime_for('.exe') assert_equal 'application/x-perl', Mime.mime_for('.pl') assert_equal 'application/x-perl', Mime.mime_for('.pm') - assert_equal 'application/postscript', Mime.mime_for('.ai') - assert_equal 'application/postscript', Mime.mime_for('.eps') - assert_equal 'application/postscript', Mime.mime_for('.ps') assert_equal 'application/x-python', Mime.mime_for('.py') assert_equal 'application/x-ruby', Mime.mime_for('.rb') assert_equal 'application/x-sh', Mime.mime_for('.sh') assert_equal 'application/x-shockwave-flash', Mime.mime_for('.swf') assert_equal 'application/x-silverlight-app', Mime.mime_for('.xap') assert_equal 'application/x-supercollider', Mime.mime_for('.sc') - assert_equal 'application/vnd.adobe.air-applicationinstaller-package+zip', Mime.mime_for('.air') - assert_equal 'application/vnd.oasis.opendocument.presentation', Mime.mime_for('.odp') - assert_equal 'application/vnd.oasis.opendocument.spreadsheet', Mime.mime_for('.ods') - assert_equal 'application/vnd.oasis.opendocument.text', Mime.mime_for('.odt') - assert_equal 'application/vnd.openofficeorg.extension', Mime.mime_for('.oxt') - assert_equal 'application/vnd.openxmlformats-officedocument.presentationml.presentation', Mime.mime_for('.pptx') assert_equal 'application/xaml+xml', Mime.mime_for('.xaml') assert_equal 'text/cache-manifest', Mime.mime_for('.manifest') assert_equal 'text/html', Mime.mime_for('.html') - assert_equal 'text/x-nemerle', Mime.mime_for('.n') - assert_equal 'text/x-nimrod', Mime.mime_for('.nim') - assert_equal 'text/x-ocaml', Mime.mime_for('.ml') - assert_equal 'text/x-ocaml', Mime.mime_for('.sig') - assert_equal 'text/x-ocaml', Mime.mime_for('.sml') assert_equal 'text/plain', Mime.mime_for('.c') assert_equal 'text/plain', Mime.mime_for('.cc') assert_equal 'text/plain', Mime.mime_for('.cpp') @@ -63,8 +59,13 @@ class TestMime < Test::Unit::TestCase assert_equal 'text/plain', Mime.mime_for('.hpp') assert_equal 'text/plain', Mime.mime_for('.kt') assert_equal 'text/x-logtalk', Mime.mime_for('.lgt') - assert_equal 'text/x-rust', Mime.mime_for('.rs') + assert_equal 'text/x-nemerle', Mime.mime_for('.n') + assert_equal 'text/x-nimrod', Mime.mime_for('.nim') + assert_equal 'text/x-ocaml', Mime.mime_for('.ml') + assert_equal 'text/x-ocaml', Mime.mime_for('.sig') + assert_equal 'text/x-ocaml', Mime.mime_for('.sml') assert_equal 'text/x-rust', Mime.mime_for('.rc') + assert_equal 'text/x-rust', Mime.mime_for('.rs') assert_equal 'video/quicktime', Mime.mime_for('.mov') end end