fontist 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -18,4 +18,6 @@ system:
18
18
  remote:
19
19
  formulas:
20
20
  - ./formulas/ms_vista.yml
21
+ - ./formulas/ms_system.yml
21
22
  - ./formulas/source_font.yml
23
+ - ./formulas/courier.yml
@@ -7,7 +7,7 @@ module Fontist
7
7
  @sha = sha
8
8
  @file = file
9
9
  @progress = progress
10
- @file_size = file_size || default_file_size
10
+ @file_size = (file_size || default_file_size).to_i
11
11
  end
12
12
 
13
13
  def download
@@ -21,13 +21,11 @@ module Fontist
21
21
  end
22
22
 
23
23
  def remote_source
24
- Fontist::Source.formulas.to_h.select do |key, value|
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.empty?
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
@@ -1,6 +1,8 @@
1
1
  require "fontist/formulas/base"
2
2
  require "fontist/formulas/ms_vista"
3
+ require "fontist/formulas/ms_system"
3
4
  require "fontist/formulas/source_font"
5
+ require "fontist/formulas/courier_font"
4
6
 
5
7
  module Fontist
6
8
  module Formulas
@@ -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 :font_name, :confirmation, :fonts_path, :force_download
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
- def fetch
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 check_user_license_agreement
15
- unless source.agreement === confirmation
16
- raise(Fontist::Errors::LicensingError)
17
- end
8
+ def data_node
9
+ @data_node ||= "msvista"
18
10
  end
19
11
 
20
- def decompressor
21
- @decompressor ||= (
22
- require "libmspack"
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 cabbed_fonts
46
- extract_ppviewer_cab_file
47
- grep_cabbed_fonts(decompressor.search(ppviewer_cab).files) || []
48
- end
49
-
50
- def grep_cabbed_fonts(file)
51
- Array.new.tap do |fonts|
52
- while file
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
- @source ||= Fontist::Source.formulas.msvista
61
- end
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
- def download_exe_file
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
- def fetch
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 source
14
- @source ||= Fontist::Source.formulas.source_font
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 unzip_fonts(file)
23
- Zip.on_exists_proc = true
24
-
25
- Array.new.tap do |fonts|
26
- Zip::File.open(file) do |zip_file|
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