fontist 1.11.5 → 1.13.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/rspec.yml +9 -1
- data/.rubocop.yml +1 -18
- data/README.adoc +54 -3
- data/fontist.gemspec +3 -1
- data/lib/fontist/cli.rb +51 -14
- data/lib/fontist/errors.rb +10 -0
- data/lib/fontist/font.rb +60 -14
- data/lib/fontist/formula.rb +66 -4
- data/lib/fontist/formula_picker.rb +126 -0
- data/lib/fontist/import/create_formula.rb +16 -10
- data/lib/fontist/import/files/font_detector.rb +4 -2
- data/lib/fontist/import/formula_builder.rb +24 -15
- data/lib/fontist/import/macos.rb +148 -0
- data/lib/fontist/import/manual_formula_builder.rb +24 -0
- data/lib/fontist/import/recursive_extraction.rb +2 -0
- data/lib/fontist/import_cli.rb +19 -0
- data/lib/fontist/indexes/default_family_font_index.rb +4 -1
- data/lib/fontist/repo.rb +13 -1
- data/lib/fontist/style_version.rb +39 -0
- data/lib/fontist/system.yml +1 -0
- data/lib/fontist/system_font.rb +1 -1
- data/lib/fontist/update.rb +11 -31
- data/lib/fontist/utils/system.rb +10 -0
- data/lib/fontist/version.rb +1 -1
- data/lib/fontist.rb +9 -1
- metadata +49 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 43f3bc7643cf7694fb753d9c62509f7134a26d68fb41a2e06c9c9e25f33ae2c5
|
4
|
+
data.tar.gz: 3269f7aedc78eed761697ff862701bf6ca27679e9be90972d8983e913a15beea
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a92d2d69bed9e8e33fc9785f198c9878d1a02dda4de65f290ecff30336adec6117cfd18cc09d52545f318a917b40e02b4d796049384b6b6c12fee05d2056283f
|
7
|
+
data.tar.gz: ffdb9a02c723a5a8c04c26c3f3d5a0d0bba4e875fd750bee67a3c68698d2f2e9057ff936019523d3eb9a359bbbf19de566c45acb99fff99b745952039add7e30
|
data/.github/workflows/rspec.yml
CHANGED
@@ -33,7 +33,15 @@ jobs:
|
|
33
33
|
env:
|
34
34
|
TEST_ENV: CI
|
35
35
|
|
36
|
-
- if: matrix.os
|
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
|
-
|
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/
|
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
|
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,
|
44
|
-
|
45
|
-
|
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
|
-
|
49
|
-
|
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
|
-
|
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(
|
246
|
+
Fontist.ui.success(msg)
|
210
247
|
else
|
211
|
-
Fontist.ui.error(
|
248
|
+
Fontist.ui.error(msg)
|
212
249
|
end
|
213
250
|
end
|
214
251
|
end
|
data/lib/fontist/errors.rb
CHANGED
@@ -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 ||
|
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 ||
|
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 ||
|
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 ||
|
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
|
-
|
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
|
102
|
-
@
|
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
|
110
|
-
if formula
|
111
|
-
|
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
|
148
|
+
return if sufficient_formulas.empty?
|
117
149
|
|
118
|
-
|
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
|
data/lib/fontist/formula.rb
CHANGED
@@ -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"]
|
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(
|
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
|
-
|
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
|