Skip to content

Commit

Permalink
Expand valid data URIs, open-uri support
Browse files Browse the repository at this point in the history
  • Loading branch information
dball committed Jan 12, 2011
1 parent 109ea3a commit 8d51fef
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 23 deletions.
25 changes: 4 additions & 21 deletions lib/data_uri.rb
Original file line number Diff line number Diff line change
@@ -1,24 +1,7 @@
require 'uri'
require 'base64'
require 'stringio'
require 'rubygems'
require 'mime/types'

module URI

class Data < Generic

COMPONENT = [:scheme, :opaque].freeze
OPAQUE_REGEXP = /^([^;]+);base64,(.+)$/.freeze

attr_reader :content_type, :data

def initialize(*args)
super(*args)
if OPAQUE_REGEXP.match(@opaque)
@content_type = $1
@data = Base64.decode64($2)
end
end
end

@@schemes['DATA'] = Data

end
require 'data_uri/uri'
22 changes: 22 additions & 0 deletions lib/data_uri/open_uri.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module URI

class Data

def open
io = StringIO.new(data)
OpenURI::Meta.init(io)
io.meta_add_field('content-type', content_type)
if block_given?
begin
yield io
ensure
io.close
end
else
io
end
end

end

end
33 changes: 33 additions & 0 deletions lib/data_uri/uri.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
module URI

class Data < Generic

COMPONENT = [:scheme, :opaque].freeze

attr_reader :content_type, :data

def initialize(*args)
super(*args)
@data = @opaque
if md = MIME::Type::MEDIA_TYPE_RE.match(@data)
offset = md.offset(0)
if offset[0] == 0
@content_type = md[0]
@data = @data[offset[1] .. -1]
end
end
@content_type ||= 'text/plain'
if base64 = /^;base64/.match(@data)
@data = @data[7 .. -1]
end
unless /^,/.match(@data)
raise 'Invalid data URI'
end
@data = @data[1 .. -1]
@data = base64 ? Base64.decode64(@data) : URI.decode(@data)
end
end

@@schemes['DATA'] = Data

end
36 changes: 36 additions & 0 deletions test/test_data_open_uri.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
require 'data_uri'
require 'open-uri'
require 'data_uri/open_uri'
require 'minitest/autorun'

describe URI::Data do

describe "a valid data URI" do

before do
@base64 = "R0lGODlhAQABAIABAAAAAP///yH5BAEAAAEALAAAAAABAAEAQAICTAEAOw=="
@uri = URI.parse("data:image/gif;base64,#{@base64}")
@data = Base64.decode64(@base64)
end

it "should open" do
@uri.open.read.must_equal @data
end

it "should open with a block" do
@uri.open do |io|
io.read.must_equal @data
end
end

it "should have content_type on opened IO" do
@uri.open.content_type.must_equal 'image/gif'
end

it "should open on Kernel.open" do
open(@uri).read.must_equal @uri.data
end

end

end
24 changes: 22 additions & 2 deletions test/test_data_uri.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

describe URI::Data do

describe "a valid data URI" do
describe "a base64 encoded image/gif data URI" do

before do
@base64 = "R0lGODlhAQABAIABAAAAAP///yH5BAEAAAEALAAAAAABAAEAQAICTAEAOw=="
Expand All @@ -18,11 +18,31 @@
@uri.content_type.must_equal 'image/gif'
end

it "should have decoded data" do
it "should have data" do
require 'base64'
@uri.data.must_equal Base64.decode64(@base64)
end

end

describe "a text/plain data URI" do

before do
@uri = URI.parse("data:,A%20brief%20note")
end

it "should parse as a URI::Data object" do
@uri.class.must_equal URI::Data
end

it "should have a content_type of text/plain" do
@uri.content_type.must_equal 'text/plain'
end

it "should have data" do
@uri.data.must_equal 'A brief note'
end

end

end

0 comments on commit 8d51fef

Please sign in to comment.