fontist 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +25 -1
- data/lib/fontist.rb +1 -0
- data/lib/fontist/data/formulas/courier.yml +26 -0
- data/lib/fontist/data/formulas/ms_system.yml +68 -0
- data/lib/fontist/data/formulas/ms_vista.yml +105 -26
- data/lib/fontist/data/formulas/source_font.yml +154 -42
- data/lib/fontist/data/source.yml +2 -0
- data/lib/fontist/downloader.rb +1 -1
- data/lib/fontist/finder.rb +2 -4
- data/lib/fontist/formula_finder.rb +94 -0
- data/lib/fontist/formulas.rb +2 -0
- data/lib/fontist/formulas/base.rb +48 -1
- data/lib/fontist/formulas/courier_font.rb +25 -0
- data/lib/fontist/formulas/helpers/exe_extractor.rb +45 -0
- data/lib/fontist/formulas/helpers/zip_extractor.rb +36 -0
- data/lib/fontist/formulas/ms_system.rb +29 -0
- data/lib/fontist/formulas/ms_vista.rb +18 -50
- data/lib/fontist/formulas/source_font.rb +8 -31
- data/lib/fontist/installer.rb +11 -16
- data/lib/fontist/system_font.rb +11 -0
- data/lib/fontist/version.rb +1 -1
- data/spec/fontist/finder_spec.rb +1 -1
- data/spec/fontist/formula_finder_spec.rb +54 -0
- data/spec/fontist/formulas/courier_font_spec.rb +30 -0
- data/spec/fontist/formulas/ms_system_spec.rb +31 -0
- data/spec/fontist/formulas/ms_vista_spec.rb +3 -3
- data/spec/fontist/installer_spec.rb +4 -4
- data/spec/fontist/source_spec.rb +1 -1
- data/spec/fontist/system_font_spec.rb +11 -0
- metadata +12 -2
data/lib/fontist/data/source.yml
CHANGED
data/lib/fontist/downloader.rb
CHANGED
data/lib/fontist/finder.rb
CHANGED
@@ -21,13 +21,11 @@ module Fontist
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def remote_source
|
24
|
-
Fontist::
|
25
|
-
!value.fonts.grep(/#{name}/i).empty?
|
26
|
-
end
|
24
|
+
Fontist::FormulaFinder.find(name)
|
27
25
|
end
|
28
26
|
|
29
27
|
def downloadable_font
|
30
|
-
unless remote_source.
|
28
|
+
unless remote_source.nil?
|
31
29
|
raise(
|
32
30
|
Fontist::Errors::MissingFontError,
|
33
31
|
"Fonts are missing, please run" \
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Fontist
|
2
|
+
class FormulaFinder
|
3
|
+
def initialize(font_name)
|
4
|
+
@font_name = font_name
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.find(font_name)
|
8
|
+
new(font_name).find
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.find_fonts(name)
|
12
|
+
new(name).find_fonts
|
13
|
+
end
|
14
|
+
|
15
|
+
def find
|
16
|
+
formulas = find_formula
|
17
|
+
build_formulas_array(formulas)
|
18
|
+
end
|
19
|
+
|
20
|
+
def find_fonts
|
21
|
+
matched_fonts = find_formula.map do |key, _value|
|
22
|
+
formulas[key].fonts.select do |font|
|
23
|
+
font.name == font_name
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
matched_fonts.empty? ? nil : matched_fonts.flatten
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
attr_reader :font_name
|
33
|
+
|
34
|
+
def build_formulas_array(formulas)
|
35
|
+
unless formulas.empty?
|
36
|
+
Array.new.tap do |formula_array|
|
37
|
+
formulas.each do |key|
|
38
|
+
formula_array.push(
|
39
|
+
key: key.to_s,
|
40
|
+
installer: formula_installers[key]
|
41
|
+
)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def find_formula
|
48
|
+
find_by_font_name || find_by_font || []
|
49
|
+
end
|
50
|
+
|
51
|
+
def formulas
|
52
|
+
@formulas ||= Fontist::Source.formulas.to_h
|
53
|
+
end
|
54
|
+
|
55
|
+
def formula_installers
|
56
|
+
{
|
57
|
+
msvista: Fontist::Formulas::MsVista,
|
58
|
+
ms_system: Fontist::Formulas::MsSystem,
|
59
|
+
courier: Fontist::Formulas::CourierFont,
|
60
|
+
source_front: Fontist::Formulas::SourceFont,
|
61
|
+
}
|
62
|
+
end
|
63
|
+
|
64
|
+
def find_by_font_name
|
65
|
+
formula_names = formulas.select do |key, value|
|
66
|
+
!value.fonts.map(&:name).grep(/#{font_name}/i).empty?
|
67
|
+
end.keys
|
68
|
+
|
69
|
+
formula_names.empty? ? nil : formula_names
|
70
|
+
end
|
71
|
+
|
72
|
+
# Note
|
73
|
+
#
|
74
|
+
# These interface recursively look into every single font styles,
|
75
|
+
# so ideally try to avoid using it when possible, and that's why
|
76
|
+
# we've added it as last option in formula finder.
|
77
|
+
#
|
78
|
+
def find_by_font
|
79
|
+
formula_names = formulas.select do |key, value|
|
80
|
+
match_in_font_styles?(value.fonts)
|
81
|
+
end.keys
|
82
|
+
|
83
|
+
formula_names.empty? ? nil : formula_names
|
84
|
+
end
|
85
|
+
|
86
|
+
def match_in_font_styles?(fonts)
|
87
|
+
styles = fonts.select do |font|
|
88
|
+
!font.styles.map(&:font).grep(/#{font_name}/i).empty?
|
89
|
+
end
|
90
|
+
|
91
|
+
styles.empty? ? false : true
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
data/lib/fontist/formulas.rb
CHANGED
@@ -1,7 +1,12 @@
|
|
1
|
+
require "fontist/downloader"
|
2
|
+
require "fontist/formulas/helpers/exe_extractor"
|
3
|
+
require "fontist/formulas/helpers/zip_extractor"
|
4
|
+
|
1
5
|
module Fontist
|
2
6
|
module Formulas
|
3
7
|
class Base
|
4
8
|
def initialize(font_name, confirmation:, **options)
|
9
|
+
@matched_fonts = []
|
5
10
|
@font_name = font_name
|
6
11
|
@confirmation = confirmation || "no"
|
7
12
|
@force_download = options.fetch(:force_download, false)
|
@@ -14,12 +19,54 @@ module Fontist
|
|
14
19
|
new(font_name, options.merge(confirmation: confirmation)).fetch
|
15
20
|
end
|
16
21
|
|
22
|
+
def fetch
|
23
|
+
extract_fonts(map_names_to_fonts(font_name))
|
24
|
+
|
25
|
+
matched_fonts_uniq = matched_fonts.flatten.uniq
|
26
|
+
matched_fonts_uniq.empty? ? nil : matched_fonts_uniq
|
27
|
+
end
|
28
|
+
|
17
29
|
private
|
18
30
|
|
19
|
-
attr_reader
|
31
|
+
attr_reader(
|
32
|
+
:font_name,
|
33
|
+
:fonts_path,
|
34
|
+
:confirmation,
|
35
|
+
:matched_fonts,
|
36
|
+
:force_download,
|
37
|
+
)
|
20
38
|
|
21
39
|
def check_user_license_agreement
|
22
40
|
end
|
41
|
+
|
42
|
+
def resources(name, &block)
|
43
|
+
source = formulas[name]
|
44
|
+
block_given? ? yield(source) : source
|
45
|
+
end
|
46
|
+
|
47
|
+
def formulas
|
48
|
+
@formulas ||= Fontist::Source.formulas
|
49
|
+
end
|
50
|
+
|
51
|
+
def match_fonts(fonts_dir, font_name)
|
52
|
+
font = fonts_dir.grep(/#{font_name}/i)
|
53
|
+
@matched_fonts.push(font) if font
|
54
|
+
|
55
|
+
font
|
56
|
+
end
|
57
|
+
|
58
|
+
def map_names_to_fonts(font_name)
|
59
|
+
fonts = FormulaFinder.find_fonts(font_name)
|
60
|
+
fonts = fonts.map { |font| font.styles.map(&:font) }.flatten if fonts
|
61
|
+
|
62
|
+
fonts || []
|
63
|
+
end
|
64
|
+
|
65
|
+
def download_file(source)
|
66
|
+
Fontist::Downloader.download(
|
67
|
+
source.urls.first, sha: source.sha, file_size: source.file_size,
|
68
|
+
)
|
69
|
+
end
|
23
70
|
end
|
24
71
|
end
|
25
72
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Fontist
|
2
|
+
module Formulas
|
3
|
+
class CourierFont < Base
|
4
|
+
include Formulas::Helpers::ExeExtractor
|
5
|
+
|
6
|
+
private
|
7
|
+
|
8
|
+
def extract_fonts(font_names)
|
9
|
+
resources("courier") do |resource|
|
10
|
+
cab_extract(resource) do |fonts_dir|
|
11
|
+
font_names.each do |font_name|
|
12
|
+
match_fonts(fonts_dir, font_name)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def check_user_license_agreement
|
19
|
+
unless resources("courier").agreement === confirmation
|
20
|
+
raise(Fontist::Errors::LicensingError)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Fontist
|
2
|
+
module Formulas
|
3
|
+
module Helpers
|
4
|
+
module ExeExtractor
|
5
|
+
def cab_extract(exe_file, download: true, font_ext: /.tt|.ttc/i)
|
6
|
+
exe_file = download_file(exe_file).path if download
|
7
|
+
cab_file = decompressor.search(exe_file)
|
8
|
+
cabbed_fonts = grep_fonts(cab_file.files, font_ext) || []
|
9
|
+
fonts_paths = extract_cabbed_fonts_to_assets(cabbed_fonts)
|
10
|
+
|
11
|
+
yield(fonts_paths) if block_given?
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def decompressor
|
17
|
+
@decompressor ||= (
|
18
|
+
require "libmspack"
|
19
|
+
LibMsPack::CabDecompressor.new
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
def grep_fonts(file, font_ext)
|
24
|
+
Array.new.tap do |fonts|
|
25
|
+
while file
|
26
|
+
fonts.push(file) if file.filename.match(font_ext)
|
27
|
+
file = file.next
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def extract_cabbed_fonts_to_assets(cabbed_fonts)
|
33
|
+
Array.new.tap do |fonts|
|
34
|
+
cabbed_fonts.each do |font|
|
35
|
+
font_path = fonts_path.join(font.filename).to_s
|
36
|
+
decompressor.extract(font, font_path)
|
37
|
+
|
38
|
+
fonts.push(font_path)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Fontist
|
2
|
+
module Formulas
|
3
|
+
module Helpers
|
4
|
+
module ZipExtractor
|
5
|
+
def zip_extract(resource, download: true, fonts_sub_dir: "/")
|
6
|
+
zip_file = download_file(resource) if download
|
7
|
+
zip_file ||= resource.urls.first
|
8
|
+
|
9
|
+
fonts_paths = unzip_fonts(zip_file, fonts_sub_dir)
|
10
|
+
block_given? ? yield(fonts_paths) : fonts_paths
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def unzip_fonts(file, fonts_sub_dir = "/")
|
16
|
+
Zip.on_exists_proc = true
|
17
|
+
|
18
|
+
Array.new.tap do |fonts|
|
19
|
+
Zip::File.open(file) do |zip_file|
|
20
|
+
zip_file.glob("#{fonts_sub_dir}*.{ttf,ttc}").each do |entry|
|
21
|
+
filename = entry.name.gsub("#{fonts_sub_dir}", "")
|
22
|
+
|
23
|
+
if filename
|
24
|
+
font_path = fonts_path.join(filename)
|
25
|
+
fonts.push(font_path.to_s)
|
26
|
+
|
27
|
+
entry.extract(font_path)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Fontist
|
2
|
+
module Formulas
|
3
|
+
class MsSystem < Base
|
4
|
+
include Formulas::Helpers::ExeExtractor
|
5
|
+
|
6
|
+
private
|
7
|
+
|
8
|
+
def data_node
|
9
|
+
@data_node ||= "ms_system"
|
10
|
+
end
|
11
|
+
|
12
|
+
def check_user_license_agreement
|
13
|
+
unless resources(data_node).agreement === confirmation
|
14
|
+
raise(Fontist::Errors::LicensingError)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def extract_fonts(font_names)
|
19
|
+
resources(data_node) do |resource|
|
20
|
+
cab_extract(resource) do |fonts_dir|
|
21
|
+
font_names.each do |font_name|
|
22
|
+
match_fonts(fonts_dir, font_name)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -1,69 +1,37 @@
|
|
1
|
-
require "fontist/downloader"
|
2
|
-
|
3
1
|
module Fontist
|
4
2
|
module Formulas
|
5
3
|
class MsVista < Base
|
6
|
-
|
7
|
-
fonts = extract_ppviewer_fonts
|
8
|
-
paths = fonts.grep(/#{font_name}/i)
|
9
|
-
paths.empty? ? nil : paths
|
10
|
-
end
|
4
|
+
include Formulas::Helpers::ExeExtractor
|
11
5
|
|
12
6
|
private
|
13
7
|
|
14
|
-
def
|
15
|
-
|
16
|
-
raise(Fontist::Errors::LicensingError)
|
17
|
-
end
|
8
|
+
def data_node
|
9
|
+
@data_node ||= "msvista"
|
18
10
|
end
|
19
11
|
|
20
|
-
def
|
21
|
-
|
22
|
-
|
23
|
-
LibMsPack::CabDecompressor.new
|
24
|
-
)
|
25
|
-
end
|
26
|
-
|
27
|
-
def extract_ppviewer_fonts
|
28
|
-
Array.new.tap do |fonts|
|
29
|
-
cabbed_fonts.each do |font|
|
30
|
-
font_path = fonts_path.join(font.filename).to_s
|
31
|
-
decompressor.extract(font, font_path)
|
32
|
-
|
33
|
-
fonts.push(font_path)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def extract_ppviewer_cab_file
|
39
|
-
if !File.exists?(ppviewer_cab) || force_download
|
40
|
-
exe_file = decompressor.search(download_exe_file.path)
|
41
|
-
decompressor.extract(exe_file.files.next, ppviewer_cab)
|
12
|
+
def check_user_license_agreement
|
13
|
+
unless resources(data_node).agreement === confirmation
|
14
|
+
raise(Fontist::Errors::LicensingError)
|
42
15
|
end
|
43
16
|
end
|
44
17
|
|
45
|
-
def
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
fonts.push(file) if file.filename.match(/.tt|.TT/)
|
54
|
-
file = file.next
|
18
|
+
def extract_fonts(font_names)
|
19
|
+
resources(data_node) do |resource|
|
20
|
+
exe_extract(resource) do |cab_file|
|
21
|
+
cab_extract(cab_file, download: false) do |fonts_dir|
|
22
|
+
font_names.each do |font_name|
|
23
|
+
match_fonts(fonts_dir, font_name)
|
24
|
+
end
|
25
|
+
end
|
55
26
|
end
|
56
27
|
end
|
57
28
|
end
|
58
29
|
|
59
|
-
def source
|
60
|
-
|
61
|
-
|
30
|
+
def exe_extract(source)
|
31
|
+
cab_files = decompressor.search(download_file(source).path)
|
32
|
+
decompressor.extract(cab_files.files.next, ppviewer_cab)
|
62
33
|
|
63
|
-
|
64
|
-
Fontist::Downloader.download(
|
65
|
-
source.urls.first, file_size: source.file_size.to_i, sha: source.sha
|
66
|
-
)
|
34
|
+
yield(ppviewer_cab) if block_given?
|
67
35
|
end
|
68
36
|
|
69
37
|
def ppviewer_cab
|
@@ -3,46 +3,23 @@ require "zip"
|
|
3
3
|
module Fontist
|
4
4
|
module Formulas
|
5
5
|
class SourceFont < Formulas::Base
|
6
|
-
|
7
|
-
paths = extract_fonts.grep(/#{font_name}/i)
|
8
|
-
paths.empty? ? nil : paths
|
9
|
-
end
|
6
|
+
include Formulas::Helpers::ZipExtractor
|
10
7
|
|
11
8
|
private
|
12
9
|
|
13
|
-
def
|
14
|
-
@
|
15
|
-
end
|
16
|
-
|
17
|
-
def extract_fonts
|
18
|
-
zip_file = download_file
|
19
|
-
unzip_fonts(zip_file)
|
10
|
+
def data_node
|
11
|
+
@data_node ||= "source_font"
|
20
12
|
end
|
21
13
|
|
22
|
-
def
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
zip_file.glob("fonts/*.ttf").each do |entry|
|
28
|
-
filename = entry.name.gsub("fonts/", "")
|
29
|
-
|
30
|
-
if filename
|
31
|
-
font_path = fonts_path.join(filename)
|
32
|
-
fonts.push(font_path.to_s)
|
33
|
-
|
34
|
-
entry.extract(font_path)
|
35
|
-
end
|
14
|
+
def extract_fonts(font_names)
|
15
|
+
resources(data_node) do |resource|
|
16
|
+
zip_extract(resource, fonts_sub_dir: "fonts/") do |fonts_paths|
|
17
|
+
font_names.each do |font_name|
|
18
|
+
match_fonts(fonts_paths, font_name)
|
36
19
|
end
|
37
20
|
end
|
38
21
|
end
|
39
22
|
end
|
40
|
-
|
41
|
-
def download_file
|
42
|
-
Fontist::Downloader.download(
|
43
|
-
source.urls.first, file_size: source.file_size.to_i, sha: source.sha
|
44
|
-
)
|
45
|
-
end
|
46
23
|
end
|
47
24
|
end
|
48
25
|
end
|