fontist 2.0.2 → 2.0.4

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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +5 -1
  3. data/.rubocop_todo.yml +76 -0
  4. data/Gemfile +4 -3
  5. data/fontist.gemspec +9 -9
  6. data/lib/fontist/cli/thor_ext.rb +10 -2
  7. data/lib/fontist/cli.rb +38 -4
  8. data/lib/fontist/config.rb +4 -1
  9. data/lib/fontist/font.rb +1 -1
  10. data/lib/fontist/font_installer.rb +2 -2
  11. data/lib/fontist/font_model.rb +0 -1
  12. data/lib/fontist/helpers.rb +1 -1
  13. data/lib/fontist/import/convert_formulas.rb +1 -1
  14. data/lib/fontist/import/files/collection_file.rb +1 -1
  15. data/lib/fontist/import/formula_builder.rb +4 -4
  16. data/lib/fontist/import/formula_serializer.rb +2 -2
  17. data/lib/fontist/import/google.rb +2 -2
  18. data/lib/fontist/import/google_import.rb +1 -1
  19. data/lib/fontist/import/macos.rb +1 -1
  20. data/lib/fontist/import/otf/font_file.rb +3 -4
  21. data/lib/fontist/import/otf_parser.rb +1 -2
  22. data/lib/fontist/import/otfinfo/otfinfo_requirement.rb +3 -3
  23. data/lib/fontist/import/recursive_extraction.rb +3 -2
  24. data/lib/fontist/import/sil_import.rb +9 -4
  25. data/lib/fontist/import.rb +1 -1
  26. data/lib/fontist/indexes/default_family_font_index.rb +1 -0
  27. data/lib/fontist/indexes/filename_index.rb +1 -0
  28. data/lib/fontist/indexes/formula_key_to_path.rb +0 -1
  29. data/lib/fontist/indexes/index_mixin.rb +5 -3
  30. data/lib/fontist/indexes/preferred_family_font_index.rb +1 -0
  31. data/lib/fontist/manifest.rb +1 -1
  32. data/lib/fontist/repo.rb +1 -1
  33. data/lib/fontist/system_index.rb +31 -8
  34. data/lib/fontist/update.rb +1 -1
  35. data/lib/fontist/utils/downloader.rb +7 -5
  36. data/lib/fontist/utils/locking.rb +1 -1
  37. data/lib/fontist/version.rb +1 -1
  38. metadata +47 -45
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 579975f05c71659ca72914f2e273dead08930e5943f230fbc4ad5029d19b5bad
4
- data.tar.gz: c3529656ee99bbd27cd9b7c37025e79350c99ead6b5f222cb08773460b2e6feb
3
+ metadata.gz: c046b85f916e1f47e83f3746758d88b1c7cd326a0f68853cb1ac74df166c4733
4
+ data.tar.gz: b61d9a397e865391aff213ffb8a806dea2a8363c91fcb80342cf046e6df3a099
5
5
  SHA512:
6
- metadata.gz: 7cffa6efd591fc625aff86d71774ef70aff09b6c0fe9d5cb53f4ff0fff81a80fb76950701267ecfd8bea637a26e046a1ce698111226c8972049d86cd0110dd7a
7
- data.tar.gz: 8e0386ba63208db999567979f733521ff11b64b745bfd492436012761335a6a406b0fc0104176e05cecb283c4bd3924504e7668ab388a2937fd1596f6bfe8fa4
6
+ metadata.gz: 50077b4c82967138b4b208bbf7a068b40374870776fa0d3c82a8d3336c997ffa10f5eec09a527e53c5d6ac89ddba02ba3450749255b14daaefac324b6fa9ba50
7
+ data.tar.gz: 8a070a7a8d71125e3bbdf12b77414a82f8b3b30502616ce29fd7ecd7a442579dcf0f1a7a275d3e537cd93e0b5d370283b48f3cee3da710415033d25dc261059a
data/.rubocop.yml CHANGED
@@ -1,6 +1,10 @@
1
1
  inherit_from:
2
- - 'https://raw.githubusercontent.com/fontist/oss-guides/master/ci/rubocop.yml'
2
+ - .rubocop_todo.yml
3
+ - https://raw.githubusercontent.com/riboseinc/oss-guides/main/ci/rubocop.yml
3
4
 
4
5
  AllCops:
5
6
  TargetRubyVersion: 2.7
6
7
  SuggestExtensions: false
