fontist 1.11.6 → 1.13.1

Sign up to get free protection for your applications and to get access to all the features.
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