1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 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 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
|
# frozen_string_literal: true
$LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
require "mime/types/support"
require "fileutils"
require "json"
# Convert from YAML to JSON (and back) or columnar.
class Convert
class << self
# Create a Convert instance that converts from YAML.
def from_yaml(path = nil)
new(path: path, from: :yaml)
end
# Create a Convert instance that converts from JSON.
def from_json(path = nil)
new(path: path, from: :json)
end
# Create a Convert instance that converts from the mime-types 1.x file
# format.
def from_v1(path = nil)
new(path: path, from: :v1)
end
# Converts from YAML to JSON. Defaults to converting to a single file.
def from_yaml_to_json(from: nil, to: nil, multiple_files: false)
from_yaml(to_yaml_path(from))
.to_json(
destination: to_data_path(to),
multiple_files: to_multiple_files(multiple_files)
)
end
# Convert from YAML to YAML. Used to do an in-place update of the files.
def from_yaml_to_yaml(from: nil, to: nil, multiple_files: true) # :nodoc:
from_yaml(to_yaml_path(from))
.to_yaml(
destination: to_yaml_path(to),
multiple_files: to_multiple_files(multiple_files)
)
end
# Converts from JSON to YAML. Defaults to converting to multiple files.
def from_json_to_yaml(from: nil, to: nil, multiple_files: true)
from_json(to_data_path(from))
.to_yaml(
destination: to_yaml_path(to),
multiple_files: to_multiple_files(multiple_files)
)
end
private :new
private
def to_yaml_path(path)
to_path_or_default(path, "types")
end
def to_data_path(path)
to_path_or_default(path, "data")
end
def to_path_or_default(path, default)
if path.nil? || path.empty?
default
else
path
end
end
def to_multiple_files(flag)
case flag.to_s.downcase
when "true", "yes", "multiple"
true
else
false
end
end
end
def initialize(options = {})
raise ArgumentError, ":path is required" if options[:path].nil? || options[:path].empty?
raise ArgumentError, ":from is required" if options[:from].nil? || options[:from].empty?
@loader = MIME::Types::Loader.new(options[:path])
load_from(options[:from])
end
# Convert the data to JSON.
def to_json(options = {})
options[:destination] or require_destination!
write_types(options.merge(format: :json))
end
# Convert the data to YAML.
def to_yaml(options = {})
options[:destination] or require_destination!
write_types(options.merge(format: :yaml))
end
private
def sort(list)
list.sort_by(&:simplified)
end
def load_from(source_type)
method = :"load_#{source_type}"
@loader.send(method)
end
def write_types(options)
if options[:multiple_files]
write_multiple_files(options)
else
write_one_file(options)
end
end
def write_file(file, list, options)
File.open(file, "wb") { |f|
f.puts convert(sort(list), options[:format])
}
end
def write_one_file(options)
d = options[:destination]
d = File.join(d, "mime-types.#{options[:format]}") if File.directory?(d)
write_file(d, @loader.container.map, options)
end
def write_multiple_files(options)
d = options[:destination]
must_be_directory!(d)
media_types = @loader.container.map(&:media_type).map { |type| type.sub(/^x-/, "") }.uniq
media_types.each { |media_type|
n = File.join(d, "#{media_type}.#{options[:format]}")
t = @loader.container.select { |e|
e.media_type == media_type || e.media_type == "x-#{media_type}"
}
write_file(n, t, options)
}
end
def convert(data, format)
data.send(:"to_#{format}")
end
def require_destination!
raise ArgumentError, "Destination path is required."
end
def must_be_directory!(path)
raise ArgumentError, "Cannot write multiple files to a file." if File.exist?(path) && !File.directory?(path)
FileUtils.mkdir_p(path) unless File.exist?(path)
path
end
end
|