fontist 1.12.0 → 1.13.0

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: 709582759b1009bae25d302ab0590ed5f6fe92fe55d68d1cb57c918942b4f005
4
- data.tar.gz: 165f75a0625995d8fcc388d46a26168008383d98d2705cb1ea5ed519abe41e80
3
+ metadata.gz: 43f3bc7643cf7694fb753d9c62509f7134a26d68fb41a2e06c9c9e25f33ae2c5
4
+ data.tar.gz: 3269f7aedc78eed761697ff862701bf6ca27679e9be90972d8983e913a15beea
5
5
  SHA512:
6
- metadata.gz: fd3d62de512ff44e1d9b47c192889fdcefa5db9abea1f0966ac3d761c4ef5567fa547b7d57b4eda52720040d3ca82a03eec2e3d72b24d1f9522dbde1e092c625
7
- data.tar.gz: 3adf2dcebf7714cc81fc3a6955ac69fdf7affe3e90a845f011f52d284332c856112bef7f8e98cf6d96175c043df299ad0965148ef96308b38c6eace46547ef52
6
+ metadata.gz: a92d2d69bed9e8e33fc9785f198c9878d1a02dda4de65f290ecff30336adec6117cfd18cc09d52545f318a917b40e02b4d796049384b6b6c12fee05d2056283f
7
+ data.tar.gz: ffdb9a02c723a5a8c04c26c3f3d5a0d0bba4e875fd750bee67a3c68698d2f2e9057ff936019523d3eb9a359bbbf19de566c45acb99fff99b745952039add7e30
data/.rubocop.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  inherit_from:
2
2
  - 'https://raw.githubusercontent.com/fontist/oss-guides/master/ci/rubocop.yml'
3
3
 
4
- Rails:
5
- Enabled: false
4
+ AllCops:
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.
data/lib/fontist/cli.rb CHANGED
@@ -17,15 +17,24 @@ module Fontist
17
17
  STATUS_MAIN_REPO_NOT_FOUND = 9
18
18
  STATUS_REPO_COULD_NOT_BE_UPDATED = 10
19
19
  STATUS_MANUAL_FONT_ERROR = 11
20
+ STATUS_SIZE_LIMIT_ERROR = 12
20
21
 
21
22
  ERROR_TO_STATUS = {
22
23
  Fontist::Errors::UnsupportedFontError => [STATUS_NON_SUPPORTED_FONT_ERROR],
23
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
+ ],
24
31
  Fontist::Errors::ManualFontError => [STATUS_MANUAL_FONT_ERROR],
25
32
  Fontist::Errors::LicensingError => [STATUS_LICENSING_ERROR],
26
33
  Fontist::Errors::ManifestCouldNotBeFoundError => [STATUS_MANIFEST_COULD_NOT_BE_FOUND_ERROR,
34
+ :overwrite,
27
35
  "Manifest could not be found."],
28
36
  Fontist::Errors::ManifestCouldNotBeReadError => [STATUS_MANIFEST_COULD_NOT_BE_READ_ERROR,
37
+ :overwrite,
29
38
  "Manifest could not be read."],
30
39
  Fontist::Errors::FontIndexCorrupted => [STATUS_FONT_INDEX_CORRUPTED],
31
40
  Fontist::Errors::RepoNotFoundError => [STATUS_REPO_NOT_FOUND],
@@ -43,18 +52,27 @@ module Fontist
43
52
  desc "install FONT", "Install font"
44
53
  option :force, type: :boolean, aliases: :f,
45
54
  desc: "Install even if it's already installed in system"
46
- option :accept_all_licenses, type: :boolean, aliases: "--confirm-license", desc: "Accept all license agreements"
47
- option :hide_licenses, type: :boolean, desc: "Hide license texts"
48
- 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)"
49
72
  def install(font)
50
73
  handle_class_options(options)
51
- Fontist::Font.install(
52
- font,
53
- force: options[:force],
54
- confirmation: options[:accept_all_licenses] ? "yes" : "no",
55
- hide_licenses: options[:hide_licenses],
56
- no_progress: options[:no_progress]
57
- )
74
+ confirmation = options[:accept_all_licenses] ? "yes" : "no"
75
+ Fontist::Font.install(font, options.merge(confirmation: confirmation))
58
76
  success
59
77
  rescue Fontist::Errors::GeneralError => e
60
78
  handle_error(e)
@@ -187,10 +205,18 @@ module Fontist
187
205
  end
188
206
 
189
207
  def handle_error(exception)
190
- status, message = ERROR_TO_STATUS[exception.class]
208
+ status, mode, message = ERROR_TO_STATUS[exception.class]
191
209
  raise exception unless status
192
210
 
193
- 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)
194
220
  end
195
221
 
196
222
  def error(message, status)
@@ -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
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
@@ -102,6 +107,16 @@ module Fontist
102
107
  FontInstaller.new(formula, no_progress: @no_progress)
103
108
  end
104
109
 
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
+
105
120
  def downloadable_formulas
106
121
  @downloadable_formulas ||= formulas.select(&:downloadable?)
107
122
  end
@@ -130,9 +145,9 @@ module Fontist
130
145
  end
131
146
 
132
147
  def download_font
133
- return if downloadable_formulas.empty?
148
+ return if sufficient_formulas.empty?
134
149
 
135
- downloadable_formulas.flat_map do |formula|
150
+ sufficient_formulas.flat_map do |formula|
136
151
  confirmation = check_and_confirm_required_license(formula)