8
+
9
+ plugins:
10
+ - rubocop-performance
data/.rubocop_todo.yml ADDED
@@ -0,0 +1,76 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2025-11-09 10:17:46 UTC using RuboCop version 1.81.7.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 63
10
+ # This cop supports safe autocorrection (--autocorrect).
11
+ # Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, IgnoreCopDirectives, AllowedPatterns, SplitStrings.
12
+ # URISchemes: http, https
13
+ Layout/LineLength:
14
+ Enabled: false
15
+
16
+ # Offense count: 1
17
+ # Configuration parameters: IgnoreLiteralBranches, IgnoreConstantBranches, IgnoreDuplicateElseBranch.
18
+ Lint/DuplicateBranch:
19
+ Exclude:
20
+ - 'lib/fontist/helpers.rb'
21
+
22
+ # Offense count: 10
23
+ # Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
24
+ Metrics/AbcSize:
25
+ Exclude:
26
+ - 'lib/fontist/cli.rb'
27
+ - 'lib/fontist/font.rb'
28
+ - 'lib/fontist/import/google_fonts_importer.rb'
29
+ - 'lib/fontist/import/google_importer.rb'
30
+ - 'lib/fontist/import/otf_style.rb'
31
+ - 'lib/fontist/indexes/index_mixin.rb'
32
+ - 'lib/fontist/manifest_request.rb'
33
+ - 'lib/fontist/update.rb'
34
+ - 'test-transform.rb'
35
+
36
+ # Offense count: 4
37
+ # Configuration parameters: AllowedMethods, AllowedPatterns, Max.
38
+ Metrics/CyclomaticComplexity:
39
+ Exclude:
40
+ - 'lib/fontist/cli.rb'
41
+ - 'lib/fontist/import/google_importer.rb'
42
+ - 'spec/fontist/import/create_formula_spec.rb'
43
+ - 'test-transform.rb'
44
+
45
+ # Offense count: 23
46
+ # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
47
+ Metrics/MethodLength:
48
+ Max: 44
49
+
50
+ # Offense count: 4
51
+ # Configuration parameters: AllowedMethods, AllowedPatterns, Max.
52
+ Metrics/PerceivedComplexity:
53
+ Exclude:
54
+ - 'lib/fontist/cli.rb'
55
+ - 'lib/fontist/cli/thor_ext.rb'
56
+ - 'lib/fontist/import/google_importer.rb'
57
+ - 'test-transform.rb'
58
+
59
+ # Offense count: 1
60
+ # Configuration parameters: MinSize.
61
+ Performance/CollectionLiteralInLoop:
62
+ Exclude:
63
+ - 'lib/fontist/import/otf/font_file.rb'
64
+
65
+ # Offense count: 2
66
+ # This cop supports unsafe autocorrection (--autocorrect-all).
67
+ Style/IdenticalConditionalBranches:
68
+ Exclude:
69
+ - 'lib/fontist/helpers.rb'
70
+
71
+ # Offense count: 1
72
+ # This cop supports unsafe autocorrection (--autocorrect-all).
73
+ # Configuration parameters: Mode.
74
+ Style/StringConcatenation:
75
+ Exclude:
76
+ - 'spec/fontist/system_index_spec.rb'
data/Gemfile CHANGED
@@ -3,13 +3,14 @@ source "https://rubygems.org"
3
3
  # Specify your gem's dependencies in fontist.gemspec
4
4
  gemspec
5
5
 
6
- gem "pry"
7
6
  gem "bundler"
7
+ gem "pry"
8
8
  gem "rake"
9
9
  gem "rspec"
10
10
  gem "rspec-benchmark"
11
11
  gem "rubocop"
12
- gem "rubocop-rails"
13
12
  gem "rubocop-performance"
13
+ gem "rubocop-rails"
14
+ gem "rubocop-rake"
14
15
  gem "vcr"
15
- gem "webmock"
16
+ gem "webmock"
data/fontist.gemspec CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
8
8
  spec.authors = ["Ribose Inc."]
9
9
  spec.email = ["open.source@ribose.com"]
10
10
 
11
- spec.summary = %q{Install openly-licensed fonts on Windows, Linux and Mac!}
12
- spec.description = %q{Install openly-licensed fonts on Windows, Linux and Mac!}
11
+ spec.summary = "Install openly-licensed fonts on Windows, Linux and Mac!"
12
+ spec.description = "Install openly-licensed fonts on Windows, Linux and Mac!"
13
13
  spec.homepage = "https://github.com/fontist/fontist"
14
14
  spec.license = "BSD-2-Clause"
15
15
 
@@ -20,6 +20,7 @@ Gem::Specification.new do |spec|
20
20
  spec.metadata["homepage_uri"] = spec.homepage
21
21
  spec.metadata["source_code_uri"] = "https://github.com/fontist/fontist"
22
22
  spec.metadata["changelog_uri"] = "https://github.com/fontist/fontist"
23
+ spec.metadata["rubygems_mfa_required"] = "true"
23
24
 
24
25
  spec.require_paths = ["lib"]
25
26
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
@@ -27,20 +28,19 @@ Gem::Specification.new do |spec|
27
28
  end
28
29
  spec.bindir = "exe"
29
30
  spec.executables = ["fontist"]
30
- spec.test_files = `git ls-files -- {spec}/*`.split("\n")
31
31
 
32
32
  spec.add_dependency "down", "~> 5.0"
33
+ spec.add_dependency "excavate", "~> 0.3", ">= 0.3.8"
33
34
  spec.add_dependency "extract_ttc", "~> 0.3.7"
34
35
  spec.add_dependency "fuzzy_match", "~> 2.1"
36
+ spec.add_dependency "git", "~> 2.0"
35
37
  spec.add_dependency "json", "~> 2.0"
36
- spec.add_dependency "nokogiri", "~> 1.0"
38
+ spec.add_dependency "lutaml-model", "~> 0.7"
37
39
  spec.add_dependency "mime-types", "~> 3.0"
40
+ spec.add_dependency "nokogiri", "~> 1.0"
41
+ spec.add_dependency "plist", "~> 3.0"
42
+ spec.add_dependency "socksify", "~> 1.7"
38
43
  spec.add_dependency "sys-uname", "~> 1.2"
39
44
  spec.add_dependency "thor", "~> 1.4"
40
- spec.add_dependency "git", "~> 1.0"
41
45
  spec.add_dependency "ttfunk", "~> 1.6"
42
- spec.add_dependency "plist", "~> 3.0"
43
- spec.add_dependency "excavate", "~> 0.3", '>= 0.3.8'
44
- spec.add_dependency "socksify", "~> 1.7"
45
- spec.add_dependency "lutaml-model", "~> 0.7"
46
46
  end
@@ -37,7 +37,7 @@ module Fontist
37
37
 
38
38
  def start(given_args = ARGV, config = {})
