fontist 1.11.7 → 1.13.2

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: d3a779a1f127060501e1c69c59986bcd1a616ab699c5cff439cec4aafc27a0a2
4
- data.tar.gz: cbcfe4d0a06ccfbcb309b2c59aac6a58ce09d804c6b23cec5970a6d67b697d43
3
+ metadata.gz: 2e0bff9ea15b251c5c03206705574e12cfc9fc4bc779d197d73d20a05977e745
4
+ data.tar.gz: 33a6538507cc014c1fd4a0b1b11fa908560ae8319e9de13d33120c02a86953b4
5
5
  SHA512:
6
- metadata.gz: d17e2fa944c7ddfd142869d1db9df35fae4ae7aa58c6188290529d31be66b9043e300b0cff2e4cb13545fb1bbdc707820fa4c88f557c914cb59ad4b7a1fef46f
7
- data.tar.gz: 98db0b18012107e2a39644d9c892a7ef5330543526da993f1b346300bba2bcefa02b2b17ff417a716f7e6f3e84d0b7589eda24d4b154366a290010bbe8f9ad0a
6
+ metadata.gz: bf17d3b2dd7a687f97db3bd24200d0bd07821bab47ac0c0ce8eeb1156ec1fc95b39660dfb75e6eb13e00080968de1168c83cca7d54caee0c09139d0a167651d6
7
+ data.tar.gz: 18b6c0294686dcf739b2d1654b8c3e8488d823cb2de1d62659f834c7f8ca443615170d29f3f3bb2b705b27b07cb8a79d80ca6a185d09979c8c0f2f37f8af547f
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,26 @@ 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
+ -F, [--formula]:: Install by formula instead of font
131
+ -a, [--accept-all-licenses]:: Accept all license agreements
132
+ -h, [--hide-licenses]:: Hide license texts
133
+ -p, [--no-progress]:: Hide download progress
134
+ -V, [--version=VERSION]:: Install particular version of a font
135
+ -s, [--smallest]:: Install the smallest formula
136
+ -n, [--newest]:: Install the newest version of a font
137
+ -S, [--size-limit=N]:: Specify size limit for a formula to be installed
138
+ (default is 300 MB)
139
+
120
140
  === Uninstall fonts
121
141
 
122
142
  Uninstalls any font supported by Fontist.
@@ -618,7 +638,7 @@ repository https://github.com/fontist/formulas[formulas]:
618
638
 
619
639
  [source,sh]
620
640
  ----
621
- cd ~/.fontist/versions/v2/formulas
641
+ cd ~/.fontist/versions/{last_version}/formulas
622
642
  git add Formulas/google
623
643
  git commit -m "Google Fonts update"
624
644
  git push
@@ -640,12 +660,44 @@ They can be updated with:
640
660
  [source,sh]
641
661
  ----
642
662
  fontist import-sil
643
- cd ~/.fontist/formulas
644
- git add Formulas/sil index.yml filename_index.yml
663
+ cd ~/.fontist/versions/{last_version}/formulas
664
+ git add Formulas/sil
645
665
  git commit -m "SIL fonts update"
646
666
  git push
647
667
  ----
648
668
 
669
+ === Dynamically importing formulas from macOS
670
+
671
+ macOS provides https://support.apple.com/en-om/HT211240#download[fonts] which
672
+ can be manually downloaded with the Font Book app. When such font is requested,
673
+ fontist prints information on how to install it.
674
+
675
+ In order to know which fonts are available in a current version of macOS,
676
+ for each version there is a formula containing all supported fonts.
677
+
678
+ A new formula can be generated with:
679
+
680
+ [source,sh]
681
+ ----
682
+ fontist import macos --name "Big Sur" --fonts-link "https://support.apple.com/en-om/HT211240#download"
683
+ cd ~/.fontist/versions/{last_version}/formulas
684
+ git add Formulas/macos
685
+ git commit -m "Add Big Sur macOS formula"
686
+ git push
687
+ ----
688
+
689
+ Here `--fonts-link` is a link to a page containing a list of available fonts
690
+ in the Font Book app.
691
+
692
+ If the import is run on a different version of macOS, then a proper version
693
+ should be set in the `platforms` attribute of the generated formula:
694
+
695
+ [source,yaml]
696
+ ----
697
+ platforms:
698
+ - macos-20
699
+ ----
700
+
649
701
 
