Module: DataUri

Defined in:
lib/datauris.rb,
lib/datauris/version.rb

Constant Summary collapse

REGEX_V0 =
%r{
  \Adata:
  (?<mediatype>
    (?<type> .+? / .+? )?
    (?<parameters> (?: ; .+? = .+? )* )
  )?
  (?<base64extension>;base64)?
  ,
  (?<data>.*)\z
}x
REGEX =

make parameters key/value more strict - why? why not?

e.g. MIME_PARAM_RE = /^;([-\w.+]+)=([^;,]+)/.freeze

allow  +(plus) or .(dot) in param key - possible?? why? why not?
%r{
  \A
  data:
  (?<mediatype>
    (?:
        (?<type> [\w-]+? )  
         / 
        (?<subtype> [\w.+-]+? )
    )?
    (?<parameters> (?: ; 
                       [\w-]+? 
                          = 
                          .+? 
                    )* 
    )
  )?
  (?<base64extension>;base64)?
  ,
  (?<data>.*)
  \z
}x
NOT_SAFECHARS_RX =
/([^a-zA-Z0-9\-_.~]+)/
MAJOR =

todo: namespace inside version or something - why? why not??

1
MINOR =
0
PATCH =
1
VERSION =
[MAJOR,MINOR,PATCH].join('.')

Class Method Summary collapse

Class Method Details

._parse(str) ⇒ Object



74
# File 'lib/datauris.rb', line 74

def self._parse( str ) REGEX.match( str ); end


12
13
14
# File 'lib/datauris/version.rb', line 12

def self.banner
  "datauris/#{VERSION} on Ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}] in (#{root})"
end

.build(data, type = nil, base64: nil) ⇒ Object Also known as: encode

base64 - force base64 encoding (instead of “automagic”)



169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/datauris.rb', line 169

def self.build( data, type=nil, base64: nil )
    uri = "data:"
    uri += type      if type   ## note: allow optional / no type

    
    ## puts "  type: #{type.inspect}, base64: #{base64.inspect}"


    ## add more (binary) media types here - why? why not?

    ##   note svg is text AND an image => image/svg+xml

    if base64.nil?                   
        base64 = if type 
                   if type.start_with?( 'image/svg+xml' )
                     false
                   elsif type.start_with?( 'image/') ||
                         type.start_with?( 'application/octet-stream' )
                     true
                   else 
                     false
                   end
                 else # no type (assume text)

                    false
                 end
    end

    if base64    
        uri += ";base64," + Base64.strict_encode64( data )
    else
        ## use encode_uri_component by default - why? why not?

        ##  space becomes %20

        ##  :     becomes %3A

        ##  ,     becomes %2C  and so on

        uri += "," + encode_uri( data )
    end   
end

.encode_uri(str) ⇒ Object



160
161
162
163
164
165
# File 'lib/datauris.rb', line 160

def self.encode_uri( str )
  encoding = str.encoding
  str.b.gsub( NOT_SAFECHARS_RX ) do |m|
    '%' + m.unpack('H2' * m.bytesize).join('%').upcase
  end.force_encoding(encoding)
end

.parse(str) ⇒ Object Also known as: decode



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/datauris.rb', line 76

def self.parse( str )
    m = _parse( str ) 
  
    if m
      ## 1) return mediatype (mimetype PLUS optional parameters)

      ## 2) return data (base64 decoded or not)

  
      mediatype = m[:mediatype]  
      data      = if m[:base64extension]   ## assume base64 encoded

                     Base64.strict_decode64(m[:data])
                  else
                     ## e.g. %20 => space(20)

                     ##  etc.

                     ## todo/double check - use a different URI decoder - why? why not?

                     URI.decode_uri_component(m[:data])
                  end

      ## returns data first!!!

      ##  and mediatype second (to follow the order in build)

      ##   - also mediatype is optional -  arguable more intuitive - yes,no?

      [data, mediatype]
    else
       raise ArgumentError, "invalid datauri - cannot match regex; sorry"
    end
end

.rootObject



16
17
18
# File 'lib/datauris/version.rb', line 16

def self.root
  File.expand_path( File.dirname(File.dirname(File.dirname(__FILE__))) )
end

.valid?(str) ⇒ Boolean Also known as: is_valid?

Returns:

  • (Boolean)


103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/datauris.rb', line 103

def self.valid?( str )
  m = _parse( str )
  if m 
    if m[:base64extension]   ## assume base64

      begin
        Base64.strict_decode64(m[:data])
        true
      rescue ArgumentError
        false
      end
    else
      true
    end
  else
    false
  end
end

.versionObject



8
9
10
# File 'lib/datauris/version.rb', line 8

def self.version
  VERSION
end