fontist 1.5.1 → 1.7.3

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: a35bdc7e99674109bec5810eb8e57d91516ff93f7cf4aefbb608e0298a010f76
4
- data.tar.gz: fc886de884ebc5309acb9dc6168fd6c2d7f460f11e05d9be8a1ffca8177e3b6f
3
+ metadata.gz: bfbc7b0d13e8084d44fe41d69ff1719a203a375cd75970cf8efa0abd2cd711af
4
+ data.tar.gz: 1a259f0e45ea264ca55c1e112cb25bd672f41532ae82c58989cf368f058d2374
5
5
  SHA512:
6
- metadata.gz: 05f4a699ac69711925ebf9f036be06e5f5c302b9fe3cec23974bc7892ff18a73115d2373694784ee11ac8c0620b5df215a50cb9c2f173a6448a1ceb0b688753b
7
- data.tar.gz: a41c8f091f5783cb0f2d0beabc0d92e9059f78415f36593f9de6b18eb1175d4059a38cb60710dd5064f0a8280aaa6ab9a13e68190903ed7ebe011e8b9068d39c
6
+ metadata.gz: 82a25bf83f43b02f1e8a77717d9d240ebd55910bc0c529ce0ff09d434cad829c862c8db9564597159a3214b6cffa9dce2ee8f64a6f841f5dc589e10571a94c44
7
+ data.tar.gz: 91771cd423b516b6db27db7ef5e55cd24f01bea9fb368aa4331e0bc75a887e3df35d84a4fa08748e98bc41a16d8f80861cf584ff9cc6a61e938c3b7392ee94ee
data/README.md CHANGED
@@ -109,7 +109,7 @@ fonts in your system.
109
109
  #### Find formula fonts
110
110
 
111
111
  Normally, each font name can be associated with multiple styles or collection, for
112
- example the `Calibri` font might contains a `regular`, `bola` or `italic` styles
112
+ example the `Calibri` font might contains a `regular`, `bold` or `italic` styles
113
113
  fonts and if you want a interface that can return the complete list then this is
114
114
  your friend. You can use it as following:
115
115
 
@@ -136,28 +136,29 @@ operation you would do in any ruby object.
136
136
 
137
137
  #### Locations
138
138
 
139
- Fontist lets find font locations from a YAML manifest of the following format:
139
+ Fontist lets find font locations from a manifest of the following format:
140
140
 
141
- ```yml
142
- Segoe UI:
143
- - Regular
144
- - Bold
145
- Roboto Mono:
146
- - Regular
141
+ ```ruby
142
+ {"Segoe UI"=>["Regular", "Bold"],
143
+ "Roboto Mono"=>["Regular"]}
147
144
  ```
148
145
 
149
- Calling the following code returns a nested hash with font paths.
146
+ Calling the following code returns a nested hash with font paths and names.
147
+ Font name is useful to choose a specific font in a font collection file (TTC).
150
148
 
151
149
  ```ruby
152
- Fontist::Manifest::Locations.call(manifest_path)
150
+ Fontist::Manifest::Locations.from_hash(manifest)
153
151
  ```
154
152
 
155
153
  ```ruby
156
- {"Segoe UI"=>
157
- {"Regular"=>["/Users/user/.fontist/fonts/SEGOEUI.TTF"],
158
- "Bold"=>["/Users/user/.fontist/fonts/SEGOEUIB.TTF"]},
159
- "Roboto Mono"=>
160
- {"Regular"=>[]}}
154
+ {"Segoe UI"=> {
155
+ "Regular"=>{"full_name"=>"Segoe UI",
156
+ "paths"=>["/Users/user/.fontist/fonts/SEGOEUI.TTF"]},
157
+ "Bold"=>{"full_name"=>"Segoe UI Bold",
158
+ "paths"=>["/Users/user/.fontist/fonts/SEGOEUIB.TTF"]}},
159
+ "Roboto Mono"=> {
160
+ "Regular"=>{"full_name"=>nil,
161
+ "paths"=>[]}}}
161
162
  ```
162
163
 
163
164
  #### Install
@@ -166,17 +167,41 @@ Fontist lets not only to get font locations but also to install fonts from the
166
167
  manifest:
167
168
 
168
169
  ```ruby