39
39
  config[:shell] ||= Thor::Base.shell.new
40
- handle_help_switches(given_args) do |args|
40
+ handle_version_and_help_switches(given_args) do |args|
41
41
  dispatch(nil, args, nil, config)
42
42
  end
43
43
  rescue StandardError => e
@@ -47,7 +47,15 @@ module Fontist
47
47
  private
48
48
 
49
49
  # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
50
- def handle_help_switches(given_args)
50
+ def handle_version_and_help_switches(given_args)
51
+ # Handle version flags before Thor processes them
52
+ # Only intercept --version if it's used as a global flag (first arg or no command before it)
53
+ if given_args.include?("--version") &&
54
+ (given_args.first == "--version" || !given_args.first&.match?(/^[a-z]/))
55
+ yield(["version"])
56
+ return
57
+ end
58
+
51
59
  yield(given_args.dup)
52
60
  rescue Thor::UnknownArgumentError => e
53
61
  retry_with_args = []
data/lib/fontist/cli.rb CHANGED
@@ -63,6 +63,37 @@ module Fontist
63
63
  false
64
64
  end
65
65
 
66
+ desc "version", "Show fontist version"
67
+ def version
68
+ handle_class_options(options)
69
+ Fontist.ui.say("fontist: #{Fontist::VERSION}")
70
+
71
+ # Show formulas repository information if available
72
+ if Dir.exist?(Fontist.formulas_repo_path)
73
+ begin
74
+ require "git"
75
+ repo = Git.open(Fontist.formulas_repo_path)
76
+ repo_url = repo.config["remote.origin.url"] || Fontist.formulas_repo_url
77
+ branch = repo.current_branch
78
+ # Use execute.first for git gem ~> 4.0 compatibility
79
+ log_entry = repo.log(1).execute.first
80
+ revision = log_entry.sha[0..6]
81
+ updated = repo.gcommit(log_entry.sha).date.strftime("%Y-%m-%d")
82
+
83
+ Fontist.ui.say("formulas:")
84
+ Fontist.ui.say(" repo: #{repo_url}")
85
+ Fontist.ui.say(" version: #{Fontist.formulas_version}")
86
+ Fontist.ui.say(" branch: #{branch}")
87
+ Fontist.ui.say(" commit: #{revision}")
88
+ Fontist.ui.say(" updated: #{updated}")
89
+ rescue StandardError => e
90
+ Fontist.ui.debug("Could not read formulas repository info: #{e.message}")
91
+ end
92
+ end
93
+
94
+ STATUS_SUCCESS
95
+ end
96
+
66
97
  desc "install FONT", "Install font"
67
98
  option :force, type: :boolean, aliases: :f,
68
99
  desc: "Install even if already installed in system"
@@ -112,7 +143,10 @@ module Fontist
112
143
  def status(font = nil)
113
144
  handle_class_options(options)
114
145
  paths = Fontist::Font.status(font)
115
- return error("No font is installed.", STATUS_MISSING_FONT_ERROR) if paths.empty?
146
+ if paths.empty?
147
+ return error("No font is installed.",
148
+ STATUS_MISSING_FONT_ERROR)
149
+ end
116
150
 
117
151
  success
118
152
  rescue Fontist::Errors::GeneralError => e
@@ -175,11 +209,11 @@ module Fontist
175
209
  option :name, desc: "Example: Times New Roman"
176
210
  option :mirror, repeatable: true
177
211
  option :subdir, desc: "Subdirectory to take fonts from, starting with the " \
178
- "root dir, e.g.: stixfonts-2.10/fonts/static_otf. May include `fnmatch` patterns."
212
+ "root dir, e.g.: stixfonts-2.10/fonts/static_otf. May include `fnmatch` patterns."
179
213
  option :file_pattern, desc: "File pattern, e.g. '*.otf'. " \
180
- "Uses `fnmatch` patterns."
214
+ "Uses `fnmatch` patterns."
181
215
  option :name_prefix, desc: "Prefix to add to all font family names, " \
182
- "e.g. 'Wine ' for compatibility fonts"
216
+ "e.g. 'Wine ' for compatibility fonts"
183
217
  def create_formula(url)
184
218
  handle_class_options(options)
185
219
  require "fontist/import/create_formula"
@@ -103,7 +103,10 @@ module Fontist
103
103
  def persist
104
104
  config_model = self.class.new
105
105
  @custom_values.each do |key, value|
106
- config_model.send("#{key}=", value) if config_model.respond_to?("#{key}=")
106
+ if config_model.respond_to?("#{key}=")
107
+ config_model.send("#{key}=",
108
+ value)
109
+ end
107
110
  end
108
111
 
109
112
  FileUtils.mkdir_p(File.dirname(Fontist.config_path))
data/lib/fontist/font.rb CHANGED
@@ -343,7 +343,7 @@ module Fontist
343
343
  end
344
344
 
345
345
  def map_to_hash(elements)
346
- elements.map { |e| [e, yield(e)] }.to_h
346
+ elements.to_h { |e| [e, yield(e)] }
347
347
  end
348
348
 
349
349
  def requested_fonts(fonts)
@@ -107,11 +107,11 @@ module Fontist
107
107
  end
108
108
 
109
109
  def subdirectory_pattern
110
- @subdirectory_pattern ||= "*" + subdirectories.first.chomp("/") unless subdirectories.empty?
110
+ @subdirectory_pattern ||= "*#{subdirectories.first.chomp('/')}" unless subdirectories.empty?
111
111
  end
112
112
 
113
113
  def subdirectories
