fontist 1.11.6 → 1.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ebc9110896000190889a313f291012ebc3b84a7296230398ee61c9822c44ea87
4
- data.tar.gz: 9de28427a3a46124e8ded2880de764ad9bb632bc9c919babe15123fc38eebdb3
3
+ metadata.gz: f376e0b45e530b28be9d60c132b3840d4485103995fc435c0512b07bf6e20435
4
+ data.tar.gz: b8c8aa1f3de0b627bcaffe09b45398dd60a0ba2a3a2163599263461acb179292
5
5
  SHA512:
6
- metadata.gz: 005c1c9a434bbfa11da8602be4180e20056798afccf4c302204e6d986c6a288d7ee6cbfb387c597db79fe4ae86e50aa22729d4553813b7f025d27a1033c83f19
7
- data.tar.gz: 8584ca32768a87ce2ddfd95275e6f22a9b61074df2db8b407f587931cc2729b444dd257f6435fd564bd0588a2bcf5d6e2634f611cf73a87d76ec517a86de4edf
6
+ metadata.gz: 157c06d56119a5e94a7a15b33b7b1e65695eb94af595f618bbbcf382f8d201d8db7f1a51ed2e3b20cf56d0339a7bd33dc2be82900de1851e29ee31225d2f8054
7
+ data.tar.gz: 3fabd78041974540dc3504c293e335cfd39d241c5cd80da8fd0eef2b6b0a0e6a49701baf4c13e4c151ff397c8aaa6d9d542b37a45b52610ca404bb0abcef004a
@@ -33,7 +33,15 @@ jobs:
33
33
  env:
34
34
  TEST_ENV: CI
35
35
 
36
- - if: matrix.os != 'macos-latest'
36
+ - if: matrix.os == 'windows-latest' && matrix.ruby == '2.4'
37
+ run: curl -O https://curl.se/ca/cacert.pem
38
+
39
+ - if: matrix.os == 'windows-latest' && matrix.ruby == '2.4'
40
+ run: bundle exec rspec --tag ~dev
41
+ env:
42
+ SSL_CERT_FILE: cacert.pem
43
+
44
+ - if: matrix.os != 'macos-latest' || matrix.os == 'windows-latest' && matrix.ruby == '2.4'
37
45
  run: bundle exec rspec --tag ~dev
38
46
  env:
39
47
  TEST_ENV: CI
data/.rubocop.yml CHANGED
@@ -2,21 +2,4 @@ inherit_from:
2
2
  - 'https://raw.githubusercontent.com/fontist/oss-guides/master/ci/rubocop.yml'
3
3
 
4
4
  AllCops:
5
- Exclude:
6
- - 'lib/fontist/import/google/fonts_public.pb.rb'
7
- - 'lib/fontist/formula_template.rb'
8
-
9
- Rails:
10
- Enabled: false
11
-
12
- Layout/LineLength:
13
- Exclude:
14
- - 'lib/fontist/formulas/**/*.rb'
15
-
16
- Layout/FirstHashElementIndentation:
17
- Exclude:
18
- - 'lib/fontist/formulas/**/*.rb'
19
-
20
- Layout/HeredocIndentation:
21
- Exclude:
22
- - 'lib/fontist/formulas/**/*.rb'
5
+ SuggestExtensions: false
data/README.adoc CHANGED
@@ -117,6 +117,25 @@ NOTE: Specifying the formula's name or the font's filename is not supported.
117
117
 
118
118
  NOTE: The `install` command is similar to the `Font.install` library call.
119
119
 
