fontist 1.3.0 → 1.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/check_google.yml +28 -0
- data/.github/workflows/macosx.yml +3 -0
- data/.github/workflows/ubuntu.yml +1 -1
- data/.github/workflows/windows.yml +1 -1
- data/.gitignore +6 -0
- data/.hound.yml +2 -0
- data/.rubocop.yml +22 -0
- data/README.md +224 -0
- data/bin/check_google +8 -0
- data/bin/convert_formulas +8 -0
- data/bin/fontist +7 -0
- data/bin/generate_otfinfo +8 -0
- data/bin/import_google +8 -0
- data/fontist.gemspec +15 -1
- data/lib/fontist.rb +19 -13
- data/lib/fontist/cli.rb +168 -0
- data/lib/fontist/errors.rb +6 -0
- data/lib/fontist/font.rb +145 -7
- data/lib/fontist/font_formula.rb +42 -7
- data/lib/fontist/fontist_font.rb +70 -0
- data/lib/fontist/formula.rb +31 -9
- data/lib/fontist/formula_template.rb +122 -0
- data/lib/fontist/formulas.rb +41 -0
- data/lib/fontist/import.rb +9 -0
- data/lib/fontist/import/convert_formulas.rb +65 -0
- data/lib/fontist/import/create_formula.rb +59 -0
- data/lib/fontist/import/extractors.rb +5 -0
- data/lib/fontist/import/extractors/cab_extractor.rb +37 -0
- data/lib/fontist/import/extractors/extractor.rb +19 -0
- data/lib/fontist/import/extractors/ole_extractor.rb +41 -0
- data/lib/fontist/import/extractors/seven_zip_extractor.rb +44 -0
- data/lib/fontist/import/extractors/zip_extractor.rb +31 -0
- data/lib/fontist/import/files/collection_file.rb +52 -0
- data/lib/fontist/import/files/file_requirement.rb +17 -0
- data/lib/fontist/import/files/font_detector.rb +48 -0
- data/lib/fontist/import/formula_builder.rb +166 -0
- data/lib/fontist/import/formula_serializer.rb +133 -0
- data/lib/fontist/import/google.rb +16 -0
- data/lib/fontist/import/google/fonts_public.md +10 -0
- data/lib/fontist/import/google/fonts_public.pb.rb +71 -0
- data/lib/fontist/import/google/fonts_public.proto +46 -0
- data/lib/fontist/import/google/new_fonts_fetcher.rb +121 -0
- data/lib/fontist/import/google/skiplist.yml +8 -0
- data/lib/fontist/import/google_check.rb +34 -0
- data/lib/fontist/import/google_import.rb +180 -0
- data/lib/fontist/import/helpers/hash_helper.rb +13 -0
- data/lib/fontist/import/helpers/system_helper.rb +23 -0
- data/lib/fontist/import/otf/font_file.rb +105 -0
- data/lib/fontist/import/otf_parser.rb +25 -0
- data/lib/fontist/import/otf_style.rb +29 -0
- data/lib/fontist/import/otfinfo/otfinfo_requirement.rb +22 -0
- data/lib/fontist/import/otfinfo/template.erb +20 -0
- data/lib/fontist/import/otfinfo_generate.rb +45 -0
- data/lib/fontist/import/recursive_extraction.rb +185 -0
- data/lib/fontist/import/template_helper.rb +19 -0
- data/lib/fontist/import/text_helper.rb +30 -0
- data/lib/fontist/manifest.rb +2 -0
- data/lib/fontist/manifest/install.rb +32 -0
- data/lib/fontist/manifest/locations.rb +60 -0
- data/lib/fontist/system_font.rb +66 -22
- data/lib/fontist/utils.rb +5 -0
- data/lib/fontist/utils/cache.rb +88 -0
- data/lib/fontist/utils/downloader.rb +66 -9
- data/lib/fontist/utils/dsl.rb +8 -0
- data/lib/fontist/utils/dsl/collection_font.rb +36 -0
- data/lib/fontist/utils/dsl/font.rb +38 -0
- data/lib/fontist/utils/exe_extractor.rb +25 -22
- data/lib/fontist/utils/msi_extractor.rb +31 -0
- data/lib/fontist/utils/seven_zip_extractor.rb +41 -0
- data/lib/fontist/utils/system.rb +23 -0
- data/lib/fontist/utils/ui.rb +12 -0
- data/lib/fontist/utils/zip_extractor.rb +22 -8
- data/lib/fontist/version.rb +1 -1
- metadata +173 -49
- data/lib/fontist/formulas/andale_font.rb +0 -80
- data/lib/fontist/formulas/arial_black_font.rb +0 -79
- data/lib/fontist/formulas/cleartype_fonts.rb +0 -227
- data/lib/fontist/formulas/comic_font.rb +0 -78
- data/lib/fontist/formulas/courier_font.rb +0 -81
- data/lib/fontist/formulas/euphemia_font.rb +0 -85
- data/lib/fontist/formulas/georgia_font.rb +0 -80
- data/lib/fontist/formulas/impact_font.rb +0 -78
- data/lib/fontist/formulas/montserrat_font.rb +0 -132
- data/lib/fontist/formulas/ms_truetype_fonts.rb +0 -125
- data/lib/fontist/formulas/open_sans_fonts.rb +0 -263
- data/lib/fontist/formulas/overpass_font.rb +0 -73
- data/lib/fontist/formulas/source_fonts.rb +0 -109
- data/lib/fontist/formulas/stix_fonts.rb +0 -108
- data/lib/fontist/formulas/tahoma_font.rb +0 -147
- data/lib/fontist/formulas/webding_font.rb +0 -78
- data/spec/fontist/font_formula_spec.rb +0 -67
- data/spec/fontist/font_spec.rb +0 -113
- data/spec/fontist/formula_spec.rb +0 -67
- data/spec/fontist/formulas/andale_font_spec.rb +0 -29
- data/spec/fontist/formulas/arial_black_font_spec.rb +0 -29
- data/spec/fontist/formulas/cleartype_fonts_spec.rb +0 -38
- data/spec/fontist/formulas/comic_font_spec.rb +0 -29
- data/spec/fontist/formulas/courier_font_spec.rb +0 -29
- data/spec/fontist/formulas/euphemia_font_spec.rb +0 -29
- data/spec/fontist/formulas/georgia_font_spec.rb +0 -29
- data/spec/fontist/formulas/impact_font_spec.rb +0 -29
- data/spec/fontist/formulas/montserrat_font_spec.rb +0 -29
- data/spec/fontist/formulas/ms_truetype_fonts_spec.rb +0 -29
- data/spec/fontist/formulas/open_sans_fonts_spec.rb +0 -29
- data/spec/fontist/formulas/overpass_font_spec.rb +0 -29
- data/spec/fontist/formulas/source_fonts_spec.rb +0 -31
- data/spec/fontist/formulas/stix_fonts_spec.rb +0 -29
- data/spec/fontist/formulas/tahoma_font_spec.rb +0 -29
- data/spec/fontist/formulas/webding_font_spec.rb +0 -29
- data/spec/fontist/registry_spec.rb +0 -47
- data/spec/fontist/system_font_spec.rb +0 -44
- data/spec/fontist/utils/downloader_spec.rb +0 -35
- data/spec/fontist_spec.rb +0 -5
- data/spec/spec_helper.rb +0 -22
- data/spec/support/fontist_helper.rb +0 -10
data/lib/fontist/utils.rb
CHANGED
@@ -1,8 +1,13 @@
|
|
1
1
|
require "fontist/utils/ui"
|
2
|
+
require "fontist/utils/system"
|
2
3
|
require "fontist/utils/dsl"
|
4
|
+
require "fontist/utils/dsl/font"
|
5
|
+
require "fontist/utils/dsl/collection_font"
|
3
6
|
require "fontist/utils/downloader"
|
4
7
|
require "fontist/utils/zip_extractor"
|
5
8
|
require "fontist/utils/exe_extractor"
|
9
|
+
require "fontist/utils/msi_extractor"
|
10
|
+
require "fontist/utils/seven_zip_extractor"
|
6
11
|
|
7
12
|
module Fontist
|
8
13
|
module Utils
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module Fontist
|
2
|
+
module Utils
|
3
|
+
class Cache
|
4
|
+
def fetch(key, bar: nil)
|
5
|
+
map = load_cache
|
6
|
+
if cache_exist?(map[key])
|
7
|
+
print_bar(bar, map[key]) if bar
|
8
|
+
|
9
|
+
return downloaded_file(map[key])
|
10
|
+
end
|
11
|
+
|
12
|
+
generated_file = yield
|
13
|
+
path = save_cache(generated_file, key)
|
14
|
+
|
15
|
+
downloaded_file(path)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def cache_map_path
|
21
|
+
Fontist.downloads_path.join("map.yml")
|
22
|
+
end
|
23
|
+
|
24
|
+
def load_cache
|
25
|
+
cache_map_path.exist? ? YAML.load_file(cache_map_path) : {}
|
26
|
+
end
|
27
|
+
|
28
|
+
def downloaded_file(path)
|
29
|
+
File.new(downloaded_path(path))
|
30
|
+
end
|
31
|
+
|
32
|
+
def cache_exist?(path)
|
33
|
+
path && File.exist?(downloaded_path(path))
|
34
|
+
end
|
35
|
+
|
36
|
+
def downloaded_path(path)
|
37
|
+
Fontist.downloads_path.join(path)
|
38
|
+
end
|
39
|
+
|
40
|
+
def print_bar(bar, path)
|
41
|
+
File.size(downloaded_path(path)).tap do |size|
|
42
|
+
bar.total = size
|
43
|
+
bar.increment(size)
|
44
|
+
bar.finish("cache")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def save_cache(generated_file, key)
|
49
|
+
path = move_to_downloads(generated_file)
|
50
|
+
|
51
|
+
map = load_cache
|
52
|
+
map[key] = path
|
53
|
+
File.write(cache_map_path, YAML.dump(map))
|
54
|
+
|
55
|
+
path
|
56
|
+
end
|
57
|
+
|
58
|
+
def move_to_downloads(source)
|
59
|
+
create_downloads_directory
|
60
|
+
path = generate_file_path(source)
|
61
|
+
move(source, path)
|
62
|
+
relative_to_downloads(path)
|
63
|
+
end
|
64
|
+
|
65
|
+
def create_downloads_directory
|
66
|
+
unless Fontist.downloads_path.exist?
|
67
|
+
FileUtils.mkdir_p(Fontist.downloads_path)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def generate_file_path(source)
|
72
|
+
dir = Dir.mktmpdir(nil, Fontist.downloads_path)
|
73
|
+
filename = source.original_filename
|
74
|
+
File.join(dir, filename)
|
75
|
+
end
|
76
|
+
|
77
|
+
def move(source_file, target_path)
|
78
|
+
# Windows requires file descriptors to be closed before files are moved
|
79
|
+
source_file.close
|
80
|
+
FileUtils.mv(source_file.path, target_path)
|
81
|
+
end
|
82
|
+
|
83
|
+
def relative_to_downloads(path)
|
84
|
+
Pathname.new(path).relative_path_from(Fontist.downloads_path).to_s
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require_relative "cache"
|
2
|
+
|
1
3
|
module Fontist
|
2
4
|
module Utils
|
3
5
|
class Downloader
|
@@ -5,12 +7,15 @@ module Fontist
|
|
5
7
|
# TODO: If the first mirror fails, try the second one
|
6
8
|
@file = file
|
7
9
|
@sha = [sha].flatten.compact
|
8
|
-
@progress_bar = set_progress_bar(progress_bar)
|
9
10
|
@file_size = (file_size || default_file_size).to_i
|
11
|
+
@progress_bar = set_progress_bar(progress_bar)
|
12
|
+
@cache = Cache.new
|
10
13
|
end
|
11
14
|
|
12
15
|
def download
|
13
|
-
file =
|
16
|
+
file = @cache.fetch(@file, bar: @progress_bar) do
|
17
|
+
download_file
|
18
|
+
end
|
14
19
|
|
15
20
|
if !sha.empty? && !sha.include?(Digest::SHA256.file(file).to_s)
|
16
21
|
raise(Fontist::Errors::TamperedFileError.new(
|
@@ -43,36 +48,88 @@ module Fontist
|
|
43
48
|
end
|
44
49
|
|
45
50
|
def set_progress_bar(progress_bar)
|
46
|
-
ENV.fetch("TEST_ENV", "") === "CI"
|
51
|
+
if ENV.fetch("TEST_ENV", "") === "CI" || progress_bar
|
52
|
+
ProgressBar.new(@file_size)
|
53
|
+
else
|
54
|
+
NullProgressBar.new
|
55
|
+
end
|
47
56
|
end
|
48
57
|
|
49
58
|
def download_file
|
50
|
-
|
51
|
-
|
52
|
-
Down.download(
|
59
|
+
file = Down.download(
|
53
60
|
@file,
|
54
61
|
open_timeout: 10,
|
55
62
|
read_timeout: 10,
|
63
|
+
content_length_proc: ->(content_length) {
|
64
|
+
@progress_bar.total = content_length if content_length
|
65
|
+
},
|
56
66
|
progress_proc: -> (progress) {
|
57
|
-
|
67
|
+
@progress_bar.increment(progress)
|
58
68
|
}
|
59
69
|
)
|
60
70
|
|
71
|
+
@progress_bar.finish
|
72
|
+
|
73
|
+
file
|
61
74
|
rescue Down::NotFound
|
62
75
|
raise(Fontist::Errors::InvalidResourceError.new("Invalid URL: #{@file}"))
|
63
76
|
end
|
64
77
|
end
|
65
78
|
|
79
|
+
class NullProgressBar
|
80
|
+
def total=(_)
|
81
|
+
# do nothing
|
82
|
+
end
|
83
|
+
|
84
|
+
def increment(_)
|
85
|
+
# do nothing
|
86
|
+
end
|
87
|
+
|
88
|
+
def finish(_ = nil)
|
89
|
+
# do nothing
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
66
93
|
class ProgressBar
|
67
94
|
def initialize(total)
|
68
95
|
@counter = 1
|
69
96
|
@total = total
|
70
97
|
end
|
71
98
|
|
99
|
+
def total=(total)
|
100
|
+
@total = total
|
101
|
+
end
|
102
|
+
|
72
103
|
def increment(progress)
|
73
|
-
complete = sprintf("%#.2f%%", ((@counter.to_f / @total.to_f) * 100))
|
74
|
-
print "\r\e[0KDownloads: #{@counter}MB/#{@total}MB (#{complete})"
|
75
104
|
@counter = progress
|
105
|
+
Fontist.ui.print "\r\e[0KDownloads: #{counter_mb}MB/#{total_mb}MB " \
|
106
|
+
"(#{completeness})"
|
107
|
+
end
|
108
|
+
|
109
|
+
def finish(message = nil)
|
110
|
+
if message
|
111
|
+
Fontist.ui.print " (#{message})\n"
|
112
|
+
else
|
113
|
+
Fontist.ui.print "\n"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
private
|
118
|
+
|
119
|
+
def completeness
|
120
|
+
sprintf("%#.2f%%", (@counter.fdiv(@total) * 100)) # rubocop:disable Style/FormatStringToken, Metrics/LineLength
|
121
|
+
end
|
122
|
+
|
123
|
+
def counter_mb
|
124
|
+
@counter / byte_to_megabyte
|
125
|
+
end
|
126
|
+
|
127
|
+
def total_mb
|
128
|
+
@total / byte_to_megabyte
|
129
|
+
end
|
130
|
+
|
131
|
+
def byte_to_megabyte
|
132
|
+
@byte_to_megabyte ||= 1024 * 1024
|
76
133
|
end
|
77
134
|
end
|
78
135
|
end
|
data/lib/fontist/utils/dsl.rb
CHANGED
@@ -47,6 +47,10 @@ module Fontist
|
|
47
47
|
instance.temp_resource.merge!(filename: name)
|
48
48
|
end
|
49
49
|
|
50
|
+
def source_filename(name)
|
51
|
+
instance.temp_resource.merge!(source_filename: name)
|
52
|
+
end
|
53
|
+
|
50
54
|
def provides_font(font, options = {})
|
51
55
|
font_styles = instance.extract_font_styles(options)
|
52
56
|
instance.font_list.push(name: font, styles: font_styles)
|
@@ -65,6 +69,10 @@ module Fontist
|
|
65
69
|
instance.license_required = false
|
66
70
|
end
|
67
71
|
|
72
|
+
def copyright(copyright)
|
73
|
+
instance.copyright = copyright
|
74
|
+
end
|
75
|
+
|
68
76
|
def license_url(url)
|
69
77
|
instance.license_url = url
|
70
78
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Fontist
|
2
|
+
module Utils
|
3
|
+
module Dsl
|
4
|
+
class CollectionFont
|
5
|
+
REQUIRED_ATTRIBUTES = %i[style].freeze
|
6
|
+
|
7
|
+
attr_reader :attributes
|
8
|
+
|
9
|
+
def initialize(attributes)
|
10
|
+
REQUIRED_ATTRIBUTES.each do |required_attribute|
|
11
|
+
unless attributes[required_attribute]
|
12
|
+
raise(Fontist::Errors::MissingAttributeError.new(
|
13
|
+
"Missing attribute: #{required_attribute}"
|
14
|
+
))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
self.attributes = attributes
|
19
|
+
end
|
20
|
+
|
21
|
+
def attributes=(attrs)
|
22
|
+
@attributes = { family_name: attrs[:family_name],
|
23
|
+
type: attrs[:style],
|
24
|
+
collection: attrs[:full_name],
|
25
|
+
full_name: attrs[:full_name],
|
26
|
+
post_script_name: attrs[:post_script_name],
|
27
|
+
version: attrs[:version],
|
28
|
+
description: attrs[:description],
|
29
|
+
copyright: attrs[:copyright],
|
30
|
+
font: attrs[:filename],
|
31
|
+
source_font: attrs[:source_filename] }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Fontist
|
2
|
+
module Utils
|
3
|
+
module Dsl
|
4
|
+
class Font
|
5
|
+
REQUIRED_ATTRIBUTES = %i[family_name
|
6
|
+
style
|
7
|
+
full_name
|
8
|
+
filename].freeze
|
9
|
+
|
10
|
+
attr_reader :attributes
|
11
|
+
|
12
|
+
def initialize(attributes)
|
13
|
+
REQUIRED_ATTRIBUTES.each do |required_attribute|
|
14
|
+
unless attributes[required_attribute]
|
15
|
+
raise(Fontist::Errors::MissingAttributeError.new(
|
16
|
+
"Missing attribute: #{required_attribute}"
|
17
|
+
))
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
self.attributes = attributes
|
22
|
+
end
|
23
|
+
|
24
|
+
def attributes=(attrs)
|
25
|
+
@attributes = { family_name: attrs[:family_name],
|
26
|
+
type: attrs[:style],
|
27
|
+
full_name: attrs[:full_name],
|
28
|
+
post_script_name: attrs[:post_script_name],
|
29
|
+
version: attrs[:version],
|
30
|
+
description: attrs[:description],
|
31
|
+
copyright: attrs[:copyright],
|
32
|
+
font: attrs[:filename],
|
33
|
+
source_font: attrs[:source_filename] }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -1,20 +1,23 @@
|
|
1
1
|
module Fontist
|
2
2
|
module Utils
|
3
3
|
module ExeExtractor
|
4
|
-
def cab_extract(exe_file, download: true,
|
4
|
+
def cab_extract(exe_file, download: true, font_ext: /.ttf|.otf|.ttc/i)
|
5
5
|
download = @downloaded === true ? false : download
|
6
6
|
|
7
7
|
exe_file = download_file(exe_file).path if download
|
8
|
+
|
9
|
+
Fontist.ui.say(%(Installing font "#{key}".))
|
8
10
|
cab_file = decompressor.search(exe_file)
|
9
|
-
cabbed_fonts = grep_fonts(cab_file.files
|
11
|
+
cabbed_fonts = grep_fonts(cab_file.files) || []
|
10
12
|
fonts_paths = extract_cabbed_fonts_to_assets(cabbed_fonts)
|
11
13
|
|
12
|
-
yield(fonts_paths)
|
14
|
+
block_given? ? yield(fonts_paths) : fonts_paths
|
13
15
|
end
|
14
16
|
|
15
|
-
def exe_extract(source)
|
17
|
+
def exe_extract(source, subarchive: nil)
|
16
18
|
cab_file = decompressor.search(download_file(source).path)
|
17
|
-
|
19
|
+
subarchive_path = extract_subarchive(cab_file.files, subarchive)
|
20
|
+
block_given? ? yield(subarchive_path) : subarchive_path
|
18
21
|
end
|
19
22
|
|
20
23
|
private
|
@@ -26,10 +29,10 @@ module Fontist
|
|
26
29
|
)
|
27
30
|
end
|
28
31
|
|
29
|
-
def grep_fonts(file
|
32
|
+
def grep_fonts(file)
|
30
33
|
Array.new.tap do |fonts|
|
31
34
|
while file
|
32
|
-
fonts.push(file) if file.filename
|
35
|
+
fonts.push(file) if font_file?(file.filename)
|
33
36
|
file = file.next
|
34
37
|
end
|
35
38
|
end
|
@@ -38,7 +41,8 @@ module Fontist
|
|
38
41
|
def extract_cabbed_fonts_to_assets(cabbed_fonts)
|
39
42
|
Array.new.tap do |fonts|
|
40
43
|
cabbed_fonts.each do |font|
|
41
|
-
|
44
|
+
target_filename = target_filename(font.filename)
|
45
|
+
font_path = fonts_path.join(target_filename).to_s
|
42
46
|
decompressor.extract(font, font_path)
|
43
47
|
|
44
48
|
fonts.push(font_path)
|
@@ -46,26 +50,25 @@ module Fontist
|
|
46
50
|
end
|
47
51
|
end
|
48
52
|
|
49
|
-
def
|
50
|
-
|
51
|
-
|
52
|
-
filename = file.filename
|
53
|
-
if filename.include?("cab")
|
54
|
-
file_path = temp_dir.join(filename).to_s
|
53
|
+
def extract_subarchive(file, subarchive = nil)
|
54
|
+
while file
|
55
|
+
filename = file.filename
|
55
56
|
|
56
|
-
|
57
|
-
|
58
|
-
|
57
|
+
if subarchive_found?(filename, subarchive)
|
58
|
+
file_path = File.join(Dir.mktmpdir, filename)
|
59
|
+
decompressor.extract(file, file_path)
|
59
60
|
|
60
|
-
|
61
|
+
return file_path
|
61
62
|
end
|
63
|
+
|
64
|
+
file = file.next
|
62
65
|
end
|
63
66
|
end
|
64
67
|
|
65
|
-
def
|
66
|
-
|
67
|
-
|
68
|
-
)
|
68
|
+
def subarchive_found?(filename, subarchive)
|
69
|
+
return subarchive == filename if subarchive
|
70
|
+
|
71
|
+
filename.include?("cab") || filename.include?("msi")
|
69
72
|
end
|
70
73
|
end
|
71
74
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Fontist
|
2
|
+
module Utils
|
3
|
+
module MsiExtractor
|
4
|
+
def msi_extract(resource)
|
5
|
+
file = @downloaded ? resource : download_file(resource)
|
6
|
+
|
7
|
+
cab_content = read_the_largest_file(file)
|
8
|
+
|
9
|
+
cab_file = Tempfile.new(["data", ".cab"], mode: File::BINARY)
|
10
|
+
cab_file.write(cab_content)
|
11
|
+
|
12
|
+
block_given? ? yield(cab_file.path) : cab_file.path
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def read_the_largest_file(file)
|
18
|
+
ole = storage.open(file)
|
19
|
+
the_largest_file = ole.dir.entries(".").max_by { |x| ole.file.size(x) }
|
20
|
+
ole.file.read(the_largest_file)
|
21
|
+
end
|
22
|
+
|
23
|
+
def storage
|
24
|
+
@storage ||= begin
|
25
|
+
require "ole/storage"
|
26
|
+
Ole::Storage
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Fontist
|
2
|
+
module Utils
|
3
|
+
module SevenZipExtractor
|
4
|
+
def seven_zip_extract(resource, extension: /\.cab$/)
|
5
|
+
file = download_file(resource)
|
6
|
+
|
7
|
+
extract_seven_zip_file(file, extension)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def extract_seven_zip_file(file, extension)
|
13
|
+
File.open(file, "rb") do |zip_file|
|
14
|
+
reader.open(zip_file) do |szr|
|
15
|
+
path = extract_by_extension(szr, extension)
|
16
|
+
|
17
|
+
return block_given? ? yield(path) : path
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def reader
|
23
|
+
@reader ||= begin
|
24
|
+
require "seven_zip_ruby"
|
25
|
+
SevenZipRuby::Reader
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def extract_by_extension(szr, extension)
|
30
|
+
cab_entry = szr.entries.detect do |entry|
|
31
|
+
entry.file? && entry.path.match(extension)
|
32
|
+
end
|
33
|
+
|
34
|
+
tmp_dir = Dir.mktmpdir
|
35
|
+
szr.extract(cab_entry, tmp_dir)
|
36
|
+
filename = Pathname.new(cab_entry.path).basename
|
37
|
+
File.join(tmp_dir, filename)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|