114
- @subdirectories ||= [@formula.extract].flatten.compact.map(&:options).compact.map(&:fonts_sub_dir).compact
114
+ @subdirectories ||= [@formula.extract].flatten.compact.filter_map(&:options).filter_map(&:fonts_sub_dir)
115
115
  end
116
116
 
117
117
  def install_font_file(source)
@@ -10,6 +10,5 @@ module Fontist
10
10
  map "name", to: :name
11
11
  map "styles", to: :styles
12
12
  end
13
-
14
13
  end
15
14
  end
@@ -21,7 +21,7 @@ module Fontist
21
21
 
22
22
  def self.silence_stream(stream)
23
23
  old_stream = stream.dup
24
- stream.reopen(RbConfig::CONFIG["host_os"] =~ /mswin|mingw/ ? "NUL:" : "/dev/null") # rubocop:disable Performance/RegexpMatch, Metrics/LineLength
24
+ stream.reopen(RbConfig::CONFIG["host_os"] =~ /mswin|mingw/ ? File::NULL : File::NULL) # rubocop:disable Performance/RegexpMatch, Layout/LineLength
25
25
  stream.sync = true
26
26
  yield
27
27
  ensure
@@ -54,7 +54,7 @@ module Fontist
54
54
  def yaml_formula_path(formula)
55
55
  name = formula_path(formula).match(/formulas\/(.*)_fonts?.rb/)[1]
56
56
 
57
- Fontist.formulas_path.join(name + ".yml")
57
+ Fontist.formulas_path.join("#{name}.yml")
58
58
  end
59
59
 
60
60
  def stringify_keys(hash)
@@ -16,7 +16,7 @@ module Fontist
16
16
  end
17
17
 
18
18
  def filename
19
- File.basename(@path, ".*") + "." + @extension
19
+ "#{File.basename(@path, '.*')}.#{@extension}"
20
20
  end
21
21
 
22
22
  def source_filename
@@ -24,7 +24,7 @@ module Fontist
24
24
  end
25
25
 
26
26
  def formula
27
- formula_attributes.map { |name| [name, send(name)] }.to_h.compact
27
+ formula_attributes.to_h { |name| [name, send(name)] }.compact
28
28
  end
29
29
 
30
30
  def save
@@ -87,7 +87,7 @@ module Fontist
87
87
  end
88
88
 
89
89
  def homepage
90
- @options[:homepage] || both_fonts.map(&:homepage).compact.first
90
+ @options[:homepage] || both_fonts.filter_map(&:homepage).first
91
91
  end
92
92
 
93
93
  def resources
@@ -138,11 +138,11 @@ module Fontist
138
138
  end
139
139
 
140
140
  def copyright
141
- both_fonts.map(&:copyright).compact.first
141
+ both_fonts.filter_map(&:copyright).first
142
142
  end
143
143
 
144
144
  def license_url
145
- both_fonts.map(&:license_url).compact.first
145
+ both_fonts.filter_map(&:license_url).first
146
146
  end
147
147
 
148
148
  def requires_license_agreement
@@ -103,7 +103,7 @@ module Fontist
103
103
  standalone.empty? ? nil : standalone
104
104
  end
105
105
 
106
- # rubocop:disable Metrics/MethodLength, Metrics/LineLength
106
+ # rubocop:disable Metrics/MethodLength, Layout/LineLength
107
107
  def extract_type(code)
108
108
  case code
109
109
  when /def extract.+exe_extract.+cab_extract.+ppviewer\.cab/m
@@ -119,7 +119,7 @@ module Fontist
119
119
  raise NotImplementedError, "Please implement an extract format"
120
120
  end
121
121
  end
122
- # rubocop:enable Metrics/MethodLength, Metrics/LineLength
122
+ # rubocop:enable Metrics/MethodLength, Layout/LineLength
123
123
 
124
124
  def requires_license_agreement(formula)
125
125
  formula.license if formula.license && formula.license_required?
@@ -14,13 +14,13 @@ module Fontist
14
14
  end
15
15
 
16
16
  def self.formula_path(name)
17
- filename = name.downcase.gsub(" ", "_") + ".yml"
17
+ filename = "#{name.downcase.gsub(' ', '_')}.yml"
18
18
  Fontist.formulas_path.join("google", filename)
19
19
  end
20
20
 
21
21
  def self.digest(path)
22
22
  checksums = Dir.glob(File.join(path,
23
- "*.{[t|T][t|T][f|F],[o|O][t|T][f|F],[t|T][t|T][c|C]}"))
23
+ "*.{[t|T][t|T][f|F],[o|O][t|T][f|F],[t|T][t|T][c|C]}"))
24
24
  .sort
25
25
  .map { |x| Digest::SHA256.file(x).to_s }
26
26
 
@@ -91,7 +91,7 @@ module Fontist
91
91
 
92
92
  def formula_dir
93
93
  @formula_dir ||= Fontist.formulas_path.join("google").tap do |path|
94
- FileUtils.mkdir_p(path) unless File.exist?(path)
94
+ FileUtils.mkdir_p(path)
95
95
  end
96
96
  end
97
97
 
@@ -60,7 +60,7 @@ module Fontist
60
60
 
61
61
  def formula_dir
62
62
  @formula_dir ||= Fontist.formulas_path.join("macos").tap do |path|
63
- FileUtils.mkdir_p(path) unless File.exist?(path)
63
+ FileUtils.mkdir_p(path)
64
64
  end
65
65
  end
66
66
  end
@@ -29,11 +29,11 @@ module Fontist
29
29
  end
30
30
 
31
31
  def to_style