650
702
  == Development
651
703
 
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"
@@ -0,0 +1,14 @@
1
+ module Fontist
2
+ class CLI < Thor
3
+ module ClassOptions
4
+ def handle_class_options(options)
5
+ Fontist.preferred_family = options[:preferred_family]
6
+ Fontist.log_level = options[:quiet] ? :fatal : :info
7
+
8
+ if options[:formulas_path]
9
+ Fontist.formulas_path = Pathname.new(options[:formulas_path])
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
data/lib/fontist/cli.rb CHANGED
@@ -1,9 +1,13 @@
1
1
  require "thor"
2
+ require "fontist/cli/class_options"
2
3
  require "fontist/repo_cli"
4
+ require "fontist/import_cli"
3
5
  require "fontist/google_cli"
4
6
 
5
7
  module Fontist
6
8
  class CLI < Thor
9
+ include ClassOptions
10
+
7
11
  STATUS_SUCCESS = 0
8
12
  STATUS_UNKNOWN_ERROR = 1
9
13
  STATUS_NON_SUPPORTED_FONT_ERROR = 2
@@ -15,18 +19,31 @@ module Fontist
15
19
  STATUS_REPO_NOT_FOUND = 8
16
20
  STATUS_MAIN_REPO_NOT_FOUND = 9
17
21
  STATUS_REPO_COULD_NOT_BE_UPDATED = 10
22
+ STATUS_MANUAL_FONT_ERROR = 11
23
+ STATUS_SIZE_LIMIT_ERROR = 12
24
+ STATUS_FORMULA_NOT_FOUND = 13
18
25
 
19
26
  ERROR_TO_STATUS = {
20
27
  Fontist::Errors::UnsupportedFontError => [STATUS_NON_SUPPORTED_FONT_ERROR],
21
28
  Fontist::Errors::MissingFontError => [STATUS_MISSING_FONT_ERROR],
29
+ Fontist::Errors::SizeLimitError => [
30
+ STATUS_SIZE_LIMIT_ERROR,
31
+ :append,
32
+ "Please specify higher `--size-limit`, or use the `--newest` or " \
33
+ "`--smallest` options.",
34
+ ],
35
+ Fontist::Errors::ManualFontError => [STATUS_MANUAL_FONT_ERROR],
22
36
  Fontist::Errors::LicensingError => [STATUS_LICENSING_ERROR],
23
37
  Fontist::Errors::ManifestCouldNotBeFoundError => [STATUS_MANIFEST_COULD_NOT_BE_FOUND_ERROR,
38
+ :overwrite,
24
39
  "Manifest could not be found."],
25
40
  Fontist::Errors::ManifestCouldNotBeReadError => [STATUS_MANIFEST_COULD_NOT_BE_READ_ERROR,
41
+ :overwrite,
26
42
  "Manifest could not be read."],
27
43
  Fontist::Errors::FontIndexCorrupted => [STATUS_FONT_INDEX_CORRUPTED],
28
44
  Fontist::Errors::RepoNotFoundError => [STATUS_REPO_NOT_FOUND],
29
45
  Fontist::Errors::MainRepoNotFoundError => [STATUS_MAIN_REPO_NOT_FOUND],
46
+ Fontist::Errors::FormulaNotFoundError => [STATUS_FORMULA_NOT_FOUND],
30
47
  }.freeze
31
48
 
32
49
  def self.exit_on_failure?
@@ -37,21 +54,39 @@ module Fontist
37
54
  type: :boolean,
38
55
  desc: "Use Preferred Family when available"
