Passed
Push — master ( fdfd44...f2af80 )
by Paul
01:42
created

ContentParser.munge_hash_value()   A

Complexity

Conditions 4

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 4

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 4
c 2
b 0
f 0
dl 0
loc 18
rs 9.2
ccs 6
cts 6
cp 1
crap 4
1 1
require "json"
2 1
require "base64"
3 1
require_relative "file_fetcher"
4 1
require_relative "file_system"
5 1
require_relative "align_key"
6 1
require_relative "font_hash"
7 1
require_relative "styles_array"
8
9 1
module Resume
10 1
  module CLI
11 1
    module ContentParser
12 1
      ASSET_PATH = /dropbox/
13 1
      private_constant :ASSET_PATH
14
      # Regex taken from http://stackoverflow.com/q/8571501/567863
15 1
      BASE64_STRING_REGEX = %r{\A
16
        ([A-Za-z0-9+/]{4})*
17
        ([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)
18
      \z}x
19 1
      private_constant :BASE64_STRING_REGEX
20
21 1
      module_function
22
23 1
      def decode_content(string)
24
        # Force encoding to UTF-8 is needed for strings that had UTF-8
25
        # characters in them when they were originally encoded
26 200
        Base64.strict_decode64(string).force_encoding("utf-8")
27
      end
28
29 1
      def parse(resume)
30 11
        JSON.recurse_proc(resume, &decode_and_fetch_assets)
31
      end
32
33
      # Values that need parsing can be found in hash and array values
34
      # in the JSON, so specifically target those data types for
35
      # manipulation, and ignore any direct references given to the
36
      # keys or values of the JSON hash.
37 1
      def decode_and_fetch_assets
38 11
        proc do |object|
39 1241
          case object
40
          when Hash
41 127
            parse_hash(object)
42
          when Array
43 86
            parse_array(object)
44
          else
45 1028
            object
46
          end
47
        end
48
      end
49 1
      private_class_method :decode_and_fetch_assets
50
51 1
      def parse_hash(hash)
52 127
        hash.each do |key, value|
53 565
          if value =~ BASE64_STRING_REGEX
54 139
            value = decode_content(value)
55
          end
56 565
          if value =~ ASSET_PATH
57 26
            hash[key] = FileFetcher.fetch(value)
58 26
            next
59
          end
60 539
          munge_hash_value(hash, key, value)
61
        end
62
      end
63 1
      private_class_method :parse_hash
64
65 1
      def munge_hash_value(hash, key, value)
66 539
        case [key, value]
67
        when AlignKey
68
          # Prawn specifically requires :align values to
69
          # be symbols otherwise it errors out
70 14
          hash[key] = value.to_sym
71
        when StylesArray
72
          # Prawn specifically requires :styles values to
73
          # be symbols otherwise the styles do not take effect
74 51
          hash[key] = value.map!(&:to_sym)
75
        when FontHash
76
          # This is the hash that tells Prawn what the fonts to be used
77
          # are called and where they are located
78 2
          substitute_filenames_for_filepaths(value)
79
        else
80 472
          hash[key] = value
81
        end
82
      end
83 1
      private_class_method :munge_hash_value
84
85 1
      def substitute_filenames_for_filepaths(value)
86 2
        %i(normal bold).each do |property|
87 4
          if value.key?(property)
88 2
            value[property] = FileSystem.tmpfile_path(value[property])
89
          end
90
        end
91
      end
92 1
      private_class_method :substitute_filenames_for_filepaths
93
94 1
      def parse_array(array)
95 86
        array.each_with_index do |value, index|
96 100
          if value =~ BASE64_STRING_REGEX
97 57
            array[index] = decode_content(value)
98
          end
99
        end
100
      end
101 1
      private_class_method :parse_array
102
    end
103
  end
104
end
105