fontist 1.8.1 → 1.8.6

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 (40) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/rspec.yml +2 -2
  3. data/README.md +14 -0
  4. data/fontist.gemspec +7 -5
  5. data/lib/fontist.rb +4 -0
  6. data/lib/fontist/cli.rb +22 -24
  7. data/lib/fontist/errors.rb +51 -2
  8. data/lib/fontist/font.rb +33 -54
  9. data/lib/fontist/font_installer.rb +4 -0
  10. data/lib/fontist/font_path.rb +29 -0
  11. data/lib/fontist/formula.rb +4 -4
  12. data/lib/fontist/import/create_formula.rb +3 -2
  13. data/lib/fontist/import/extractors.rb +4 -0
  14. data/lib/fontist/import/extractors/cpio_extractor.rb +39 -0
  15. data/lib/fontist/import/extractors/gzip_extractor.rb +27 -0
  16. data/lib/fontist/import/extractors/rpm_extractor.rb +45 -0
  17. data/lib/fontist/import/extractors/tar_extractor.rb +47 -0
  18. data/lib/fontist/import/google/skiplist.yml +3 -0
  19. data/lib/fontist/import/recursive_extraction.rb +21 -7
  20. data/lib/fontist/import/sil_import.rb +99 -0
  21. data/lib/fontist/index.rb +4 -65
  22. data/lib/fontist/indexes/base_index.rb +82 -0
  23. data/lib/fontist/indexes/filename_index.rb +19 -0
  24. data/lib/fontist/indexes/font_index.rb +21 -0
  25. data/lib/fontist/indexes/index_formula.rb +36 -0
  26. data/lib/fontist/manifest/install.rb +3 -2
  27. data/lib/fontist/manifest/locations.rb +1 -1
  28. data/lib/fontist/system_font.rb +33 -36
  29. data/lib/fontist/system_index.rb +46 -4
  30. data/lib/fontist/utils.rb +5 -0
  31. data/lib/fontist/utils/cache.rb +12 -4
  32. data/lib/fontist/utils/cpio/cpio.rb +199 -0
  33. data/lib/fontist/utils/cpio_extractor.rb +47 -0
  34. data/lib/fontist/utils/gzip_extractor.rb +24 -0
  35. data/lib/fontist/utils/locking.rb +17 -0
  36. data/lib/fontist/utils/rpm_extractor.rb +37 -0
  37. data/lib/fontist/utils/tar_extractor.rb +61 -0
  38. data/lib/fontist/version.rb +1 -1
  39. metadata +53 -13
  40. data/lib/fontist/index_formula.rb +0 -30
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 0d083618f330800ccb94e30d93fa8b5bf65d5e0a
4
- data.tar.gz: 133e64a85156c8fa5dcfc284ef57b3047fdbec0e
2
+ SHA256:
3
+ metadata.gz: d13c412a0a68cdcf1845948c2f3b96c45187dc27193bae4a581d2ee1f3324201
4
+ data.tar.gz: ed82b44bfc05274b749e4c4b2f2ace5e4ae115343c6ca9f99ac4fc552d71147f
5
5
  SHA512:
6
- metadata.gz: f5a33afe8b4157afadbaa8530e39de7a0b51222904101c396668e6e5d030fc51f6895f9f60478d9a32dc46af1bda7f1cef1aff0f27e2bc10bc3ae0e7b661d71f
7
- data.tar.gz: 3b1d0e38e2b42cf5e24f568cec75a34666ff7b3a98b36b673969365a4ec87b4add38b5fe3dac79a16871596d19b9454eac9fd6ada0097764a26af364f7fd5fee
6
+ metadata.gz: d8a08b20f1b2409b34749ad4f4531e2c727b3e39fa9e3b015d564d6ec14365dd9aa43274aa337845b72e4072bfcad50fe26412a69b805e7c83139934b009a6d6
7
+ data.tar.gz: bb20f38a5c4c4e9714dc69b15f249636e10c76942359e10ac38dc08d98eac3cfc1c6efe879bc9e13596d38872bae75c4721ce6d3892e1ca2726bbe7f9cb50b41
@@ -37,8 +37,8 @@ jobs:
37
37
  - uses: actions/cache@v1
38
38
  with:
39
39
  path: vendor/bundle
40
- key: bundle-${{ matrix.os }}-${{ matrix.ruby }}-${{ hashFiles('**/*.gemspec') }}
41
- restore-keys: bundle-${{ matrix.os }}-${{ matrix.ruby }}
40
+ key: bundle-v2-${{ matrix.os }}-${{ matrix.ruby }}-${{ hashFiles('**/*.gemspec') }}
41
+ restore-keys: bundle-v2-${{ matrix.os }}-${{ matrix.ruby }}
42
42
 
43
43
  - if: matrix.os == 'macos-latest'
44
44
  run: brew install lcdf-typetools
data/README.md CHANGED
@@ -434,6 +434,20 @@ git commit -m "Google Fonts update"
434
434
  git push
435
435
  ```
436
436
 
437
+ ### Import of SIL fonts
438
+
439
+ Fontist contains formulas of [SIL fonts](https://software.sil.org/fonts/). They
440
+ can be updated with:
441
+
442
+ ```sh
443
+ fontist import-sil
444
+ cd ~/.fontist/formulas
445
+ git add Formulas/sil
446
+ git add index.yml
447
+ git commit -m "SIL fonts update"
448
+ git push
449
+ ```
450
+
437
451
  ### Releasing
438
452
 
439
453
  Releasing is done automatically with GitHub Action. Just bump and tag with `gem-release`.
data/fontist.gemspec CHANGED
@@ -5,15 +5,15 @@ require "fontist/version"
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "fontist"
7
7
  spec.version = Fontist::VERSION
8
- spec.authors = ["Ribose Inc.", "Abu Nashir"]
9
- spec.email = ["operations@ribose.com", "abunashir@gmail.com"]
8
+ spec.authors = ["Ribose Inc."]
9
+ spec.email = ["open.source@ribose.com"]
10
10
 
11
- spec.summary = %q{A libarary find or download fonts}
12
- spec.description = %q{A libarary find or download fonts}
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!}
13
13
  spec.homepage = "https://github.com/fontist/fontist"
14
14
  spec.license = "BSD-2-Clause"
15
15
 
16
- spec.post_install_message = "Please run `fontist update` to fetch formulas"
16
+ spec.post_install_message = "Please run `fontist update` to fetch formulas."
17
17
 
18
18
  spec.metadata["homepage_uri"] = spec.homepage
19
19
  spec.metadata["source_code_uri"] = "https://github.com/fontist/fontist"
@@ -27,6 +27,7 @@ Gem::Specification.new do |spec|
27
27
  spec.executables = ["fontist"]
28
28
  spec.test_files = `git ls-files -- {spec}/*`.split("\n")
29
29
 
30
+ spec.add_runtime_dependency "arr-pm", "~> 0.0.1"
30
31
  spec.add_runtime_dependency "down", "~> 5.0"
31
32
  spec.add_runtime_dependency "libmspack", "~> 0.1.0"
32
33
  spec.add_runtime_dependency "rubyzip", "~> 2.3.0"
@@ -40,6 +41,7 @@ Gem::Specification.new do |spec|
40
41
  spec.add_development_dependency "pry"
41
42
  spec.add_development_dependency "bundler", "~> 2.0"
42
43
  spec.add_development_dependency "gem-release"
44
+ spec.add_development_dependency "nokogiri", "~> 1.0"
43
45
  spec.add_development_dependency "rake", "~> 12.3.3"
44
46
  spec.add_development_dependency "rspec", "~> 3.0"
45
47
  spec.add_development_dependency "rubocop", "0.75.0"
data/lib/fontist.rb CHANGED
@@ -62,4 +62,8 @@ module Fontist
62
62
  def self.formula_index_path
63
63
  Fontist.formulas_repo_path.join("index.yml")
64
64
  end
65
+
66
+ def self.formula_filename_index_path
67
+ Fontist.formulas_repo_path.join("filename_index.yml")
68
+ end
65
69
  end
data/lib/fontist/cli.rb CHANGED
@@ -9,15 +9,17 @@ module Fontist
9
9
  STATUS_LICENSING_ERROR = 4
10
10
  STATUS_MANIFEST_COULD_NOT_BE_FOUND_ERROR = 5
11
11
  STATUS_MANIFEST_COULD_NOT_BE_READ_ERROR = 6
12
+ STATUS_FONT_INDEX_CORRUPTED = 7
12
13
 
13
14
  ERROR_TO_STATUS = {
14
- Fontist::Errors::NonSupportedFontError => [STATUS_NON_SUPPORTED_FONT_ERROR],
15
+ Fontist::Errors::UnsupportedFontError => [STATUS_NON_SUPPORTED_FONT_ERROR],
15
16
  Fontist::Errors::MissingFontError => [STATUS_MISSING_FONT_ERROR],
16
17
  Fontist::Errors::LicensingError => [STATUS_LICENSING_ERROR],
17
18
  Fontist::Errors::ManifestCouldNotBeFoundError => [STATUS_MANIFEST_COULD_NOT_BE_FOUND_ERROR,
18
19
  "Manifest could not be found."],
19
20
  Fontist::Errors::ManifestCouldNotBeReadError => [STATUS_MANIFEST_COULD_NOT_BE_READ_ERROR,
20
21
  "Manifest could not be read."],
22
+ Fontist::Errors::FontIndexCorrupted => [STATUS_FONT_INDEX_CORRUPTED],
21
23
  }.freeze
22
24
 
23
25
  def self.exit_on_failure?
@@ -27,12 +29,14 @@ module Fontist
27
29
  desc "install FONT", "Install font"
28
30
  option :force, type: :boolean, aliases: :f,
29
31
  desc: "Install even if it's already installed in system"
30
- option :confirm_license, type: :boolean, desc: "Confirm license agreement"
32
+ option :accept_all_licenses, type: :boolean, aliases: "--confirm-license", desc: "Accept all license agreements"
33
+ option :hide_licenses, type: :boolean, desc: "Hide license texts"
31
34
  def install(font)
32
35
  Fontist::Font.install(
33
36
  font,
34
37
  force: options[:force],
35
- confirmation: options[:confirm_license] ? "yes" : "no"
38
+ confirmation: options[:accept_all_licenses] ? "yes" : "no",
39
+ hide_licenses: options[:hide_licenses]
36
40
  )
37
41
  success
38
42
  rescue Fontist::Errors::GeneralError => e
@@ -50,12 +54,11 @@ module Fontist
50
54
  end
51
55
  map remove: :uninstall
52
56
 
53
- desc "status [FONT]", "Show status of FONT or all fonts in fontist"
57
+ desc "status [FONT]", "Show paths of FONT or all fonts"
54
58
  def status(font = nil)
55
- formulas = Fontist::Font.status(font)
56
- return error("No font is installed.", STATUS_MISSING_FONT_ERROR) if formulas.empty?
59
+ paths = Fontist::Font.status(font)
60
+ return error("No font is installed.", STATUS_MISSING_FONT_ERROR) if paths.empty?
57
61
 
58
- print_formulas(formulas)
59
62
  success
60
63
  rescue Fontist::Errors::GeneralError => e
61
64
  handle_error(e)
@@ -88,11 +91,13 @@ module Fontist
88
91
  end
89
92
 
90
93
  desc "manifest-install MANIFEST", "Install fonts from MANIFEST (yaml)"
91
- option :confirm_license, type: :boolean, desc: "Confirm license agreement"
94
+ option :accept_all_licenses, type: :boolean, aliases: "--confirm-license", desc: "Accept all license agreements"
95
+ option :hide_licenses, type: :boolean, desc: "Hide license texts"
92
96
  def manifest_install(manifest)
93
97
  paths = Fontist::Manifest::Install.from_file(
94
98
  manifest,
95
- confirmation: options[:confirm_license] ? "yes" : "no"
99
+ confirmation: options[:accept_all_licenses] ? "yes" : "no",
100
+ hide_licenses: options[:hide_licenses]
96
101
  )
97
102
 
98
103
  print_yaml(paths)
@@ -105,7 +110,8 @@ module Fontist
105
110
  option :name, desc: "Example: Times New Roman"
106
111
  option :mirror, repeatable: true
107
112
  option :subarchive, desc: "Subarchive to choose when there are several ones"
108
- option :subdir, desc: "Subdirectory to take fonts from"
113
+ option :subdir, desc: "Subdirectory to take fonts from, starting with the " \
114
+ "root dir, e.g.: stixfonts-2.10/fonts/static_otf. May include `fnmatch` patterns."
109
115
  def create_formula(url)
110
116
  require "fontist/import/create_formula"
111
117
  name = Fontist::Import::CreateFormula.new(url, options).call
@@ -124,6 +130,12 @@ module Fontist
124
130
  STATUS_SUCCESS
125
131
  end
126
132
 
133
+ desc "import-sil", "Import formulas from SIL"
134
+ def import_sil
135
+ require "fontist/import/sil_import"
136
+ Fontist::Import::SilImport.new.call
137
+ end
138
+
127
139
  private
128
140
 
129
141
  def success
@@ -146,20 +158,6 @@ module Fontist
146
158
  Fontist.ui.say(YAML.dump(object))
147
159
  end
148
160
 
149
- def print_formulas(formulas)
150
- formulas.each do |formula, fonts|
151
- Fontist.ui.success(formula.key)
152
-
153
- fonts.each do |font, styles|
154
- Fontist.ui.success(" #{font.name}")
155
-
156
- styles.each do |style, path|
157
- Fontist.ui.success(" #{style.type} (#{path})")
158
- end
159
- end
160
- end
161
- end
162
-
163
161
  # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
164
162
  def print_list(formulas)
165
163
  formulas.each do |formula, fonts|
@@ -1,7 +1,9 @@
1
1
  module Fontist
2
2
  module Errors
3
3
  class GeneralError < StandardError; end
4
+
4
5
  class BinaryCallError < GeneralError; end
6
+ class FontIndexCorrupted < GeneralError; end
5
7
  class FontNotFoundError < GeneralError; end
6
8
  class FormulaIndexNotFoundError < GeneralError; end
7
9
  class InvalidResourceError < GeneralError; end
@@ -9,10 +11,57 @@ module Fontist
9
11
  class ManifestCouldNotBeFoundError < GeneralError; end
10
12
  class ManifestCouldNotBeReadError < GeneralError; end
11
13
  class MissingAttributeError < GeneralError; end
12
- class MissingFontError < GeneralError; end
13
- class NonSupportedFontError < GeneralError; end
14
14
  class TamperedFileError < GeneralError; end
15
15
  class TimeoutError < GeneralError; end
16
16
  class UnknownFontTypeError < GeneralError; end
17
+ class UnknownArchiveError < GeneralError; end
18
+
19
+ class FontError < GeneralError
20
+ attr_reader :font, :style
21
+
22
+ def initialize(msg, font = nil, style = nil)
23
+ @font = font
24
+ @style = style
25
+
26
+ super(msg)
27
+ end
28
+
29
+ def name
30
+ messages = []
31
+ messages << "Font name: '#{@font}'"
32
+ messages << "Style: '#{@style}'" if @style
33
+ messages.join("; ")
34
+ end
35
+ end
36
+
37
+ class MissingFontError < FontError
38
+ def initialize(font, style = nil)
39
+ name = prepare_name(font, style)
40
+ msg = "#{name} font is missing, please run `fontist install '#{font}'` to download the font."
41
+
42
+ super(msg, font, style)
43
+ end
44
+
45
+ private
46
+
47
+ def prepare_name(font, style)
48
+ names = []
49
+ names << "'#{font}'"
50
+ names << "'#{style}'" if style
51
+ names.join(" ")
52
+ end
53
+ end
54
+
55
+ class UnsupportedFontError < FontError
56
+ def initialize(font)
57
+ msg = <<~MSG.chomp
58
+ Font '#{font}' not found locally nor available in the Fontist formula repository.
59
+ Perhaps it is available at the latest Fontist formula repository.
60
+ You can update the formula repository using the command `fontist update` and try again.
61
+ MSG
62
+
63
+ super(msg, font)
64
+ end
65
+ end
17
66
  end
18
67
  end
data/lib/fontist/font.rb CHANGED
@@ -1,11 +1,13 @@
1
1
  require "fontist/font_installer"
2
+ require "fontist/font_path"
2
3
 
3
4
  module Fontist
4
5
  class Font
5
6
  def initialize(options = {})
6
- @name = options.fetch(:name, nil)
7
- @confirmation = options.fetch(:confirmation, "no")
8
- @force = options.fetch(:force, false)
7
+ @name = options[:name]
8
+ @confirmation = options[:confirmation] || "no"
9
+ @hide_licenses = options[:hide_licenses]
10
+ @force = options[:force] || false
9
11
 
10
12
  check_or_create_fontist_path!
11
13
  end
@@ -18,8 +20,8 @@ module Fontist
18
20
  new(name: name).find
19
21
  end
20
22
 
21
- def self.install(name, confirmation: "no", force: false)
22
- new(name: name, confirmation: confirmation, force: force).install
23
+ def self.install(name, options = {})
24
+ new(options.merge(name: name)).install
23
25
  end
24
26
 
25
27
  def self.uninstall(name)
@@ -47,9 +49,9 @@ module Fontist
47
49
  end
48
50
 
49
51
  def status
50
- return installed_statuses unless @name
52
+ return installed_paths unless @name
51
53
 
52
- font_status || downloadable_font || raise_non_supported_font
54
+ find_system_font || downloadable_font || raise_non_supported_font
53
55
  end
54
56
 
55
57
  def list
@@ -73,9 +75,14 @@ module Fontist
73
75
  return
74
76
  end
75
77
 
78
+ print_paths(paths)
79
+ end
80
+
81
+ def print_paths(paths)
76
82
  Fontist.ui.say("Fonts found at:")
77
83
  paths.each do |path|
78
- Fontist.ui.say("- #{path}")
84
+ font_path = FontPath.new(path)
85
+ Fontist.ui.say(font_path.to_s)
79
86
  end
80
87
  end
81
88
 
@@ -96,12 +103,7 @@ module Fontist
96
103
 
97
104
  def downloadable_font
98
105
  if formula
99
- raise(
100
- Fontist::Errors::MissingFontError,
101
- "#{name} fonts are missing, please run " \
102
- "`fontist install '#{name}'` to " \
103
- "download the font."
104
- )
106
+ raise Fontist::Errors::MissingFontError.new(name)
105
107
  end
106
108
  end
107
109
 
@@ -118,19 +120,26 @@ module Fontist
118
120
  end
119
121
 
120
122
  def check_and_confirm_required_license(formula)
121
- if formula.license_required && !confirmation.casecmp("yes").zero?
122
- @confirmation = show_license_and_ask_for_input(formula.license)
123
+ if formula.license_required
124
+ show_license(formula.license) unless @hide_licenses
123
125
 
124
- if !confirmation.casecmp("yes").zero?
125
- raise Fontist::Errors::LicensingError.new(
126
- "Fontist will not download these fonts unless you accept the terms."
127
- )
126
+ unless confirmation.casecmp?("yes")
127
+ @confirmation = ask_for_agreement
128
+
129
+ unless confirmation&.casecmp?("yes")
130
+ raise Fontist::Errors::LicensingError.new(
131
+ "Fontist will not download these fonts unless you accept the terms."
132
+ )
133
+ end
128
134
  end
129
135
  end
130
136
  end
131
137
 
132
- def show_license_and_ask_for_input(license)
138
+ def show_license(license)
133
139
  Fontist.ui.say(license_agrement_message(license))
140
+ end
141
+
142
+ def ask_for_agreement
134
143
  Fontist.ui.ask(
135
144
  "\nDo you accept all presented font licenses, and want Fontist " \
136
145
  "to download these fonts for you? => TYPE 'Yes' or 'No':"
@@ -166,37 +175,14 @@ module Fontist
166
175
  Fontist::FontistFont.find(name)
167
176
  end
168
177
 
169
- def installed_statuses
170
- installed_styles(all_formulas)
178
+ def installed_paths
179
+ print_paths(SystemFont.font_paths)
171
180
  end
172
181
 
173
182
  def all_formulas
174
183
  Fontist::Formula.all
175
184
  end
176
185
 
177
- def font_status
178
- return unless formula
179
-
180
- statuses = installed_styles([formula])
181
- statuses.empty? ? nil : statuses
182
- end
183
-
184
- def installed_styles(formulas)
185
- filter_blank(formulas) do |formula|
186
- filter_blank(formula.fonts) do |font|
187
- filter_blank(font.styles) do |style|
188
- path(style)
189
- end
190
- end
191
- end
192
- end
193
-
194
- def filter_blank(elements)
195
- elements.map { |e| [e, yield(e)] }
196
- .to_h
197
- .reject { |_k, v| v.nil? || v.empty? }
198
- end
199
-
200
186
  def path(style)
201
187
  font_paths.detect do |path|
202
188
  File.basename(path) == style.font
@@ -236,14 +222,7 @@ module Fontist
236
222
  end
237
223
 
238
224
  def raise_non_supported_font
239
- raise Fontist::Errors::NonSupportedFontError.new(
240
- "Font '#{@name}' not found locally nor available in the Fontist " \
241
- "formula repository.\n" \
242
- "Perhaps it is available at the latest Fontist formula " \
243
- "repository.\n" \
244
- "You can update the formula repository using the command " \
245
- "`fontist update` and try again."
246
- )
225
+ raise Fontist::Errors::UnsupportedFontError.new(@name)
247
226
  end
248
227
  end
249
228
  end
@@ -6,6 +6,10 @@ module Fontist
6
6
  include Utils::ExeExtractor
7
7
  include Utils::MsiExtractor
8
8
  include Utils::SevenZipExtractor
9
+ include Utils::RpmExtractor
10
+ include Utils::GzipExtractor
11
+ include Utils::CpioExtractor
12
+ include Utils::TarExtractor
9
13
 
10
14
  def initialize(formula)
11
15
  @formula = formula
@@ -0,0 +1,29 @@
1
+ require "fontist/indexes/filename_index"
2
+
3
+ module Fontist
4
+ class FontPath
5
+ def initialize(path)
6
+ @path = path
7
+ end
8
+
9
+ def to_s
10
+ [].tap do |s|
11
+ s << "-"
12
+ s << @path
13
+ s << "(from #{formulas.join(' or ')} formula)" if formulas.any?
14
+ end.join(" ")
15
+ end
16
+
17
+ def formulas
18
+ @formulas ||= if fontist_font?
19
+ Indexes::FilenameIndex.from_yaml.load_index_formulas(File.basename(@path)).map(&:name)
20
+ else
21
+ []
22
+ end
23
+ end
24
+
25
+ def fontist_font?
26
+ @path.start_with?(Fontist.fonts_path.to_s)
27
+ end
28
+ end
29
+ end