120
+ If there are several formulas with a requested font, then `fontist` searches
121
+ for the newest version of the font among formulas with size below a limit
122
+ (300 MB). This behavior can be changed with options.
123
+
124
+ NOTE: If styles of a font are spread among several formulas, then all
125
+ available formulas would be installed.
126
+
127
+ Supported options:
128
+
129
+ -f, [--force]:: Install even if it's already installed in system
130
+ -a, [--accept-all-licenses]:: Accept all license agreements
131
+ -h, [--hide-licenses]:: Hide license texts
132
+ -p, [--no-progress]:: Hide download progress
133
+ -V, [--version=VERSION]:: Install particular version of a font
134
+ -s, [--smallest]:: Install the smallest formula
135
+ -n, [--newest]:: Install the newest version of a font
136
+ -S, [--size-limit=N]:: Specify size limit for a formula to be installed
137
+ (default is 300 MB)
138
+
120
139
  === Uninstall fonts
121
140
 
122
141
  Uninstalls any font supported by Fontist.
@@ -618,7 +637,7 @@ repository https://github.com/fontist/formulas[formulas]:
618
637
 
619
638
  [source,sh]
620
639
  ----
621
- cd ~/.fontist/versions/v2/formulas
640
+ cd ~/.fontist/versions/{last_version}/formulas
622
641
  git add Formulas/google
623
642
  git commit -m "Google Fonts update"
624
643
  git push
@@ -640,12 +659,44 @@ They can be updated with:
640
659
  [source,sh]
641
660
  ----
642
661
  fontist import-sil
643
- cd ~/.fontist/formulas
644
- git add Formulas/sil index.yml filename_index.yml
662
+ cd ~/.fontist/versions/{last_version}/formulas
663
+ git add Formulas/sil
645
664
  git commit -m "SIL fonts update"
646
665
  git push
647
666
  ----
648
667
 
668
+ === Dynamically importing formulas from macOS
669
+
670
+ macOS provides https://support.apple.com/en-om/HT211240#download[fonts] which
671
+ can be manually downloaded with the Font Book app. When such font is requested,
672
+ fontist prints information on how to install it.
673
+
674
+ In order to know which fonts are available in a current version of macOS,
675
+ for each version there is a formula containing all supported fonts.
676
+
677
+ A new formula can be generated with:
678
+
679
+ [source,sh]
680
+ ----
681
+ fontist import macos --name "Big Sur" --fonts-link "https://support.apple.com/en-om/HT211240#download"
682
+ cd ~/.fontist/versions/{last_version}/formulas
683
+ git add Formulas/macos
684
+ git commit -m "Add Big Sur macOS formula"
685
+ git push
686
+ ----
687
+
688
+ Here `--fonts-link` is a link to a page containing a list of available fonts
689
+ in the Font Book app.
690
+
691
+ If the import is run on a different version of macOS, then a proper version
692
+ should be set in the `platforms` attribute of the generated formula:
693
+
694
+ [source,yaml]
695
+ ----
696
+ platforms:
697
+ - macos-20
698
+ ----
699
+
649
700
 
650
701
  == Development
651
702
 
data/fontist.gemspec CHANGED
@@ -29,15 +29,17 @@ Gem::Specification.new do |spec|
29
29
 
30
30
  spec.add_runtime_dependency "down", "~> 5.0"
31
31
  spec.add_runtime_dependency "extract_ttc", "~> 0.1"
32
+ spec.add_runtime_dependency "nokogiri", "~> 1.0"
33
+ spec.add_runtime_dependency "sys-uname", "~> 1.2"
32
34
  spec.add_runtime_dependency "thor", "~> 1.0.1"
33
35
  spec.add_runtime_dependency "git", "~> 1.0"
34
36
  spec.add_runtime_dependency "ttfunk", "~> 1.6"
37
+ spec.add_runtime_dependency "plist", "~> 3.0"
35
38
  spec.add_runtime_dependency "excavate", "~> 0.1"
36
39
 
37
40
  spec.add_development_dependency "pry"
38
41
  spec.add_development_dependency "bundler", "~> 2.0"
39
42
  spec.add_development_dependency "gem-release"
40
- spec.add_development_dependency "nokogiri", "~> 1.0"
41
43
  spec.add_development_dependency "rake", "~> 13"
42
44
  spec.add_development_dependency "rspec", "~> 3.0"