169
- Fontist::Manifest::Install.call(manifest, confirmation: "yes")
170
+ Fontist::Manifest::Install.from_hash(manifest, confirmation: "yes")
170
171
  ```
171
172
 
172
173
  It will install fonts and return their locations:
173
174
 
174
175
  ```ruby
175
- {"Segoe UI"=>
176
- {"Regular"=>["/Users/user/.fontist/fonts/SEGOEUI.TTF"],
177
- "Bold"=>["/Users/user/.fontist/fonts/SEGOEUIB.TTF"]},
178
- "Roboto Mono"=>
179
- {"Regular"=>["/Users/user/.fontist/fonts/RobotoMono-VariableFont_wght.ttf"]}}
176
+ {"Segoe UI"=> {
177
+ "Regular"=>{"full_name"=>"Segoe UI",
178
+ "paths"=>["/Users/user/.fontist/fonts/SEGOEUI.TTF"]},
179
+ "Bold"=>{"full_name"=>"Segoe UI Bold",
180
+ "paths"=>["/Users/user/.fontist/fonts/SEGOEUIB.TTF"]}},
181
+ "Roboto Mono"=> {
182
+ "Regular"=>{"full_name"=>"Roboto Mono Regular",
183
+ "paths"=>["/Users/user/.fontist/fonts/RobotoMono-VariableFont_wght.ttf"]}}}
184
+ ```
185
+
186
+ #### Support of YAML format
187
+
188
+ Both commands support a YAML file as an input with a `from_file` method. For
189
+ example, if there is a `manifest.yml` file containing:
190
+
191
+ ```yaml
192
+ Segoe UI:
193
+ - Regular
194
+ - Bold
195
+ Roboto Mono:
196
+ - Regular
197
+ ```
198
+
199
+ Then the following calls would return font names and paths, as from the
200
+ `from_hash` method (see [Locations](#locations) and [Install](#install)).
201
+
202
+ ```ruby
203
+ Fontist::Manifest::Locations.from_file("manifest.yml")
204
+ Fontist::Manifest::Install.from_file("manifest.yml", confirmation: "yes")
180
205
  ```
181
206
 
182
207
  ### CLI
@@ -191,7 +216,8 @@ All searches are case-insensitive for ease of use.
191
216
 
192
217
  The `install` command is similar to the `Font.install` call. It first checks
193
218
  whether this font is already installed, and if not, then installs the font and
194
- returns its paths. Font or formula could be specified as a name.
219
+ returns its paths. Only font name (not formula name, nor font filename) could
220
+ be used as a parameter.
195
221
 
196
222
  ```
197
223
  $ fontist install "segoe ui"
@@ -274,11 +300,17 @@ $ fontist manifest-locations manifest.yml
274
300
  ---
275
301
  Segoe UI:
276
302
  Regular:
277
- - "/Users/user/.fontist/fonts/SEGOEUI.TTF"
303
+ full_name: Segoe UI
304
+ paths:
305
+ - "/Users/user/.fontist/fonts/SEGOEUI.TTF"
278
306
  Bold:
279
- - "/Users/user/.fontist/fonts/SEGOEUIB.TTF"
307
+ full_name: Segoe UI Bold
308
+ paths:
309
+ - "/Users/user/.fontist/fonts/SEGOEUIB.TTF"
280
310
  Roboto Mono:
