fontist 1.16.0 → 1.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 14a836d048cc0ce0d74885f256e3d7cb48466efcadd75008207e1568927ca8cc
4
- data.tar.gz: 468355d3c50412aef7642ad44abf204edbf827a81d3ccfe327f274a90cddedcd
3
+ metadata.gz: e1c609003084e7675dfd55c7488c57b9f216a7e9f6412e2dd707e589bdb5f11e
4
+ data.tar.gz: ff531fc17364227dc60b47eaa64fe5547bc9c1d30e05c94364109d79d7276b5e
5
5
  SHA512:
6
- metadata.gz: 62e88a6ac1766b61ffe5db70b36f9b0bb8316d80c048d8df8de57e39e3387de1fd60c3cff1094f0b235d7bfab0979d2b4e4ed01eba12125852f745327e8641b1
7
- data.tar.gz: 97338d5eee1a8df78555281d9bc765499f30c86b98913bae5b21729745e5e983ed257e8ee51d543802e69dc734eee64f464dd8b319c534c3b06c768a65267817
6
+ metadata.gz: 2bcb373787926878310fa113e4454ac09e203c82708bd2edb3df796ce1e92f7e038a5c54011aade53f7cbc2ac2f20c311e449d5d5304a0235b93bfb0433750de
7
+ data.tar.gz: 6ad5b3863ed427316065477a3c873264ffa6d543bb86be696396e61d8f727533bc8bb50268ce8818b45bb15da387e6913b88f2c1a9abb7ed4a4944e0a8d57691
data/README.adoc CHANGED
@@ -73,6 +73,10 @@ All commands support the following global options:
73
73
  NOTE: See <<preferred-family-change>> for the differences between
74
74
  "`preferred family`" and "`default family`".
75
75
 
76
+ `-q, --quiet`:: Print as little information as possible, mostly critical errors.
77
+
78
+ `-v, --verbose`:: Set the log level to debug. It prints formulas excluded
79
+ during installation and information for developers of fontist.
76
80
 
77
81
  === Install fonts: `fontist install`
78
82
 
@@ -125,6 +129,12 @@ for the newest version of the font among formulas with size below a limit
125
129
  NOTE: If styles of a font are spread among several formulas, then all
126
130
  available styles from all formulas would be installed.
127
131
 
132
+ NOTE: Some formulas may have the `min_fontist` attribute, which defines the
133
+ minimum version of fontist by which they can be installed. If `fontist` is of a
134
+ older version, then the formula is avoided to use. In order to see which
135
+ formulas were excluded from the search, the `-v, --verbose` option can be
136
+ specified.
137
+
128
138
  Supported options:
129
139
 
130
140
  `-f, [--force]`:: Install even if already installed in system
@@ -969,6 +979,15 @@ $ fontist install --formula ms_truetype
969
979
 
970
980
  WARNING: This section is only for Fontist maintainers.
971
981
 
982
+ === Formulas versioning
983
+
984
+ To add a new attribute, change how formula is treated or completely replace the structure, there are 2 ways to change a formula format:
985
+
986
+ 1. Use the `min_fontist` attribute in a formula. It sets a requirement for fontist to install the formula only if its version is equal or more than a specified version.
987
+ 2. Use a new branch in the formulas repo, e.g. "v2", "v3", "v4", etc. After creating a new branch, it should be defined in https://github.com/fontist/fontist/blob/v1.16.0/lib/fontist.rb#L51[`Fontist.formulas_version`]
988
+
989
+ NOTE: Using a new branch would require all users to re-download the entire formulas repo. Since this method has a significant overhead, the former one (`min_fontist`) should be used whenever possible.
990
+
972
991
  === Dynamically importing formulas from Google Fonts
973
992
 
974
993
  https://fonts.google.com[Google Fonts] provides probably the largest collection
data/fontist.gemspec CHANGED
@@ -38,7 +38,7 @@ Gem::Specification.new do |spec|
38
38
  spec.add_runtime_dependency "git", "~> 1.0"
39
39
  spec.add_runtime_dependency "ttfunk", "~> 1.6"