137
152
  paths = font_installer(formula).install(confirmation: confirmation)
138
153
 
@@ -107,6 +107,12 @@ module Fontist
107
107
  Helpers.parse_to_object(@data["extract"])
108
108
  end
109
109
 
110
+ def file_size
111
+ return unless @data["resources"]
112
+
113
+ @data["resources"].values.first["file_size"]&.to_i
114
+ end
115
+
110
116
  def resources
111
117
  Helpers.parse_to_object(@data["resources"]&.values)
112
118
  end
@@ -115,8 +121,14 @@ module Fontist
115
121
  @data["instructions"]
116
122
  end
117
123
 
124
+ def fonts_by_name(name)
125
+ fonts.select do |font|
126
+ font.name.casecmp?(name)
127
+ end
128
+ end
129
+
118
130
  def fonts
119
- @fonts ||= Helpers.parse_to_object(hash_collection_fonts + hash_fonts)
131
+ @fonts ||= Helpers.parse_to_object(fonts_by_family)
120
132
  end
121
133
 
122
134
  def digest
@@ -130,6 +142,41 @@ module Fontist
130
142
  @path.sub(Regexp.new("^" + escaped), "").sub(/\.yml$/, "")
131
143
  end
132
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
+
133
180
  def hash_collection_fonts
134
181
  return [] unless @data["font_collections"]
135
182
 
@@ -138,8 +185,7 @@ module Fontist
138
185
  "source_font" => coll["source_filename"] }
139
186
 
140
187
  coll["fonts"].map do |font|
141
- { "name" => font["name"],
142
- "styles" => font["styles"].map { |s| filenames.merge(s) } }
188
+ font.merge("styles" => font["styles"].map { |s| filenames.merge(s) })
143
189
  end
144
190
  end
145
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
@@ -73,7 +73,7 @@ module Fontist
73
73
  end
74
74
 
75
75
  def resource_options_without_sha
76
- { urls: [@url] + mirrors }
76
+ { urls: [@url] + mirrors, file_size: file_size }
77
77
  end
78
78
 
79
79
  def resource_options_with_sha
@@ -86,7 +86,7 @@ module Fontist
86
86
 
87
87
  sha = prepare_sha256(sha)
88
88
 
89
- { urls: urls, sha256: sha }
89
+ { urls: urls, sha256: sha, file_size: file_size }
90
90
  end
91
91
 
92
92
  def downloads
@@ -120,6 +120,10 @@ module Fontist
120
120
  output
121
121
  end
122
122
 
123
+ def file_size
124
+ File.size(@archive)
125
+ end
126
+
123
127
  def font_collections
124
128
  return if @font_collection_files.empty?
125
129
 
@@ -9,7 +9,10 @@ module Fontist
9
9
 
10
10
  def add_formula(formula)
11
11
  formula.fonts.each do |font|
12
- add_index_formula(font.name, formula.to_index_formula)
12
+ font.styles.each do |style|
13
+ font_name = style.default_family_name || font.name
14
+ add_index_formula(font_name, formula.to_index_formula)
15
+ end
13
16
  end
14
17
  end
15
18
 
@@ -0,0 +1,39 @@
1
+ module Fontist
2
+ class StyleVersion
3
+ def initialize(text)
4
+ @text = text
5
+ end
6
+
7
+ def value
8
+ @value ||= numbers || default_value
9
+ end
10
+
11
+ def numbers
12
+ string_version&.split(".")&.map(&:strip)
13
+ end
14
+
15
+ def string_version
16
+ @text&.split(";")&.first
17
+ end
18
+
19
+ def default_value
20
+ ["0"]
21
+ end
22
+
23
+ def <=>(other)
24
+ value <=> other.value
25
+ end
26
+
27
+ def ==(other)
28
+ value == other.value
29
+ end
30
+
31
+ def eql?(other)
32
+ value.eql?(other.value)
33
+ end
34
+
35
+ def hash
36
+ value.hash
37
+ end
38
+ end
39
+ end
@@ -1,3 +1,3 @@
1
1
  module Fontist
2
- VERSION = "1.12.0".freeze
2
+ VERSION = "1.13.0".freeze
3
3
  end
data/lib/fontist.rb CHANGED
@@ -107,6 +107,10 @@ module Fontist
107
107
  Fontist.fontist_version_path
108
108
  end
109
109
 
110
+ def self.formula_size_limit_in_megabytes
111
+ 300
112
+ end
113
+
110
114
  def self.preferred_family?
111
115
  !!@preferred_family
112
116
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fontist
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.12.0
4
+ version: 1.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-11-23 00:00:00.000000000 Z
11
+ date: 2021-12-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: down
@@ -304,6 +304,7 @@ files:
304
304
  - lib/fontist/font_installer.rb
305
305
  - lib/fontist/font_path.rb
306
306
  - lib/fontist/formula.rb
307
+ - lib/fontist/formula_picker.rb
307
308
  - lib/fontist/google_cli.rb
308
309
  - lib/fontist/helpers.rb
309
310
  - lib/fontist/import.rb
@@ -346,6 +347,7 @@ files:
346
347
  - lib/fontist/manifest/locations.rb
347
348
  - lib/fontist/repo.rb
348
349
  - lib/fontist/repo_cli.rb
350
+ - lib/fontist/style_version.rb
349
351
  - lib/fontist/system.yml
350
352
  - lib/fontist/system_font.rb
351
353
  - lib/fontist/system_index.rb