43
45
  spec.add_development_dependency "rspec-benchmark", "~> 0.6"
data/lib/fontist/cli.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require "thor"
2
2
  require "fontist/repo_cli"
3
+ require "fontist/import_cli"
3
4
  require "fontist/google_cli"
4
5
 
5
6
  module Fontist
@@ -15,14 +16,25 @@ module Fontist
15
16
  STATUS_REPO_NOT_FOUND = 8
16
17
  STATUS_MAIN_REPO_NOT_FOUND = 9
17
18
  STATUS_REPO_COULD_NOT_BE_UPDATED = 10
19
+ STATUS_MANUAL_FONT_ERROR = 11
20
+ STATUS_SIZE_LIMIT_ERROR = 12
18
21
 
19
22
  ERROR_TO_STATUS = {
20
23
  Fontist::Errors::UnsupportedFontError => [STATUS_NON_SUPPORTED_FONT_ERROR],
21
24
  Fontist::Errors::MissingFontError => [STATUS_MISSING_FONT_ERROR],
25
+ Fontist::Errors::SizeLimitError => [
26
+ STATUS_SIZE_LIMIT_ERROR,
27
+ :append,
28
+ "Please specify higher `--size-limit`, or use the `--newest` or " \
29
+ "`--smallest` options.",
30
+ ],
31
+ Fontist::Errors::ManualFontError => [STATUS_MANUAL_FONT_ERROR],
22
32
  Fontist::Errors::LicensingError => [STATUS_LICENSING_ERROR],
23
33
  Fontist::Errors::ManifestCouldNotBeFoundError => [STATUS_MANIFEST_COULD_NOT_BE_FOUND_ERROR,
34
+ :overwrite,
24
35
  "Manifest could not be found."],
25
36
  Fontist::Errors::ManifestCouldNotBeReadError => [STATUS_MANIFEST_COULD_NOT_BE_READ_ERROR,
37
+ :overwrite,
26
38
  "Manifest could not be read."],
27
39
  Fontist::Errors::FontIndexCorrupted => [STATUS_FONT_INDEX_CORRUPTED],
28
40
  Fontist::Errors::RepoNotFoundError => [STATUS_REPO_NOT_FOUND],
@@ -40,18 +52,27 @@ module Fontist
40
52
  desc "install FONT", "Install font"
41
53
  option :force, type: :boolean, aliases: :f,
42
54
  desc: "Install even if it's already installed in system"
43
- option :accept_all_licenses, type: :boolean, aliases: "--confirm-license", desc: "Accept all license agreements"
44
- option :hide_licenses, type: :boolean, desc: "Hide license texts"
45
- option :no_progress, type: :boolean, desc: "Hide download progress"
55
+ option :accept_all_licenses, type: :boolean,
56
+ aliases: ["--confirm-license", :a],
57
+ desc: "Accept all license agreements"
58
+ option :hide_licenses, type: :boolean, aliases: :h,
59
+ desc: "Hide license texts"
60
+ option :no_progress, type: :boolean, aliases: :p,
61
+ desc: "Hide download progress"
62
+ option :version, type: :string, aliases: :V,
63
+ desc: "Specify particular version of a font"
64
+ option :smallest, type: :boolean, aliases: :s,
65
+ desc: "Install the smallest formula if several"
66
+ option :newest, type: :boolean, aliases: :n,
67
+ desc: "Install the newest version of a font if several"
68
+ option :size_limit,
69
+ type: :numeric, aliases: :S,
70
+ desc: "Specify size limit for formula " \
71
+ "(default is #{Fontist.formula_size_limit_in_megabytes} MB)"
46
72
  def install(font)
47
73
  handle_class_options(options)
48
- Fontist::Font.install(
49
- font,
50
- force: options[:force],
51
- confirmation: options[:accept_all_licenses] ? "yes" : "no",
52
- hide_licenses: options[:hide_licenses],
53
- no_progress: options[:no_progress]
54
- )
74
+ confirmation = options[:accept_all_licenses] ? "yes" : "no"
75
+ Fontist::Font.install(font, options.merge(confirmation: confirmation))
55
76
  success
56
77
  rescue Fontist::Errors::GeneralError => e
57
78
  handle_error(e)
@@ -167,6 +188,9 @@ module Fontist
167
188
  desc "repo SUBCOMMAND ...ARGS", "Manage custom repositories"
168
189
  subcommand "repo", Fontist::RepoCLI
169
190
 
191
+ desc "import SUBCOMMAND ...ARGS", "Manage imports"
192
+ subcommand "import", Fontist::ImportCLI
193
+
170
194
  desc "google SUBCOMMAND ...ARGS", "Manage Google formulas"
171
195
  subcommand "google", Fontist::GoogleCLI
172
196
 
@@ -181,10 +205,18 @@ module Fontist
181
205
  end
182
206
 
183
207
  def handle_error(exception)
184
- status, message = ERROR_TO_STATUS[exception.class]
208
+ status, mode, message = ERROR_TO_STATUS[exception.class]
185
209
  raise exception unless status
186
210
 
187
- error(message || exception.message, status)
211
+ text = if message && mode == :overwrite
212
+ message
213
+ elsif message
214
+ "#{exception.message} #{message}"
215
+ else
216
+ exception.message
217
+ end
218
+
219
+ error(text, status)
188
220
  end
189
221
 
190
222
  def error(message, status)
@@ -205,10 +237,15 @@ module Fontist
205
237
  Fontist.ui.say(" #{font.name}")
206
238
 
207
239
  styles.each do |style, installed|
240
+ opts = []
241
+ opts << "manual" if formula.manual?
242
+ opts << (installed ? "installed" : "uninstalled")
243
+ msg = " #{style.type} (#{opts.join(', ')})"
244
+
208
245
  if installed
209
- Fontist.ui.success(" #{style.type} (installed)")
246
+ Fontist.ui.success(msg)
210
247
  else
211
- Fontist.ui.error(" #{style.type} (uninstalled)")
248
+ Fontist.ui.error(msg)
212
249
  end
213
250
  end
214
251
  end
@@ -28,6 +28,8 @@ module Fontist
28
28
 
29
29
  class RepoCouldNotBeUpdatedError < GeneralError; end
30
30
 
31
+ class SizeLimitError < GeneralError; end
32
+
31
33
  class TamperedFileError < GeneralError; end
32
34
 
33
35
  class TimeoutError < GeneralError; end
@@ -72,6 +74,14 @@ module Fontist
72
74
  end
73
75
  end
74
76
 
77
+ class ManualFontError < FontError
78
+ def initialize(font, formula)
79
+ msg = "'#{font}' font is missing.\n\n#{formula.instructions}"
80
+
81
+ super(msg, font)
82
+ end
83
+ end
84
+
75
85
  class UnsupportedFontError < FontError
76
86
  def initialize(font)
77
87
  msg = <<~MSG.chomp
data/lib/fontist/font.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require "fontist/font_installer"
2
2
  require "fontist/font_path"
3
+ require "fontist/formula_picker"
3
4
 
4
5
  module Fontist
5
6
  class Font
@@ -9,6 +10,10 @@ module Fontist
9
10
  @hide_licenses = options[:hide_licenses]
10
11
  @no_progress = options[:no_progress] || false
11
12
  @force = options[:force] || false
13
+ @version = options[:version]
14
+ @smallest = options[:smallest]
15
+ @newest = options[:newest]
16
+ @size_limit = options[:size_limit]
12
17
 
13
18
  check_or_create_fontist_path!
14
19
  end
@@ -38,21 +43,25 @@ module Fontist
38
43
  end
39
44
 
40
45
  def find
41
- find_system_font || downloadable_font || raise_non_supported_font
46
+ find_system_font || downloadable_font || manual_font ||
47
+ raise_non_supported_font
42
48
  end
43
49
 
44
50
  def install
45
- (find_system_font unless @force) || download_font || raise_non_supported_font
51
+ (find_system_font unless @force) || download_font || manual_font ||
52
+ raise_non_supported_font
46
53
  end
47
54
 
48
55
  def uninstall
49
- uninstall_font || downloadable_font || raise_non_supported_font
56
+ uninstall_font || downloadable_font || manual_font ||
57
+ raise_non_supported_font
50
58
  end
51
59
 
52
60
  def status
53
61
  return installed_paths unless @name
54
62
 
55
- find_system_font || downloadable_font || raise_non_supported_font
63
+ find_system_font || downloadable_font || manual_font ||
64
+ raise_non_supported_font
56
65
  end
57
66
 
58
67
  def list
@@ -62,7 +71,7 @@ module Fontist
62
71
  end
63
72
 
64
73
  def all
65
- Fontist::Formula.all.map(&:fonts).flatten
74
+ all_formulas.map(&:fonts).flatten
66
75
  end
67
76
 
68
77
  private
@@ -98,24 +107,47 @@ module Fontist
98
107
  FontInstaller.new(formula, no_progress: @no_progress)
99
108
  end
100
109
 
101
- def formula
102
- @formula ||= Fontist::Formula.find(name)
110
+ def sufficient_formulas
111
+ @sufficient_formulas ||=
112
+ FormulaPicker.new(@name,
113
+ size_limit: @size_limit,
114
+ version: @version,
115
+ smallest: @smallest,
116
+ newest: @newest)
117
+ .call(downloadable_formulas)
118
+ end
119
+
120
+ def downloadable_formulas
121
+ @downloadable_formulas ||= formulas.select(&:downloadable?)
122
+ end
123
+
124
+ def manual_formulas
125
+ @manual_formulas ||= formulas.reject(&:downloadable?)
103
126
  end
104
127
 
105
128
  def formulas
106
129
  @formulas ||= Fontist::Formula.find_many(name)
130
+ .select { |f| supported_formula?(f) }
107
131
  end
108
132
 
109
- def downloadable_font
110
- if formula
111
- raise Fontist::Errors::MissingFontError.new(name)
133
+ def supported_formula?(formula)
134
+ return true if formula.platforms.nil?
135
+
136
+ formula.platforms.any? do |platform|
137
+ Utils::System.match?(platform)
112
138
  end
113
139
  end
114
140
 
141
+ def downloadable_font
142
+ return if downloadable_formulas.empty?
143
+
144
+ raise Fontist::Errors::MissingFontError.new(name)
145
+ end
146
+
115
147
  def download_font
116
- return if formulas.empty?
148
+ return if sufficient_formulas.empty?
117
149
 
118
- formulas.flat_map do |formula|
150
+ sufficient_formulas.flat_map do |formula|
119
151
  confirmation = check_and_confirm_required_license(formula)
120
152
  paths = font_installer(formula).install(confirmation: confirmation)
121
153
 
@@ -165,6 +197,12 @@ module Fontist
165
197
  MSG
166
198
  end
167
199
 
200
+ def manual_font
201
+ return if manual_formulas.empty?
202
+
203
+ raise Fontist::Errors::ManualFontError.new(name, manual_formulas.first)
204
+ end
205
+
168
206
  def uninstall_font
169
207
  paths = find_fontist_paths
170
208
  return unless paths
@@ -190,7 +228,7 @@ module Fontist
190
228
  end
191
229
 
192
230
  def all_formulas
193
- Fontist::Formula.all
231
+ Fontist::Formula.all.select { |f| supported_formula?(f) }
194
232
  end
195
233
 
196
234
  def path(style)
@@ -215,7 +253,7 @@ module Fontist
215
253
 
216
254
  def list_styles(formulas)
217
255
  map_to_hash(formulas) do |formula|
218
- map_to_hash(formula.fonts) do |font|
256
+ map_to_hash(requested_fonts(formula.fonts)) do |font|
219
257
  map_to_hash(font.styles) do |style|
220
258
  installed(style)
221
259
  end
@@ -227,6 +265,14 @@ module Fontist
227
265
  elements.map { |e| [e, yield(e)] }.to_h
228
266
  end
229
267
 
268
+ def requested_fonts(fonts)
269
+ return fonts unless @name
270
+
271
+ fonts.select do |font|
272
+ font.name.casecmp?(name)
273
+ end
274
+ end
275
+
230
276
  def installed(style)
231
277
  path(style) ? true : false
232
278
  end
@@ -59,6 +59,14 @@ module Fontist
59
59
  Indexes::IndexFormula.new(path)
60
60
  end
61
61
 
62
+ def manual?
63
+ !downloadable?
64
+ end
65
+
66
+ def downloadable?
67
+ @data.key?("resources")
68
+ end
69
+
62
70
  def path
63
71
  @path
64
72
  end
@@ -91,16 +99,36 @@ module Fontist
91
99
  @data["requires_license_agreement"] ? true : false
92
100
  end
93
101
 
102
+ def platforms
103
+ @data["platforms"]
104
+ end
105
+
94
106
  def extract
95
107
  Helpers.parse_to_object(@data["extract"])
96
108
  end
97
109
 
110
+ def file_size
111
+ return unless @data["resources"]
112
+
113
+ @data["resources"].values.first["file_size"]&.to_i
114
+ end
115
+
98
116
  def resources
99
- Helpers.parse_to_object(@data["resources"].values)
117
+ Helpers.parse_to_object(@data["resources"]&.values)
118
+ end
119
+
120
+ def instructions
121
+ @data["instructions"]
122
+ end
123
+
124
+ def fonts_by_name(name)
125
+ fonts.select do |font|
126
+ font.name.casecmp?(name)
127
+ end
100
128
  end
101
129
 
102
130
  def fonts
103
- @fonts ||= Helpers.parse_to_object(hash_collection_fonts + hash_fonts)
131
+ @fonts ||= Helpers.parse_to_object(fonts_by_family)
104
132
  end
105
133
 
106
134
  def digest
@@ -114,6 +142,41 @@ module Fontist
114
142
  @path.sub(Regexp.new("^" + escaped), "").sub(/\.yml$/, "")
115
143
  end
116
144
 
145
+ def fonts_by_family
146
+ return hash_all_fonts unless Fontist.preferred_family?
147
+
148
+ preferred_family_fonts
149
+ end
150
+
151
+ def preferred_family_fonts
152
+ groups = preferred_family_styles.group_by do |style|
153
+ style["family_name"]
154
+ end
155
+
156
+ groups.map do |font_name, font_styles|
157
+ { "name" => font_name, "styles" => font_styles }
158
+ end
159
+ end
160
+
161
+ def preferred_family_styles
162
+ hash_all_fonts.flat_map do |font|
163
+ font["styles"].map do |style|
164
+ style.merge(preferred_style(style))
165
+ end
166
+ end
167
+ end
168
+
169
+ def preferred_style(style)
170
+ { "family_name" => style["preferred_family_name"] || style["family_name"],
171
+ "type" => style["preferred_type"] || style["type"],
172
+ "default_family_name" => style["family_name"],
173
+ "default_type" => style["type"] }
174
+ end
175
+
176
+ def hash_all_fonts
177
+ hash_collection_fonts + hash_fonts
178
+ end
179
+
117
180
  def hash_collection_fonts
118
181
  return [] unless @data["font_collections"]
119
182
 
@@ -122,8 +185,7 @@ module Fontist
122
185
  "source_font" => coll["source_filename"] }