40
40
  spec.add_runtime_dependency "plist", "~> 3.0"
41
- spec.add_runtime_dependency "excavate", "~> 0.3"
41
+ spec.add_runtime_dependency "excavate", "~> 0.3", '>= 0.3.4'
42
42
  spec.add_runtime_dependency "socksify", "~> 1.7"
43
43
 
44
44
  spec.add_development_dependency "pry", "~> 0.14"
@@ -3,12 +3,19 @@ module Fontist
3
3
  module ClassOptions
4
4
  def handle_class_options(options)
5
5
  Fontist.preferred_family = options[:preferred_family]
6
- Fontist.log_level = options[:quiet] ? :fatal : :info
6
+ Fontist.log_level = log_level(options)
7
7
 
8
8
  if options[:formulas_path]
9
9
  Fontist.formulas_path = Pathname.new(options[:formulas_path])
10
10
  end
11
11
  end
12
+
13
+ def log_level(options)
14
+ return :debug if options[:verbose]
15
+ return :fatal if options[:quiet]
16
+
17
+ :info
18
+ end
12
19
  end
13
20
  end
14
21
  end
data/lib/fontist/cli.rb CHANGED
@@ -25,6 +25,7 @@ module Fontist
25
25
  STATUS_FORMULA_NOT_FOUND = 13
26
26
  STATUS_FONTCONFIG_NOT_FOUND = 14
27
27
  STATUS_FONTCONFIG_FILE_NOT_FOUND = 15
28
+ STATUS_FONTIST_VERSION_ERROR = 15
28
29
 
29
30
  ERROR_TO_STATUS = {
30
31
  Fontist::Errors::UnsupportedFontError => [STATUS_NON_SUPPORTED_FONT_ERROR],
@@ -50,6 +51,7 @@ module Fontist
50
51
  Fontist::Errors::FontconfigNotFoundError => [STATUS_FONTCONFIG_NOT_FOUND],
51
52
  Fontist::Errors::FontconfigFileNotFoundError =>
52
53
  [STATUS_FONTCONFIG_FILE_NOT_FOUND],
54
+ Fontist::Errors::FontistVersionError => [STATUS_FONTIST_VERSION_ERROR],
53
55
  }.freeze
54
56
 
55
57
  def self.exit_on_failure?
@@ -65,6 +67,11 @@ module Fontist
65
67
  type: :boolean,
66
68
  desc: "Hide all messages"
67
69
 
70
+ class_option :verbose,
71
+ aliases: :v,
72
+ type: :boolean,
73
+ desc: "Print debug messages"
74
+
68
75
  class_option :formulas_path, type: :string, desc: "Path to formulas"
69
76
 
70
77
  desc "install FONT", "Install font"
@@ -179,9 +186,10 @@ module Fontist
179
186
  desc "create-formula URL", "Create a new formula with fonts from URL"
180
187
  option :name, desc: "Example: Times New Roman"
181
188
  option :mirror, repeatable: true
182
- option :subarchive, desc: "Subarchive to choose when there are several ones"
183
189
  option :subdir, desc: "Subdirectory to take fonts from, starting with the " \
184
190
  "root dir, e.g.: stixfonts-2.10/fonts/static_otf. May include `fnmatch` patterns."
191
+ option :file_pattern, desc: "File pattern, e.g. '*.otf'. " \
192
+ "Uses `fnmatch` patterns."
185
193
  def create_formula(url)
186
194
  handle_class_options(options)
187
195
  require "fontist/import/create_formula"
@@ -18,6 +18,8 @@ module Fontist
18
18
 
19
19
  class FontIndexCorrupted < GeneralError; end
20
20
 
21
+ class FontistVersionError < GeneralError; end
22
+
21
23
  class FontNotFoundError < GeneralError; end
22
24
 
23
25
  # for backward compatibility with metanorma,
@@ -10,9 +10,8 @@ module Fontist
10
10
  end
11
11
 
12
12
  def install(confirmation:)