32
- STYLE_ATTRIBUTES.map { |name| [name, send(name)] }.to_h.compact
32
+ STYLE_ATTRIBUTES.to_h { |name| [name, send(name)] }.compact
33
33
  end
34
34
 
35
35
  def to_collection_style
36
- COLLECTION_ATTRIBUTES.map { |name| [name, send(name)] }.to_h.compact
36
+ COLLECTION_ATTRIBUTES.to_h { |name| [name, send(name)] }.compact
37
37
  end
38
38
 
39
39
  def family_name
@@ -108,8 +108,7 @@ module Fontist
108
108
  .split("\n")
109
109
  .select { |x| x.include?(":") }
110
110
  .map { |x| x.split(":", 2) }
111
- .map { |x| x.map { |y| Fontist::Import::TextHelper.cleanup(y) } }
112
- .to_h
111
+ .to_h { |x| x.map { |y| Fontist::Import::TextHelper.cleanup(y) } }
113
112
  end
114
113
 
115
114
  def detect_extension
@@ -19,8 +19,7 @@ module Fontist
19
19
  text.split("\n")
20
20
  .select { |x| x.include?(":") }
21
21
  .map { |x| x.split(":", 2) }
22
- .map { |x| x.map { |y| Fontist::Import::TextHelper.cleanup(y) } }
23
- .to_h
22
+ .to_h { |x| x.map { |y| Fontist::Import::TextHelper.cleanup(y) } }
24
23
  end
25
24
  end
26
25
  end
@@ -7,9 +7,9 @@ module Fontist
7
7
  def initialize
8
8
  otfinfo_path = `which otfinfo`
9
9
  if otfinfo_path.empty?
10
- abort "otfinfo is not available. (Or is PATH not setup properly?)"\
11
- " You must install otfinfo."\
12
- " On macOS it can be installed via `brew install lcdf-typetools`."
10
+ abort "otfinfo is not available. (Or is PATH not setup properly?) " \
11
+ "You must install otfinfo. " \
12
+ "On macOS it can be installed via `brew install lcdf-typetools`."
13
13
  end
14
14
  end
15
15
 
@@ -84,7 +84,8 @@ module Fontist
84
84
  file = Otf::FontFile.new(path, name_prefix: @name_prefix)
85
85
  @font_files << file unless already_exist?(file)
86
86
  when :collection
87
- @collection_files << Files::CollectionFile.new(path, name_prefix: @name_prefix)
87
+ @collection_files << Files::CollectionFile.new(path,
88
+ name_prefix: @name_prefix)
88
89
  end
89
90
  end
90
91
 
@@ -112,7 +113,7 @@ module Fontist
112
113
  end
113
114
 
114
115
  def subdirectory_pattern
115
- @subdirectory_pattern ||= "*" + @subdir.chomp("/") if @subdir
116
+ @subdirectory_pattern ||= "*#{@subdir.chomp('/')}" if @subdir
116
117
  end
117
118
 
118
119
  def file_pattern?(path)
@@ -37,7 +37,8 @@ module Fontist
37
37
  end
38
38
 
39
39
  def create_formula_by_archive_url(url)
40
- path = Fontist::Import::CreateFormula.new(url, formula_dir: formula_dir).call
40
+ path = Fontist::Import::CreateFormula.new(url,
41
+ formula_dir: formula_dir).call
41
42
  Fontist.ui.success("Formula has been successfully created: #{path}")
42
43
 
43
44
  path
@@ -75,11 +76,15 @@ module Fontist
75
76
 
76
77
  def find_archive_link(document)
77
78
  links = document.css("a.btn-download")
78
- download_links = links.select { |tag| tag.content.include?("DOWNLOAD CURRENT VERSION") }
79
+ download_links = links.select do |tag|
80
+ tag.content.include?("DOWNLOAD CURRENT VERSION")
81
+ end
79
82
  return download_links.first unless download_links.empty?
80
83
 
81
84
  links = document.css("a")
82
- download_links = links.select { |tag| tag.content.match?(/Download.*\.zip/) }
85
+ download_links = links.select do |tag|
86
+ tag.content.match?(/Download.*\.zip/)
87
+ end
83
88
  download_links.first
84
89
  end
85
90
 
@@ -91,7 +96,7 @@ module Fontist
91
96
 
92
97
  def formula_dir
93
98
  @formula_dir ||= Fontist.formulas_path.join("sil").tap do |path|
94
- FileUtils.mkdir_p(path) unless File.exist?(path)
99
+ FileUtils.mkdir_p(path)
95
100
  end
96
101
  end
97
102
  end
@@ -2,7 +2,7 @@ module Fontist
2
2
  module Import
3
3
  class << self
4
4
  def name_to_filename(name)
5
- name.downcase.gsub(" ", "_") + ".yml"
5
+ "#{name.downcase.gsub(' ', '_')}.yml"
6
6
  end
7
7
  end
8
8
  end
@@ -19,6 +19,7 @@ module Fontist
19
19
  # - pclinuxos_webcore_fonts.yml
20
20
  class DefaultFamilyFontIndex < Lutaml::Model::Collection
21
21
  include IndexMixin
22
+
22
23
  instances :entries, FormulaKeyToPath
23
24
 
24
25
  key_value do
@@ -18,6 +18,7 @@ module Fontist
18
18
  # - adobe_reader_19.yml
19
19
  class FilenameIndex < Lutaml::Model::Collection
20
20
  include IndexMixin
21
+
21
22
  instances :entries, FormulaKeyToPath
22
23
 
23
24
  key_value do
@@ -1,4 +1,3 @@
1
-
2
1
  module Fontist
3
2
  module Indexes
4
3
  class FormulaKeyToPath < Lutaml::Model::Serializable
