fontist 1.16.0 → 1.17.0

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: 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