13
- if @formula.license_required && !"yes".casecmp?(confirmation)
14
- raise(Fontist::Errors::LicensingError)
15
- end
13
+ raise_fontist_version_error unless supported_version?
14
+ raise_licensing_error unless license_is_accepted?(confirmation)
16
15
 
17
16
  install_font
18
17
  end
@@ -21,6 +20,33 @@ module Fontist
21
20
 
22
21
  attr_reader :formula
23
22
 
23
+ def supported_version?
24
+ return true unless @formula.min_fontist
25
+
26
+ fontist_version = Gem::Version.new(Fontist::VERSION)
27
+ min_fontist_required = Gem::Version.new(@formula.min_fontist)
28
+
29
+ fontist_version >= min_fontist_required
30
+ end
31
+
32
+ def raise_fontist_version_error
33
+ raise Fontist::Errors::FontistVersionError,
34
+ "Formula requires higher version of fontist. " \
35
+ "Please upgrade fontist.\n" \
36
+ "Minimum required version: #{formula.min_fontist}. " \
37
+ "Current fontist version: #{Fontist::VERSION}."
38
+ end
39
+
40
+ def license_is_accepted?(confirmation)
41
+ return true unless @formula.license_required
42
+
43
+ "yes".casecmp?(confirmation)
44
+ end
45
+
46
+ def raise_licensing_error
47
+ raise(Fontist::Errors::LicensingError)
48
+ end
49
+
24
50
  def install_font
25
51
  fonts_paths = run_in_temp_dir { extract }
26
52
  fonts_paths.empty? ? nil : fonts_paths
@@ -120,6 +120,10 @@ module Fontist
120
120
  @data["platforms"]
121
121
  end
122
122
 
123
+ def min_fontist
124
+ @data["min_fontist"]
125
+ end
126
+
123
127
  def extract
124
128
  Helpers.parse_to_object(@data["extract"])
125
129
  end
@@ -5,66 +5,117 @@ module Fontist
5
5
  def initialize(font_name, size_limit:, version:, smallest:, newest:)
6
6
  @font_name = font_name
7
7
  @size_limit = size_limit || Fontist.formula_size_limit_in_megabytes
8
- @version = version
9
- @smallest = smallest
10
- @newest = newest
8
+
9
+ @options = {}
10
+ @version = @options[:version] = version if version
11
+ @smallest = @options[:smallest] = smallest if smallest
12
+ @newest = @options[:newest] = newest if newest
11
13
  end
12
14
 
13
15
  def call(formulas)
14
16
  return [] if formulas.empty?
15
- return formulas if contain_different_styles?(formulas)
16
- return by_version(formulas) if version_is_passed?
17
- return newest(formulas) if newest_is_passed?
18
- return smallest(formulas) if smallest_is_passed?
19
17
 
20
- default_way(formulas)
18
+ list = filter(formulas)
19
+ return [] if list.empty?
20
+
21
+ choose(list)
21
22
  end
22
23
 
23
24
  private
24
25
 
25
- def version_is_passed?
26
- !@version.nil?
26
+ def filter(formulas)
27
+ list = formulas
28
+
29
+ list = filter_by_passed_version(formulas) if @version
30
+ return [] if list.empty?
31
+
32
+ list = ensure_size_limit(list) if @options.empty?
33
+
34
+ ensure_fontist_version(list)
27
35
  end
28
36
 