123
186
 
124
187
  coll["fonts"].map do |font|
125
- { "name" => font["name"],
126
- "styles" => font["styles"].map { |s| filenames.merge(s) } }
188
+ font.merge("styles" => font["styles"].map { |s| filenames.merge(s) })
127
189
  end
128
190
  end
129
191
  end
@@ -0,0 +1,126 @@
1
+ require "fontist/style_version"
2
+
3
+ module Fontist
4
+ class FormulaPicker
5
+ def initialize(font_name, size_limit:, version:, smallest:, newest:)
6
+ @font_name = font_name
7
+ @size_limit = size_limit || Fontist.formula_size_limit_in_megabytes
8
+ @version = version
9
+ @smallest = smallest
10
+ @newest = newest
11
+ end
12
+
13
+ def call(formulas)
14
+ return [] if formulas.size.zero?
15
+ return formulas if contain_different_styles?(formulas)
16
+ return by_version(formulas) if version_is_passed?
17
+ return newest(formulas) if newest_is_passed?
18
+ return smallest(formulas) if smallest_is_passed?
19
+
20
+ default_way(formulas)
21
+ end
22
+
23
+ private
24
+
25
+ def version_is_passed?
26
+ !@version.nil?
27
+ end
28
+
29
+ def by_version(formulas)
30
+ formulas.each do |formula|
31
+ fonts = formula.fonts_by_name(@font_name)
32
+ fonts.each do |font|
33
+ font.styles.each do |style|
34
+ version = StyleVersion.new(style.version)
35
+ return [formula] if version == passed_version
36
+ end
37
+ end
38
+ end
39
+
40
+ []
41
+ end
42
+
43
+ def passed_version
44
+ @passed_version ||= StyleVersion.new(@version)
45
+ end
46
+
47
+ def newest_is_passed?
48
+ @newest
49
+ end
50
+
51
+ def newest(formulas)
52
+ newest_formulas = filter_by_max_version(formulas)
53
+ smallest(newest_formulas)
54
+ end
55
+
56
+ def smallest_is_passed?
57
+ @smallest
58
+ end
59
+
60
+ def smallest(formulas)
61
+ [choose_smallest_formula(formulas)]
62
+ end
63
+
64
+ def default_way(formulas)
65
+ size_limited_formulas = filter_by_size_limit(formulas)
66
+ raise_size_limit_error if size_limited_formulas.empty?
67
+ newest(size_limited_formulas)
68
+ end
69
+
70
+ def contain_different_styles?(formulas)
71
+ styles_by_formula = formulas.map do |formula|
72
+ fonts = formula.fonts_by_name(@font_name)
73
+ styles = fonts.flat_map do |font|
74
+ font.styles.map(&:type)
75
+ end
76
+
77
+ styles.uniq.sort
78
+ end
79
+
80
+ styles_by_formula.uniq.size > 1
81
+ end
82
+
83
+ def filter_by_size_limit(formulas)
84
+ formulas.select do |formula|
85
+ formula.file_size.nil? || formula.file_size < size_limit_in_bytes
86
+ end
87
+ end
88
+
89
+ def size_limit_in_bytes
90
+ @size_limit_in_bytes ||= @size_limit * 1024 * 1024
91
+ end
92
+
93
+ def raise_size_limit_error
94
+ raise Errors::SizeLimitError,
95
+ "There are only formulas above the size limit " \
96
+ "(#{@size_limit} MB)."
97
+ end
98
+
99
+ def filter_by_max_version(formulas)
100
+ formulas_with_version = detect_formula_version(formulas)
101
+ max_version = formulas_with_version.map(&:first).max
102
+ formulas_with_version.select do |version, _formula|
103
+ version == max_version
104
+ end.map(&:last)
105
+ end
106
+
107
+ def detect_formula_version(formulas)
108
+ formulas.map do |formula|
109
+ fonts = formula.fonts_by_name(@font_name)
110
+ versions = fonts.flat_map do |font|
111
+ font.styles.map do |style|
112
+ StyleVersion.new(style.version)
113
+ end
114
+ end
115
+
116
+ [versions.max, formula]
117
+ end
118
+ end
119
+
120
+ def choose_smallest_formula(formulas)
121
+ formulas.min_by do |formula|
122
+ formula.file_size || 0
123
+ end
124
+ end
125
+ end
126
+ end