281
- Regular: []
311
+ Regular:
312
+ full_name:
313
+ paths: []
282
314
  ```
283
315
 
284
316
  Since Segoe UI is installed, but Roboto Mono is not.
@@ -292,12 +324,18 @@ $ fontist manifest-install --confirm-license manifest.yml
292
324
  ---
293
325
  Segoe UI:
294
326
  Regular:
295
- - "/Users/user/.fontist/fonts/SEGOEUI.TTF"
327
+ full_name: Segoe UI
328
+ paths:
329
+ - "/Users/user/.fontist/fonts/SEGOEUI.TTF"
296
330
  Bold:
297
- - "/Users/user/.fontist/fonts/SEGOEUIB.TTF"
331
+ full_name: Segoe UI Bold
332
+ paths:
333
+ - "/Users/user/.fontist/fonts/SEGOEUIB.TTF"
298
334
  Roboto Mono:
299
335
  Regular:
300
- - "/Users/user/.fontist/fonts/RobotoMono-VariableFont_wght.ttf"
336
+ full_name: Roboto Mono Regular
337
+ paths:
338
+ - "/Users/user/.fontist/fonts/RobotoMono-VariableFont_wght.ttf"
301
339
  ```
302
340
 
303
341
  #### Help
@@ -308,6 +346,15 @@ List of all commands could be seen by:
308
346
  fontist help