39
56
 
57
+ class_option :quiet,
58
+ aliases: :q,
59
+ type: :boolean,
60
+ desc: "Hide all messages"
61
+
62
+ class_option :formulas_path, type: :string, desc: "Path to formulas"
63
+
40
64
  desc "install FONT", "Install font"
41
65
  option :force, type: :boolean, aliases: :f,
42
66
  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"
67
+ option :formula, type: :boolean, aliases: :F,
68
+ desc: "Install by formula instead of font"
69
+ option :accept_all_licenses, type: :boolean,
70
+ aliases: ["--confirm-license", :a],
71
+ desc: "Accept all license agreements"
72
+ option :hide_licenses, type: :boolean, aliases: :h,
73
+ desc: "Hide license texts"
74
+ option :no_progress, type: :boolean, aliases: :p,
75
+ desc: "Hide download progress"
76
+ option :version, type: :string, aliases: :V,
77
+ desc: "Specify particular version of a font"
78
+ option :smallest, type: :boolean, aliases: :s,
79
+ desc: "Install the smallest formula if several"
80
+ option :newest, type: :boolean, aliases: :n,
81
+ desc: "Install the newest version of a font if several"
82
+ option :size_limit,
83
+ type: :numeric, aliases: :S,
84
+ desc: "Specify size limit for formula " \
85
+ "(default is #{Fontist.formula_size_limit_in_megabytes} MB)"
46
86
  def install(font)
47
87
  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
- )
88
+ confirmation = options[:accept_all_licenses] ? "yes" : "no"
89
+ Fontist::Font.install(font, options.merge(confirmation: confirmation))
55
90
  success
56
91
  rescue Fontist::Errors::GeneralError => e
57
92
  handle_error(e)
@@ -113,8 +148,12 @@ module Fontist
113
148
  end
114
149
 
115
150
  desc "manifest-install MANIFEST", "Install fonts from MANIFEST (yaml)"
116
- option :accept_all_licenses, type: :boolean, aliases: "--confirm-license", desc: "Accept all license agreements"
117
- option :hide_licenses, type: :boolean, desc: "Hide license texts"
151
+ option :accept_all_licenses, type: :boolean,
152
+ aliases: ["--confirm-license", :a],
153
+ desc: "Accept all license agreements"
154
+ option :hide_licenses, type: :boolean,
155
+ aliases: :h,
156
+ desc: "Hide license texts"
118
157
  def manifest_install(manifest)
119
158
  handle_class_options(options)