29
- def by_version(formulas)
30
- formulas.each do |formula|
31
- fonts = formula.fonts_by_name(@font_name)
32
- fonts.each do |font|
33
- font.styles.each do |style|
34
- version = StyleVersion.new(style.version)
35
- return [formula] if version == passed_version
36
- end
37
+ def ensure_fontist_version(formulas)
38
+ suitable, unsuitable = filter_by_fontist_version(formulas)
39
+ raise_fontist_version_error(unsuitable) if suitable.empty?
40
+
41
+ suitable
42
+ end
43
+
44
+ def filter_by_fontist_version(formulas)
45
+ suitable, unsuitable = formulas.partition do |f|
46
+ f.min_fontist.nil? ||
47
+ Gem::Version.new(Fontist::VERSION) >= Gem::Version.new(f.min_fontist)
48
+ end
49
+
50
+ unless unsuitable.empty?
51
+ print_formulas_with_unsuitable_fontist_version(unsuitable)
52
+ end
53
+
54
+ [suitable, unsuitable]
55
+ end
56
+
57
+ def print_formulas_with_unsuitable_fontist_version(formulas)
58
+ Fontist.ui.debug(
59
+ "Some formulas were excluded from choice, because they require " \
60
+ "higher version of fontist: #{formulas_versions(formulas)}. " \
61
+ "Current fontist version: #{Fontist::VERSION}.",
62
+ )
63
+ end
64
+
65
+ def raise_fontist_version_error(formulas)
66
+ raise Fontist::Errors::FontistVersionError,
67
+ "Suitable formulas require higher version of fontist. " \
68
+ "Please upgrade fontist.\n" \
69
+ "Minimum required version: #{formulas_versions(formulas)}. " \
70
+ "Current fontist version: #{Fontist::VERSION}."
71
+ end
72
+
73
+ def formulas_versions(formulas)
74
+ formulas.map { |f| "#{f.key} (#{f.min_fontist})" }.join(", ")
75
+ end
76
+
77
+ def filter_by_passed_version(formulas)
78
+ formulas.select do |formula|
79
+ contain_passed_version?(formula)
80
+ end
81
+ end
82
+
83
+ def contain_passed_version?(formula)
84
+ fonts = formula.fonts_by_name(@font_name)
85
+ fonts.each do |font|
86
+ font.styles.each do |style|
87
+ version = StyleVersion.new(style.version)
88
+ return true if version == passed_version
37
89
  end
38
90
  end
39
91
 
40
- []
92
+ false
41
93
  end
42
94
 
43
95
  def passed_version
44
96
  @passed_version ||= StyleVersion.new(@version)
45
97
  end
46
98
 
47
- def newest_is_passed?
48
- @newest
49
- end
99
+ def choose(formulas)
100
+ return formulas if contain_different_styles?(formulas)
50
101
 
51
- def newest(formulas)
52
- newest_formulas = filter_by_max_version(formulas)
53
- smallest(newest_formulas)
54
- end
102
+ list = formulas
103
+
104
+ if @options.empty? || @newest
105
+ list = choose_max_version(list)
106
+ end
55
107
 
56
- def smallest_is_passed?
57
- @smallest
108
+ smallest(list)
58
109
  end
59
110
 
60
111
  def smallest(formulas)
61
112
  [choose_smallest_formula(formulas)]
62
113
  end
63
114
 
64
- def default_way(formulas)
65
- size_limited_formulas = filter_by_size_limit(formulas)
66
- raise_size_limit_error if size_limited_formulas.empty?
67
- newest(size_limited_formulas)
115
+ def choose_smallest_formula(formulas)
116
+ formulas.min_by do |formula|
117
+ formula.file_size || 0
118
+ end
68
119
  end
69
120
 
70
121
  def contain_different_styles?(formulas)
@@ -80,6 +131,13 @@ module Fontist
80
131
  styles_by_formula.uniq.size > 1
81
132
  end
82
133
 
134
+ def ensure_size_limit(formulas)
135
+ list = filter_by_size_limit(formulas)
136
+ raise_size_limit_error if list.empty?
137
+
138
+ list
139
+ end
140
+
83
141
  def filter_by_size_limit(formulas)
84
142
  formulas.select do |formula|
85
143
  formula.file_size.nil? || resources_cached?(formula) ||
@@ -97,7 +155,7 @@ module Fontist
97
155
  "(#{@size_limit} MB)."
98
156
  end
99
157
 
100
- def filter_by_max_version(formulas)
158
+ def choose_max_version(formulas)
101
159
  formulas_with_version = detect_formula_version(formulas)
102
160
  max_version = formulas_with_version.map(&:first).max
103
161
  formulas_with_version.select do |version, _formula|
@@ -118,12 +176,6 @@ module Fontist
118
176
  end
119
177
  end