309
347
  ```
310
348
 
349
+ ### Configuration
350
+
351
+ By default Fontist uses the `~/.fontist` directory to store fonts and its
352
+ files. It could be changed with the `FONTIST_PATH` environment variable.
353
+
354
+ ```sh
355
+ FONTIST_PATH=~/.fontist_new fontist update
356
+ ```
357
+
311
358
  ## Development
312
359
 
313
360
  We are following Sandi Metz's Rules for this gem, you can read the
@@ -34,6 +34,7 @@ Gem::Specification.new do |spec|
34
34
  spec.add_runtime_dependency "ruby-ole", "~> 1.0"
35
35
  spec.add_runtime_dependency "thor", "~> 1.0.1"
36
36
  spec.add_runtime_dependency "git", "~> 1.0"
37
+ spec.add_runtime_dependency "ttfunk", "~> 1.0"
37
38
 
38
39
  spec.add_development_dependency "extract_ttc", "~> 0.1"
39
40
  spec.add_development_dependency "pry"
@@ -29,7 +29,7 @@ module Fontist
29
29
  end
30
30
 
31
31
  def self.fontist_path
32
- Pathname.new(Dir.home).join(".fontist")
32
+ Pathname.new(ENV["FONTIST_PATH"] || File.join(Dir.home, ".fontist"))
33
33
  end
34
34
 
35
35
  def self.fonts_path
@@ -55,4 +55,8 @@ module Fontist
55
55
  def self.system_file_path
56
56
  Fontist.lib_path.join("fontist", "system.yml")
57
57
  end
58
+
59
+ def self.system_index_path
60
+ Fontist.fontist_path.join("system_index.yml")
61
+ end
58
62
  end
@@ -9,17 +9,19 @@ module Fontist
9
9
  false
10
10
  end
11
11
 
12
- desc "install FONT", "Install font by font or formula"
12
+ desc "install FONT", "Install font"
13
13
  option :force, type: :boolean, aliases: :f,
14
14
  desc: "Install even if it's already installed in system"
15
+ option :confirm_license, type: :boolean, desc: "Confirm license agreement"
15
16
  def install(font)
16
- fonts_paths = Fontist::Font.install(font, force: options[:force])
17
- Fontist.ui.success("These fonts are found or installed:")
18
- Fontist.ui.success(fonts_paths.join("\n"))
17
+ Fontist::Font.install(
18
+ font,
19
+ force: options[:force],
20
+ confirmation: options[:confirm_license] ? "yes" : "no"
21
+ )
19
22
  STATUS_SUCCESS
20
23
  rescue Fontist::Errors::NonSupportedFontError
21
- Fontist.ui.error("Could not find font '#{font}'.")
22
- STATUS_ERROR
24
+ could_not_find_font(font)
23
25
  end
24
26
 
25
27
  desc "uninstall/remove FONT", "Uninstall font by font or formula"
@@ -32,8 +34,7 @@ module Fontist
32
34
  Fontist.ui.error(e.message)
33
35
  STATUS_ERROR
34
36
  rescue Fontist::Errors::NonSupportedFontError
35
- Fontist.ui.error("Could not find font '#{font}'.")
36
- STATUS_ERROR
37
+ could_not_find_font(font)
37
38
  end
38
39
  map remove: :uninstall
39
40
 
@@ -47,7 +48,7 @@ module Fontist
47
48
  rescue Fontist::Errors::MissingFontError => e
48
49
  error(e.message)
49
50
  rescue Fontist::Errors::NonSupportedFontError
50
- error("Could not find font '#{font}'.")
51
+ could_not_find_font(font)
51
52
  end
52
53
 
53
54
  desc "list [FONT]", "List installation status of FONT or fonts in fontist"
@@ -56,7 +57,7 @@ module Fontist
56
57
  print_list(formulas)
57
58
  success
58
59
  rescue Fontist::Errors::NonSupportedFontError
59
- error("Could not find font '#{font}'.")
60
+ could_not_find_font(font)
60
61
  end
61
62
 
62
63
  desc "update", "Update formulas"
@@ -69,7 +70,7 @@ module Fontist
69
70
  desc "manifest-locations MANIFEST",
70
71
  "Get locations of fonts from MANIFEST (yaml)"
71
72
  def manifest_locations(manifest)
72
- paths = Fontist::Manifest::Locations.call(manifest)
73
+ paths = Fontist::Manifest::Locations.from_file(manifest)
73
74
  print_yaml(paths)
74
75
  success
75
76
  rescue Fontist::Errors::ManifestCouldNotBeFoundError
@@ -81,7 +82,7 @@ module Fontist
81
82
  desc "manifest-install MANIFEST", "Install fonts from MANIFEST (yaml)"
82
83
  option :confirm_license, type: :boolean, desc: "Confirm license agreement"
83
84
  def manifest_install(manifest)
84
- paths = Fontist::Manifest::Install.call(
85
+ paths = Fontist::Manifest::Install.from_file(
85
86
  manifest,
86
87
  confirmation: options[:confirm_license] ? "yes" : "no"
87
88
  )
@@ -98,6 +99,7 @@ module Fontist
98
99
  option :name, desc: "Example: Times New Roman"
99
100
  option :mirror, repeatable: true
100
101
  option :subarchive, desc: "Subarchive to choose when there are several ones"
102
+ option :subdir, desc: "Subdirectory to take fonts from"
101
103
  def create_formula(url)
102
104
  require "fontist/import/create_formula"
103
105
  name = Fontist::Import::CreateFormula.new(url, options).call
@@ -111,6 +113,15 @@ module Fontist
111
113
  STATUS_SUCCESS
112
114
  end
113
115
 
116
+ def could_not_find_font(font)
117
+ error("Font '#{font}' not found locally nor available in the Fontist " \
118
+ "formula repository.\n" \
119
+ "Perhaps it is available at the latest Fontist formula " \
120
+ "repository.\n" \
121
+ "You can update the formula repository using the command " \
122
+ "`fontist update` and try again.")
123
+ end
124
+
114
125
  def error(message)
115
126
  Fontist.ui.error(message)
116
127
  STATUS_ERROR
@@ -7,6 +7,7 @@ module Fontist
7
7
  class InvalidResourceError < StandardError; end
8
8
  class TimeoutError < StandardError; end
9
9
  class MissingAttributeError < StandardError; end
10
+ class UnknownFontTypeError < StandardError; end
10
11
  class FontNotFoundError < StandardError; end
11
12
  class BinaryCallError < StandardError; end
12
13
  class ManifestCouldNotBeReadError < StandardError; end
@@ -81,7 +81,16 @@ module Fontist
81
81
  attr_reader :name, :confirmation
82
82
 
83
83
  def find_system_font
84
- Fontist::SystemFont.find(name)
84
+ paths = Fontist::SystemFont.find(name)
85
+ unless paths
86
+ Fontist.ui.say(%(Font "#{name}" not found locally.))
87
+ return
88
+ end
89
+
90
+ Fontist.ui.say("Fonts found at:")
91
+ paths.each do |path|
92
+ Fontist.ui.say("- #{path}")
93
+ end
85
94
  end
86
95
 
87
96
  def check_or_create_fontist_path!
@@ -113,7 +122,13 @@ module Fontist
113
122
  def download_font
114
123
  if formula
115
124
  check_and_confirm_required_license(formula)
116
- font_installer(formula).fetch_font(name, confirmation: confirmation)
125
+ paths = font_installer(formula).fetch_font(name,
126
+ confirmation: confirmation)
127
+
128
+ Fontist.ui.say("Fonts installed at:")
129
+ paths.each do |path|
130
+ Fontist.ui.say("- #{path}")
131
+ end
117
132
  end
118
133
  end
119
134
 
@@ -232,6 +247,5 @@ module Fontist
232
247
  def installed(style)
233
248
  path(style) ? true : false
234
249
  end
235
-
236
250
  end
237
251
  end
@@ -83,34 +83,50 @@ module Fontist
83
83
  end
84
84
  end
85
85
 
86
- def match_fonts(fonts_dir, font_name)
87
- fonts = map_names_to_fonts(font_name).join("|")
88
- font = fonts_dir.grep(/#{fonts}/i)
89
- @matched_fonts.push(font) if font
86
+ def match_fonts(fonts_paths, font_name)
87
+ filenames = filenames_by_font_name(font_name)
88
+ paths = search_for_filenames(fonts_paths, filenames)
89
+ @matched_fonts.push(*paths)
90
90
 
91
- font
91
+ paths
92
92
  end
93
93
 
94
- def extract_from_collection(options)
95
- styles = options.fetch(:extract_styles_from_collection, [])
94
+ def filenames_by_font_name(font_name)
95
+ fonts.map do |f|
96
+ if f[:name].casecmp?(font_name)
97
+ f[:styles].map do |s|
98
+ s[:font]
99
+ end
100
+ end
101
+ end.flatten.compact
102
+ end
96
103
 
97
- unless styles.empty?
98
- styles.map do |type, file|
99
- { type: type, collection: file, font: temp_resource[:filename] }
104
+ def search_for_filenames(paths, filenames)
105
+ paths.select do |path|
106
+ filenames.any? do |filename|
107
+ File.basename(path) == filename
100
108
  end
101
109
  end
102
110
  end
103
111
 
104
- def map_names_to_fonts(font_name)
105
- fonts = Fontist::Formula.find_fonts(font_name)
106
- fonts = fonts.map { |font| font.styles.map(&:font) }.flatten if fonts
112
+ def extract_from_collection(options)
113
+ styles = options.fetch(:extract_styles_from_collection, [])
107
114
 
108
- fonts || []
115
+ unless styles.empty?
116
+ styles.map do |attributes|
117
+ filenames = temp_resource.slice(:filename, :source_filename)
118
+ Fontist::Utils::Dsl::CollectionFont.new(attributes.merge(filenames))
119
+ .attributes
120
+ end
121
+ end
109
122
  end
110
123
 
111
124
  def download_file(source)
125
+ url = source[:urls].first
126
+ Fontist.ui.say(%(Downloading font "#{key}" from #{url}))
127
+
112
128
  downloaded_file = Fontist::Utils::Downloader.download(
113
- source[:urls].first,
129
+ url,
114
130
  sha: source[:sha256],
115
131
  file_size: source[:file_size],
116
132
  progress_bar: is_progress_bar_enabled
@@ -121,7 +137,33 @@ module Fontist
121
137
  end
122
138
 
123
139
  def is_progress_bar_enabled
124
- options.nil? ? false : options.fetch(:progress_bar, false)
140
+ options.nil? ? true : options.fetch(:progress_bar, true)
141
+ end
142
+
143
+ def font_file?(filename)
144
+ source_files.include?(filename)
145
+ end
146
+
147
+ def source_files
148
+ @source_files ||= fonts.flat_map do |font|
149
+ font[:styles].map do |style|
150
+ style[:source_font] || style[:font]
151
+ end
152
+ end
153
+ end
154
+
155
+ def target_filename(source_filename)
156
+ target_filenames[source_filename]
157
+ end
158
+
159
+ def target_filenames
160
+ @target_filenames ||= fonts.flat_map do |font|
161
+ font[:styles].map do |style|
162
+ source = style[:source_font] || style[:font]
163
+ target = style[:font]
164
+ [source, target]
165
+ end
166
+ end.to_h
125
167
  end
126
168
  end
127
169
  end
@@ -28,79 +28,39 @@ module Fontist
28
28
  end
29
29
 
30
30
  def find
31
- [find_formula].flatten.first
31
+ formulas.values.detect do |formula|
32
+ formula.fonts.any? do |f|
33
+ f.name.casecmp?(font_name)
34
+ end
35
+ end
32
36
  end
33
37
 
34
38
  def find_fonts
35
- formulas = [find_formula].flatten
36
- fonts = take_fonts(formulas)
37
- fonts.empty? ? nil : fonts
39
+ formulas.values.map do |formula|
40
+ formula.fonts.select do |f|
41
+ f.name.casecmp?(font_name)
42
+ end
43
+ end.flatten
38
44
  end
39
45
 
40
46
  def find_styles
41
- formulas.values.flat_map do |formula|
42
- formula.fonts.flat_map do |f|
47
+ formulas.values.map do |formula|
48
+ formula.fonts.map do |f|
43
49
  f.styles.select do |s|
44
50
  f.name.casecmp?(font_name) && s.type.casecmp?(style_name)
45
51
  end
46
52
  end
47
- end
53
+ end.flatten
48
54
  end
49
55
 
50
56
  private
51
57
 
52
58
  attr_reader :font_name, :style_name
53
59
 
54
- def find_formula
55
- find_by_key || find_by_font_name || find_by_font || []
56
- end
57
-
58
60
  def formulas
59
61
  @formulas ||= all.to_h
60
62
  end
61
63
 
62
- def take_fonts(formulas)
63
- formulas.map(&:fonts).flatten
64
- end
65
-
66
- def find_by_key
67
- matched_formulas = formulas.select do |key, _value|
68
- key.to_s.casecmp?(font_name)
69
- end
70
-
71
- matched_formulas.empty? ? nil : matched_formulas.values
72
- end
73
-
74
- def find_by_font_name
75
- matched_formulas = formulas.select do |key, value|
76
- !value.fonts.map(&:name).grep(/#{font_name}/i).empty?
77
- end
78
-
79
- matched_formulas.empty? ? nil : matched_formulas.values
80
- end
81
-
82
- # Note
83
- #
84
- # These interface recursively look into every single font styles,
85
- # so ideally try to avoid using it when possible, and that's why
86
- # we've added it as last option in formula finder.
87
- #
88
- def find_by_font
89
- matched_formulas = formulas.select do |key, value|
90
- match_in_font_styles?(value[:fonts])
91
- end
92
-
93
- matched_formulas.empty? ? nil : matched_formulas.values
94
- end
95
-
96
- def match_in_font_styles?(fonts)
97
- styles = fonts.select do |font|
98
- !font.styles.map(&:font).grep(/#{font_name}/i).empty?
99
- end
100
-
101
- styles.empty? ? false : true
102
- end
103
-
104
64
  def check_and_register_font_formulas
105
65
  $check_and_register_font_formulas ||= Fontist::Formulas.register_formulas
106
66
  end