120
159
  paths = Fontist::Manifest::Install.from_file(
@@ -167,24 +206,31 @@ module Fontist
167
206
  desc "repo SUBCOMMAND ...ARGS", "Manage custom repositories"
168
207
  subcommand "repo", Fontist::RepoCLI
169
208
 
209
+ desc "import SUBCOMMAND ...ARGS", "Manage imports"
210
+ subcommand "import", Fontist::ImportCLI
211
+
170
212
  desc "google SUBCOMMAND ...ARGS", "Manage Google formulas"
171
213
  subcommand "google", Fontist::GoogleCLI
172
214
 
173
215
  private
174
216
 
175
- def handle_class_options(options)
176
- Fontist.preferred_family = options[:preferred_family]
177
- end
178
-
179
217
  def success
180
218
  STATUS_SUCCESS
181
219
  end
182
220
 
183
221
  def handle_error(exception)
184
- status, message = ERROR_TO_STATUS[exception.class]
222
+ status, mode, message = ERROR_TO_STATUS[exception.class]
185
223
  raise exception unless status
186
224
 
187
- error(message || exception.message, status)
225
+ text = if message && mode == :overwrite
226
+ message
227
+ elsif message
228
+ "#{exception.message} #{message}"
229
+ else
230
+ exception.message
231
+ end
232
+
233
+ error(text, status)
188
234
  end
189
235
 
190
236
  def error(message, status)
@@ -205,10 +251,15 @@ module Fontist
205
251
  Fontist.ui.say(" #{font.name}")
206
252
 
207
253
  styles.each do |style, installed|
254
+ opts = []
255
+ opts << "manual" if formula.manual?
256
+ opts << (installed ? "installed" : "uninstalled")
257
+ msg = " #{style.type} (#{opts.join(', ')})"
258
+
208
259
  if installed
209
- Fontist.ui.success(" #{style.type} (installed)")
260
+ Fontist.ui.success(msg)
210
261
  else
211
- Fontist.ui.error(" #{style.type} (uninstalled)")
262
+ Fontist.ui.error(msg)
212
263
  end
213
264
  end
214
265
  end
@@ -12,6 +12,16 @@ module Fontist
12
12
  # it depends on this exception to automatically download formulas
13
13
  class FormulaIndexNotFoundError < GeneralError; end
14
14
 
15
+ class FormulaNotFoundError < GeneralError
16
+ def initialize(formula)
17
+ super(<<~MSG.chomp)
18
+ Formula '#{formula}' not found locally nor available in the Fontist formula repository.
19
+ Perhaps it is available at the latest Fontist formula repository.
20
+ You can update the formula repository using the command `fontist update` and try again.
21
+ MSG
22
+ end
23
+ end
24
+
15
25
  class MainRepoNotFoundError < FormulaIndexNotFoundError; end
16
26
 
17
27
  class InvalidResourceError < GeneralError; end
@@ -28,6 +38,8 @@ module Fontist
28
38
 
29
39
  class RepoCouldNotBeUpdatedError < GeneralError; end
30
40
 
41
+ class SizeLimitError < GeneralError; end
42
+
31
43
  class TamperedFileError < GeneralError; end
32
44
 
33
45
  class TimeoutError < GeneralError; end
@@ -72,6 +84,14 @@ module Fontist
72
84
  end
73
85
  end
74
86
 
87
+ class ManualFontError < FontError
88
+ def initialize(font, formula)
89
+ msg = "'#{font}' font is missing.\n\n#{formula.instructions}"
90
+
91
+ super(msg, font)
92
+ end
93
+ end
94
+
75
95
  class UnsupportedFontError < FontError
76
96
  def initialize(font)
77
97
  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,11 @@ 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]
17
+ @by_formula = options[:formula]
12
18
 
13
19
  check_or_create_fontist_path!
14
20
  end
@@ -38,21 +44,27 @@ module Fontist
38
44
  end
39
45
 
40
46
  def find
41
- find_system_font || downloadable_font || raise_non_supported_font
47
+ find_system_font || downloadable_font || manual_font ||
48
+ raise_non_supported_font
42
49
  end
43
50
 
44
51
  def install
45
- (find_system_font unless @force) || download_font || raise_non_supported_font
52
+ return install_formula if @by_formula
53
+
54
+ (find_system_font unless @force) || download_font || manual_font ||
55
+ raise_non_supported_font
46
56
  end
47
57
 
48
58
  def uninstall
49
- uninstall_font || downloadable_font || raise_non_supported_font
59
+ uninstall_font || downloadable_font || manual_font ||
60
+ raise_non_supported_font
50
61
  end
51
62
 
52
63
  def status
53
64
  return installed_paths unless @name
54
65
 
55
- find_system_font || downloadable_font || raise_non_supported_font
66
+ find_system_font || downloadable_font || manual_font ||
67
+ raise_non_supported_font
56
68
  end
57
69
 
58
70
  def list
@@ -94,12 +106,42 @@ module Fontist
94
106
  end
95
107
  end
96
108
 
109
+ def install_formula
110
+ download_formula || raise_formula_not_found
111
+ end
112
+
113
+ def download_formula
114
+ formula = Formula.find_by_key(@name)
115
+ return unless formula
116
+ return unless formula.downloadable?
117
+
118
+ request_formula_installation(formula)
119
+ end
120
+
121
+ def raise_formula_not_found
122
+ raise Errors::FormulaNotFoundError.new(@name)
123
+ end
124
+
97
125
  def font_installer(formula)
98
126
  FontInstaller.new(formula, no_progress: @no_progress)
99
127
  end
100
128
 
101
- def formula
102
- @formula ||= formulas.first
129
+ def sufficient_formulas
130
+ @sufficient_formulas ||=
131
+ FormulaPicker.new(@name,
132
+ size_limit: @size_limit,
133
+ version: @version,
134
+ smallest: @smallest,
135
+ newest: @newest)
136
+ .call(downloadable_formulas)
137
+ end
138
+
139
+ def downloadable_formulas
140
+ @downloadable_formulas ||= formulas.select(&:downloadable?)
141
+ end
142
+
143
+ def manual_formulas
144
+ @manual_formulas ||= formulas.reject(&:downloadable?)
103
145
  end
104
146
 
105
147
  def formulas
@@ -108,27 +150,34 @@ module Fontist
108
150
  end
109
151
 
110
152
  def supported_formula?(formula)
111
- formula.platforms.nil? ||
112
- formula.platforms.include?(Fontist::Utils::System.user_os.to_s)
153
+ return true if formula.platforms.nil?
154
+
155
+ formula.platforms.any? do |platform|
156
+ Utils::System.match?(platform)
157
+ end
113
158
  end
114
159
 
115
160
  def downloadable_font
116
- if formula
117
- raise Fontist::Errors::MissingFontError.new(name)
118
- end
161
+ return if downloadable_formulas.empty?
162
+
163
+ raise Fontist::Errors::MissingFontError.new(name)
119
164
  end
120
165
 
121
166
  def download_font
122
- return if formulas.empty?
167
+ return if sufficient_formulas.empty?
123
168
 
124
- formulas.flat_map do |formula|
125
- confirmation = check_and_confirm_required_license(formula)
126
- paths = font_installer(formula).install(confirmation: confirmation)
169
+ sufficient_formulas.flat_map do |formula|
170
+ request_formula_installation(formula)
171
+ end
172
+ end
127
173
 
128
- Fontist.ui.say("Fonts installed at:")
129
- paths.each do |path|
130
- Fontist.ui.say("- #{path}")
131
- end
174
+ def request_formula_installation(formula)
175
+ confirmation = check_and_confirm_required_license(formula)
176
+ paths = font_installer(formula).install(confirmation: confirmation)
177
+
178
+ Fontist.ui.say("Fonts installed at:")
179
+ paths.each do |path|
180
+ Fontist.ui.say("- #{path}")
132
181
  end
133
182
  end
134
183
 
@@ -171,6 +220,12 @@ module Fontist
171
220
  MSG
172
221
  end
173
222
 
223
+ def manual_font
224
+ return if manual_formulas.empty?
225
+
226
+ raise Fontist::Errors::ManualFontError.new(name, manual_formulas.first)
227
+ end
228
+
174
229
  def uninstall_font
175
230
  paths = find_fontist_paths
176
231
  return unless paths
@@ -221,7 +276,7 @@ module Fontist
221
276
 
222
277
  def list_styles(formulas)
223
278
  map_to_hash(formulas) do |formula|
224
- map_to_hash(formula.fonts) do |font|
279
+ map_to_hash(requested_fonts(formula.fonts)) do |font|
225
280
  map_to_hash(font.styles) do |style|
226
281
  installed(style)
227
282
  end
@@ -233,6 +288,14 @@ module Fontist
233
288
  elements.map { |e| [e, yield(e)] }.to_h
234
289
  end
235
290
 
291
+ def requested_fonts(fonts)
292
+ return fonts unless @name
293
+
294
+ fonts.select do |font|
295
+ font.name.casecmp?(name)
296
+ end
297
+ end
298
+
236
299
  def installed(style)
237
300
  path(style) ? true : false
238
301
  end
@@ -45,6 +45,13 @@ module Fontist
45
45
  end.flatten