@@ -6,7 +6,7 @@ module Fontist
6
6
  end
7
7
 
8
8
  module ClassMethods
9
- def from_file(file_path = self.path)
9
+ def from_file(file_path = path)
10
10
  Fontist.ui.debug("Index: #{file_path}")
11
11
 
12
12
  Fontist.formulas_repo_path_exists!
@@ -16,7 +16,8 @@ module Fontist
16
16
  file_content = File.read(file_path).strip
17
17
 
18
18
  if file_content.empty?
19
- raise Fontist::Errors::FontIndexCorrupted, "Index file is empty: #{file_path}"
19
+ raise Fontist::Errors::FontIndexCorrupted,
20
+ "Index file is empty: #{file_path}"
20
21
  end
21
22
 
22
23
  from_yaml(file_content)
@@ -51,7 +52,8 @@ module Fontist
51
52
  end
52
53
 
53
54
  def index_key_for_style(_style)
54
- raise NotImplementedError, "index_key_for_style(style) must be implemented in including class"
55
+ raise NotImplementedError,
56
+ "index_key_for_style(style) must be implemented in including class"
55
57
  end
56
58
 
57
59
  def add_index_formula(style, formula_path)
@@ -19,6 +19,7 @@ module Fontist
19
19
  # - pclinuxos_webcore_fonts.yml
20
20
  class PreferredFamilyFontIndex < Lutaml::Model::Collection
21
21
  include IndexMixin
22
+
22
23
  instances :entries, FormulaKeyToPath
23
24
 
24
25
  key_value do
@@ -100,7 +100,7 @@ module Fontist
100
100
  def self.from_hash(data, options = {})
101
101
  locations = options.delete(:locations) || false
102
102
 
103
- model = super(data, options)
103
+ model = super
104
104
 
105
105
  model.to_response(locations: locations)
106
106
  end
data/lib/fontist/repo.rb CHANGED
@@ -75,7 +75,7 @@ module Fontist
75
75
  git.pull("origin", git.current_branch)
76
76
 
77
77
  Index.rebuild
78
- rescue Git::GitExecuteError => e
78
+ rescue Git::Error => e
79
79
  raise Errors::RepoCouldNotBeUpdatedError.new(<<~MSG.chomp)
80
80
  Formulas repo '#{name}' could not be updated.
81
81
  Please consider reinitializing it with:
@@ -78,9 +78,14 @@ module Fontist
78
78
  end
79
79
 
80
80
  def find(font, style)
81
- found_fonts = index.select do |file|
82
- file.family_name.casecmp?(font) &&
83
- (style.nil? || file.type.casecmp?(style))
81
+ current_fonts = index
82
+
83
+ if style.nil?
84
+ found_fonts = current_fonts.select { |file| file.family_name&.casecmp?(font) }
85
+ else
86
+ found_fonts = current_fonts.select do |file|
87
+ file.family_name&.casecmp?(font) && file.type&.casecmp?(style)
88
+ end
84
89
  end
85
90
 
86
91
  found_fonts.empty? ? nil : found_fonts
@@ -96,7 +101,12 @@ module Fontist
96
101
  end
97
102
 
98
103
  def index_changed?
99
- fonts.nil? || fonts.empty? || font_paths != (@paths_loader&.call || []).sort.uniq
104
+ return true if fonts.nil? || fonts.empty?
105
+
106
+ current_paths = (@paths_loader&.call&.sort&.uniq || [])
107
+ excluded_paths_in_current = current_paths.select { |path| excluded?(path) }
108
+
109
+ current_paths != (font_paths + excluded_paths_in_current).uniq.sort
100
110
  end
101
111
 
102
112
  def update
@@ -136,9 +146,14 @@ module Fontist
136
146
  end
137
147
 
138
148
  def detect_paths(paths)
139
- # paths are file paths to font files
149
+ existing_fonts_by_path = fonts&.group_by(&:path) || {}
150
+
140
151
  paths.sort.uniq.flat_map do |path|
141
- detect_fonts(path)
152
+ if existing_fonts_by_path[path]&.any?
153
+ existing_fonts_by_path[path]
154
+ else
155
+ detect_fonts(path)
156
+ end
142
157
  end.compact
143
158
  end
144
159
 
@@ -215,15 +230,23 @@ module Fontist
215
230
  include Utils::Locking
216
231
 
217
232
  def self.system_index
233
+ current_path = Fontist.system_index_path
234
+ return @system_index if !@system_index.nil? && @system_index_path == current_path
235
+
236
+ @system_index_path = current_path
218
237
  @system_index = SystemIndexFontCollection.from_file(
219
- path: Fontist.system_index_path,
238
+ path: current_path,
220
239
  paths_loader: -> { SystemFont.font_paths },
221
240
  )
222
241
  end
223
242
 
224
243
  def self.fontist_index
244
+ current_path = Fontist.fontist_index_path
245
+ return @fontist_index if !@fontist_index.nil? && @fontist_index_path == current_path
246
+
247
+ @fontist_index_path = current_path
225
248
  @fontist_index = SystemIndexFontCollection.from_file(
226
- path: Fontist.fontist_index_path,
249
+ path: current_path,
227
250
  paths_loader: -> { SystemFont.fontist_font_paths },
228
251
  )
229
252
  end
@@ -19,7 +19,7 @@ module Fontist
19
19
 
20
20
  def update_main_repo
21
21
  dir = File.dirname(Fontist.formulas_repo_path)
22
- FileUtils.mkdir_p(dir) unless File.exist?(dir)
22
+ FileUtils.mkdir_p(dir)
23
23
 
