diff --git a/lib/marcel/mime_type/definitions.rb b/lib/marcel/mime_type/definitions.rb index 13b577b..380a634 100644 --- a/lib/marcel/mime_type/definitions.rb +++ b/lib/marcel/mime_type/definitions.rb @@ -6,7 +6,7 @@ Marcel::MimeType.extend "text/html", extensions: %w( html htm ), magic: [ - [64, %r{\A\s*<(!DOCTYPE html|html)}mi], + [0, %r{\A(?:\xEF\xBB\xBF)?\s*(?:<\?xml\s+[^>]*\?>\s*)?(?:\s*)*<(?:!DOCTYPE\s+html|html)(?=[\s>])}min], [-64, %r{\s*\z}mi], ] diff --git a/test/magic_test.rb b/test/magic_test.rb index c7305ec..755ce15 100644 --- a/test/magic_test.rb +++ b/test/magic_test.rb @@ -12,6 +12,29 @@ class Marcel::MimeType::MagicTest < Marcel::TestCase end end + test "detects HTML in partial reads with leading metadata" do + prefixes = [ + "\n", + "\xEF\xBB\xBF".b, + "\n" + ] + + prefixes.each do |prefix| + html = prefix + "\n" + ("

x

\n" * 600) + "" + chunk = html.byteslice(0, 4096) + + assert_equal 4096, chunk.bytesize + refute_includes chunk, "" + assert_equal "text/html", Marcel::MimeType.for( + StringIO.new(chunk), name: "page.html", declared_type: "text/html" + ) + end + end + + test "does not detect an HTML-prefixed custom element as HTML" do + assert_equal "application/octet-stream", Marcel::MimeType.for(StringIO.new("")) + end + test "add and remove type" do Marcel::Magic.add('application/x-my-thing', extensions: 'mtg', parents: 'application/json') Marcel::Magic.remove('application/x-my-thing')