120
178
 
121
- def choose_smallest_formula(formulas)
122
- formulas.min_by do |formula|
123
- formula.file_size || 0
124
- end
125
- end
126
-
127
179
  def resources_cached?(formula)
128
180
  Utils::Cache.new.already_fetched?(
129
181
  formula.resources.flat_map(&:urls),
@@ -40,8 +40,8 @@ module Fontist
40
40
  def extractor
41
41
  @extractor ||=
42
42
  RecursiveExtraction.new(archive,
43
- subarchive: @options[:subarchive],
44
- subdir: @options[:subdir])
43
+ subdir: @options[:subdir],
44
+ file_pattern: @options[:file_pattern])
45
45
  end
46
46
 
47
47
  def archive
@@ -70,7 +70,9 @@ module Fontist
70
70
  end
71
71
 
72
72
  def font
73
- File.basename(@path, ".*") + "." + @extension
73
+ basename = File.basename(@path, ".*").chomp(".#{@extension}")
74
+
75
+ "#{basename}.#{@extension}"
74
76
  end
75
77
 
76
78
  def source_font
@@ -8,9 +8,10 @@ module Fontist
8
8
  LICENSE_PATTERN =
9
9
  /(ofl\.txt|ufl\.txt|licenses?\.txt|license(\.md)?|copying)$/i.freeze
10
10
 
11
- def initialize(archive, subarchive: nil, subdir: nil)
11
+ def initialize(archive, subdir: nil, file_pattern: nil)
12
12
  @archive = archive
13
13
  @subdir = subdir
14
+ @file_pattern = file_pattern
14
15
  @operations = {}
15
16
  @font_files = []
16
17
  @collection_files = []
@@ -72,10 +73,11 @@ module Fontist
72
73
 
73
74
  def extract_data(archive)
74
75
  Excavate::Archive.new(path(archive)).files(recursive_packages: true) do |path|
76
+ Fontist.ui.debug(path)
75
77
  next unless File.file?(path)
76
78
 
77
79
  match_license(path)
78
- match_font(path) if font_directory?(path)
80
+ match_font(path) if font_candidate?(path)
79
81
  end
80
82
  end
81
83
 
@@ -110,6 +112,10 @@ module Fontist
110
112
  end
111
113
  end
112
114
 
115
+ def font_candidate?(path)
116
+ font_directory?(path) && file_pattern?(path)
117
+ end
118
+
113
119
  def font_directory?(path)
114
120
  return true unless subdirectory_pattern
115
121
 
@@ -119,6 +125,12 @@ module Fontist
119
125
  def subdirectory_pattern
120
126
  @subdirectory_pattern ||= "*" + @subdir.chomp("/") if @subdir
121
127
  end
128
+
129
+ def file_pattern?(path)
130
+ return true unless @file_pattern
131
+
132
+ File.fnmatch?(@file_pattern, File.basename(path))
133
+ end
122
134
  end
123
135
  end
124
136
  end
@@ -1,3 +1,3 @@
1
1
  module Fontist
2
- VERSION = "1.16.0".freeze
2
+ VERSION = "1.17.0".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: 1.16.0
4
+ version: 1.17.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-07-29 00:00:00.000000000 Z
11
+ date: 2023-09-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: down
@@ -143,6 +143,9 @@ dependencies:
143
143
  - - "~>"
144
144
  - !ruby/object:Gem::Version
145
145
  version: '0.3'
146
+ - - ">="
147
+ - !ruby/object:Gem::Version
148
+ version: 0.3.4
146
149
  type: :runtime
147
150
  prerelease: false
148
151
  version_requirements: !ruby/object:Gem::Requirement
@@ -150,6 +153,9 @@ dependencies:
150
153
  - - "~>"
151
154
  - !ruby/object:Gem::Version
152
155
  version: '0.3'
156
+ - - ">="
157
+ - !ruby/object:Gem::Version
158
+ version: 0.3.4
153
159
  - !ruby/object:Gem::Dependency
154
160
  name: socksify
155
161
  requirement: !ruby/object:Gem::Requirement