24
24
  unless Dir.exist?(Fontist.formulas_repo_path)
25
25
  return Git.clone(Fontist.formulas_repo_url,
@@ -94,9 +94,9 @@ module Fontist
94
94
  progress_bar.total = content_length
95
95
  end
96
96
  },
97
- progress_proc: -> (progress) {
97
+ progress_proc: ->(progress) {
98
98
  progress_bar.increment(progress)
99
- }
99
+ },
100
100
  )
101
101
  end
102
102
  # rubocop:enable Metrics/MethodLength
@@ -118,7 +118,7 @@ module Fontist
118
118
  class ProgressBar
119
119
  def initialize(total)
120
120
  @counter = 0
121
- @total = total
121
+ @total = total
122
122
  @printed_percent = -1
123
123
  @printed_size = -1
124
124
  @start = Time.now
@@ -137,7 +137,8 @@ module Fontist
137
137
  def finish
138
138
  print
139
139
 
140
- Fontist.ui.print(format(", %<mb_per_second>.2f MiB/s, done.\n", mb_per_second: mb_per_second))
140
+ Fontist.ui.print(format(", %<mb_per_second>.2f MiB/s, done.\n",
141
+ mb_per_second: mb_per_second))
141
142
  end
142
143
 
143
144
  private
@@ -204,7 +205,8 @@ module Fontist
204
205
  end
205
206
 
206
207
  def print_size
207
- Fontist.ui.print(format("\r\e[0KDownloading: %<downloaded>4d MiB", downloaded: counter_mb))
208
+ Fontist.ui.print(format("\r\e[0KDownloading: %<downloaded>4d MiB",
209
+ downloaded: counter_mb))
208
210
  end
209
211
 
210
212
  def mb_per_second
@@ -3,7 +3,7 @@ module Fontist
3
3
  module Locking
4
4
  def lock(lock_path)
5
5
  File.dirname(lock_path).tap do |dir|
6
- FileUtils.mkdir_p(dir) unless File.exist?(dir)
6
+ FileUtils.mkdir_p(dir)
7
7
  end
8
8
 
9
9
  f = File.open(lock_path, File::CREAT)
@@ -1,3 +1,3 @@
1
1
  module Fontist
2
- VERSION = "2.0.2".freeze
2
+ VERSION = "2.0.4".freeze
3
3
  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: 2.0.2
4
+ version: 2.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-11-18 00:00:00.000000000 Z
11
+ date: 2025-12-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: down
@@ -25,105 +25,111 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '5.0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: extract_ttc
28
+ name: excavate
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 0.3.7
33
+ version: '0.3'
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: 0.3.8
34
37
  type: :runtime
35
38
  prerelease: false
36
39
  version_requirements: !ruby/object:Gem::Requirement
37
40
  requirements:
38
41
  - - "~>"
39
42
  - !ruby/object:Gem::Version
40
- version: 0.3.7
43
+ version: '0.3'
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 0.3.8
41
47
  - !ruby/object:Gem::Dependency
42
- name: fuzzy_match
48
+ name: extract_ttc
43
49
  requirement: !ruby/object:Gem::Requirement
44
50
  requirements:
45
51
  - - "~>"
46
52
  - !ruby/object:Gem::Version
47
- version: '2.1'
53
+ version: 0.3.7
48
54
  type: :runtime
49
55
  prerelease: false
50
56
  version_requirements: !ruby/object:Gem::Requirement
51
57
  requirements:
52
58
  - - "~>"
53
59
  - !ruby/object:Gem::Version
54
- version: '2.1'
60
+ version: 0.3.7
55
61
  - !ruby/object:Gem::Dependency
56
- name: json
62
+ name: fuzzy_match
57
63
  requirement: !ruby/object:Gem::Requirement
58
64
  requirements:
59
65
  - - "~>"
60
66
  - !ruby/object:Gem::Version
61
- version: '2.0'
67
+ version: '2.1'
62
68
  type: :runtime
63
69
  prerelease: false
64
70
  version_requirements: !ruby/object:Gem::Requirement
65
71
  requirements:
66
72
  - - "~>"
67
73
  - !ruby/object:Gem::Version
68
- version: '2.0'
74
+ version: '2.1'
69
75
  - !ruby/object:Gem::Dependency
70
- name: nokogiri
76
+ name: git
71
77
  requirement: !ruby/object:Gem::Requirement
72
78
  requirements:
73
79
  - - "~>"
74
80
  - !ruby/object:Gem::Version
75
- version: '1.0'
81
+ version: '2.0'
76
82
  type: :runtime
77
83
  prerelease: false
78
84
  version_requirements: !ruby/object:Gem::Requirement
79
85
  requirements:
80
86
  - - "~>"
81
87
  - !ruby/object:Gem::Version
82
- version: '1.0'
88
+ version: '2.0'
83
89
  - !ruby/object:Gem::Dependency
84
- name: mime-types
90
+ name: json
85
91
  requirement: !ruby/object:Gem::Requirement
86
92
  requirements:
87
93
  - - "~>"
88
94
  - !ruby/object:Gem::Version
89
- version: '3.0'
95
+ version: '2.0'
90
96
  type: :runtime
91
97
  prerelease: false
92
98
  version_requirements: !ruby/object:Gem::Requirement
93
99
  requirements:
94
100
  - - "~>"
95
101
  - !ruby/object:Gem::Version
96
- version: '3.0'
102
+ version: '2.0'
97
103
  - !ruby/object:Gem::Dependency
98
- name: sys-uname
104
+ name: lutaml-model
99
105
  requirement: !ruby/object:Gem::Requirement