46
46
  end
47
47
 
48
+ def self.find_by_key(key)
49
+ path = Fontist.formulas_path.join("#{key}.yml")
50
+ return unless File.exist?(path)
51
+
52
+ new_from_file(path)
53
+ end
54
+
48
55
  def self.new_from_file(path)
49
56
  data = YAML.load_file(path)
50
57
  new(data, path)
@@ -59,12 +66,20 @@ module Fontist
59
66
  Indexes::IndexFormula.new(path)
60
67
  end
61
68
 
69
+ def manual?
70
+ !downloadable?
71
+ end
72
+
73
+ def downloadable?
74
+ @data.key?("resources")
75
+ end
76
+
62
77
  def path
63
78
  @path
64
79
  end
65
80
 
66
81
  def key
67
- @data["key"] || default_key
82
+ key_from_path
68
83
  end
69
84
 
70
85
  def description
@@ -99,12 +114,28 @@ module Fontist
99
114
  Helpers.parse_to_object(@data["extract"])
100
115
  end
101
116
 
117
+ def file_size
118
+ return unless @data["resources"]
119
+
120
+ @data["resources"].values.first["file_size"]&.to_i
121
+ end
122
+
102
123
  def resources
103
- Helpers.parse_to_object(@data["resources"].values)
124
+ Helpers.parse_to_object(@data["resources"]&.values)
125
+ end
126
+
127
+ def instructions
128
+ @data["instructions"]
129
+ end
130
+
131
+ def fonts_by_name(name)
132
+ fonts.select do |font|
133
+ font.name.casecmp?(name)
134
+ end
104
135
  end
105
136
 
106
137
  def fonts
107
- @fonts ||= Helpers.parse_to_object(hash_collection_fonts + hash_fonts)
138
+ @fonts ||= Helpers.parse_to_object(fonts_by_family)
108
139
  end
109
140
 
110
141
  def digest
@@ -113,11 +144,46 @@ module Fontist
113
144
 
114
145
  private
115
146
 
116
- def default_key
147
+ def key_from_path
117
148
  escaped = Regexp.escape(Fontist.formulas_path.to_s + "/")
118
149
  @path.sub(Regexp.new("^" + escaped), "").sub(/\.yml$/, "")
119
150
  end
120
151
 
152
+ def fonts_by_family
153
+ return hash_all_fonts unless Fontist.preferred_family?
154
+
155
+ preferred_family_fonts
156
+ end
157
+
158
+ def preferred_family_fonts
159
+ groups = preferred_family_styles.group_by do |style|
160
+ style["family_name"]
161
+ end
162
+
163
+ groups.map do |font_name, font_styles|
164
+ { "name" => font_name, "styles" => font_styles }
165
+ end
166
+ end
167
+
168
+ def preferred_family_styles
169
+ hash_all_fonts.flat_map do |font|
170
+ font["styles"].map do |style|
171
+ style.merge(preferred_style(style))
172
+ end
173
+ end
174
+ end
175
+
176
+ def preferred_style(style)
177
+ { "family_name" => style["preferred_family_name"] || style["family_name"],
178
+ "type" => style["preferred_type"] || style["type"],
179
+ "default_family_name" => style["family_name"],
180
+ "default_type" => style["type"] }
181
+ end
182
+
183
+ def hash_all_fonts
184
+ hash_collection_fonts + hash_fonts
185
+ end
186
+
121
187
  def hash_collection_fonts
122
188
  return [] unless @data["font_collections"]
123
189
 
@@ -126,8 +192,7 @@ module Fontist
126
192
  "source_font" => coll["source_filename"] }
127
193
 
128
194
  coll["fonts"].map do |font|
129
- { "name" => font["name"],
130
- "styles" => font["styles"].map { |s| filenames.merge(s) } }
195
+ font.merge("styles" => font["styles"].map { |s| filenames.merge(s) })
131
196
  end
132
197
  end
133
198
  end