100
106
  requirements:
101
107
  - - "~>"
102
108
  - !ruby/object:Gem::Version
103
- version: '1.2'
109
+ version: '0.7'
104
110
  type: :runtime
105
111
  prerelease: false
106
112
  version_requirements: !ruby/object:Gem::Requirement
107
113
  requirements:
108
114
  - - "~>"
109
115
  - !ruby/object:Gem::Version
110
- version: '1.2'
116
+ version: '0.7'
111
117
  - !ruby/object:Gem::Dependency
112
- name: thor
118
+ name: mime-types
113
119
  requirement: !ruby/object:Gem::Requirement
114
120
  requirements:
115
121
  - - "~>"
116
122
  - !ruby/object:Gem::Version
117
- version: '1.4'
123
+ version: '3.0'
118
124
  type: :runtime
119
125
  prerelease: false
120
126
  version_requirements: !ruby/object:Gem::Requirement
121
127
  requirements:
122
128
  - - "~>"
123
129
  - !ruby/object:Gem::Version
124
- version: '1.4'
130
+ version: '3.0'
125
131
  - !ruby/object:Gem::Dependency
126
- name: git
132
+ name: nokogiri
127
133
  requirement: !ruby/object:Gem::Requirement
128
134
  requirements:
129
135
  - - "~>"
@@ -137,81 +143,75 @@ dependencies:
137
143
  - !ruby/object:Gem::Version
138
144
  version: '1.0'
139
145
  - !ruby/object:Gem::Dependency
140
- name: ttfunk
146
+ name: plist
141
147
  requirement: !ruby/object:Gem::Requirement
142
148
  requirements:
143
149
  - - "~>"
144
150
  - !ruby/object:Gem::Version
145
- version: '1.6'
151
+ version: '3.0'
146
152
  type: :runtime
147
153
  prerelease: false
148
154
  version_requirements: !ruby/object:Gem::Requirement
149
155
  requirements:
150
156
  - - "~>"
151
157
  - !ruby/object:Gem::Version
152
- version: '1.6'
158
+ version: '3.0'
153
159
  - !ruby/object:Gem::Dependency
154
- name: plist
160
+ name: socksify
155
161
  requirement: !ruby/object:Gem::Requirement
156
162
  requirements:
157
163
  - - "~>"
158
164
  - !ruby/object:Gem::Version
159
- version: '3.0'
165
+ version: '1.7'
160
166
  type: :runtime
161
167
  prerelease: false
162
168
  version_requirements: !ruby/object:Gem::Requirement
163
169
  requirements:
164
170
  - - "~>"
165
171
  - !ruby/object:Gem::Version
166
- version: '3.0'
172
+ version: '1.7'
167
173
  - !ruby/object:Gem::Dependency
168
- name: excavate
174
+ name: sys-uname
169
175
  requirement: !ruby/object:Gem::Requirement
170
176
  requirements:
171
177
  - - "~>"
172
178
  - !ruby/object:Gem::Version
173
- version: '0.3'
174
- - - ">="
175
- - !ruby/object:Gem::Version
176
- version: 0.3.8
179
+ version: '1.2'
177
180
  type: :runtime
178
181
  prerelease: false
179
182
  version_requirements: !ruby/object:Gem::Requirement
180
183
  requirements:
181
184
  - - "~>"
182
185
  - !ruby/object:Gem::Version
183
- version: '0.3'
184
- - - ">="
185
- - !ruby/object:Gem::Version
186
- version: 0.3.8
186
+ version: '1.2'
187
187
  - !ruby/object:Gem::Dependency
188
- name: socksify
188
+ name: thor
189
189
  requirement: !ruby/object:Gem::Requirement
190
190
  requirements:
191
191
  - - "~>"
192
192
  - !ruby/object:Gem::Version
193
- version: '1.7'
193
+ version: '1.4'
194
194
  type: :runtime
195
195
  prerelease: false
196
196
  version_requirements: !ruby/object:Gem::Requirement
197
197
  requirements:
198
198
  - - "~>"
199
199
  - !ruby/object:Gem::Version
200
- version: '1.7'
200
+ version: '1.4'
201
201
  - !ruby/object:Gem::Dependency
202
- name: lutaml-model
202
+ name: ttfunk
203
203
  requirement: !ruby/object:Gem::Requirement
204
204
  requirements:
205
205
  - - "~>"
206
206
  - !ruby/object:Gem::Version
207
- version: '0.7'
207
+ version: '1.6'
208
208
  type: :runtime
209
209
  prerelease: false
210
210
  version_requirements: !ruby/object:Gem::Requirement
211
211
  requirements:
212
212
  - - "~>"
213
213
  - !ruby/object:Gem::Version
214
- version: '0.7'
214
+ version: '1.6'
215
215
  description: Install openly-licensed fonts on Windows, Linux and Mac!
216
216
  email:
217
217
  - open.source@ribose.com
@@ -230,6 +230,7 @@ files:
230
230
  - ".hound.yml"
231
231
  - ".rspec"
232
232
  - ".rubocop.yml"
233
+ - ".rubocop_todo.yml"
233
234
  - Gemfile
234
235
  - LICENSE.txt
235
236
  - README.adoc
@@ -339,6 +340,7 @@ metadata:
339
340
  homepage_uri: https://github.com/fontist/fontist
340
341
  source_code_uri: https://github.com/fontist/fontist
341
342
  changelog_uri: https://github.com/fontist/fontist
343
+ rubygems_mfa_required: 'true'
342
344
  post_install_message: Please run `fontist update` to fetch formulas.
343
345
  rdoc_options: []
344
346
  require_paths: