fontist 2.2.1 → 3.0.1
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 +4 -4
- data/.github/workflows/formulas-auto-update-test.yml +13 -13
- data/.rubocop_todo.yml +179 -139
- data/fontist.gemspec +2 -2
- data/lib/fontist/cache/store.rb +1 -1
- data/lib/fontist/cli.rb +2 -1
- data/lib/fontist/errors.rb +3 -3
- data/lib/fontist/extract.rb +1 -0
- data/lib/fontist/font.rb +2 -2
- data/lib/fontist/font_finder.rb +1 -2
- data/lib/fontist/font_installer.rb +14 -14
- data/lib/fontist/format_matcher.rb +4 -2
- data/lib/fontist/format_spec.rb +1 -1
- data/lib/fontist/formula.rb +4 -3
- data/lib/fontist/formula_picker.rb +5 -3
- data/lib/fontist/import/formula_builder.rb +1 -1
- data/lib/fontist/import/google/data_sources/github.rb +4 -4
- data/lib/fontist/import/google/font_database.rb +8 -8
- data/lib/fontist/import/google/formula_builders/formula_builder_v4.rb +1 -1
- data/lib/fontist/import/google/formula_builders/formula_builder_v5.rb +9 -3
- data/lib/fontist/import/google/metadata_adapter.rb +6 -6
- data/lib/fontist/import/google/models/font_family.rb +1 -1
- data/lib/fontist/import/import_display.rb +5 -5
- data/lib/fontist/import/macos_importer.rb +1 -1
- data/lib/fontist/import/upgrade_formulas.rb +1 -3
- data/lib/fontist/import/v4_to_v5_migrator.rb +2 -1
- data/lib/fontist/import.rb +2 -1
- data/lib/fontist/indexes/directory_snapshot.rb +2 -2
- data/lib/fontist/indexes/incremental_scanner.rb +2 -2
- data/lib/fontist/indexes.rb +8 -4
- data/lib/fontist/macos/catalog/asset.rb +2 -2
- data/lib/fontist/macos_import_source.rb +0 -1
- data/lib/fontist/repo.rb +1 -1
- data/lib/fontist/system_index.rb +5 -5
- data/lib/fontist/utils/downloader.rb +2 -2
- data/lib/fontist/utils/system.rb +2 -2
- data/lib/fontist/validation.rb +1 -1
- data/lib/fontist/validator.rb +2 -2
- data/lib/fontist/version.rb +1 -1
- data/lib/fontist.rb +3 -2
- metadata +6 -6
data/lib/fontist/cache/store.rb
CHANGED
data/lib/fontist/cli.rb
CHANGED
|
@@ -338,7 +338,8 @@ module Fontist
|
|
|
338
338
|
"Uses `fnmatch` patterns."
|
|
339
339
|
option :name_prefix, desc: "Prefix to add to all font family names, " \
|
|
340
340
|
"e.g. 'Wine ' for compatibility fonts"
|
|
341
|
-
option :schema_version, type: :numeric, default: 5,
|
|
341
|
+
option :schema_version, type: :numeric, default: 5,
|
|
342
|
+
desc: "Formula schema version (default: 5)"
|
|
342
343
|
def create_formula(url)
|
|
343
344
|
handle_class_options(options)
|
|
344
345
|
name = Fontist::Import::CreateFormula.new(url, options).call
|
data/lib/fontist/errors.rb
CHANGED
|
@@ -159,9 +159,9 @@ module Fontist
|
|
|
159
159
|
|
|
160
160
|
def build_message(font_name)
|
|
161
161
|
"Font '#{font_name}' is only available for: #{@required_platforms.join(', ')}. " \
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
162
|
+
"Your current platform is: #{@current_platform}. " \
|
|
163
|
+
"This font is licensed exclusively for the specified platform(s) and " \
|
|
164
|
+
"cannot be installed on your system."
|
|
165
165
|
end
|
|
166
166
|
end
|
|
167
167
|
|
data/lib/fontist/extract.rb
CHANGED
data/lib/fontist/font.rb
CHANGED
|
@@ -338,9 +338,9 @@ module Fontist
|
|
|
338
338
|
all_fonts = [fontist_fonts, user_fonts, system_fonts].compact.flatten
|
|
339
339
|
return unless all_fonts && !all_fonts.empty?
|
|
340
340
|
|
|
341
|
-
uninstalled_paths = all_fonts.
|
|
341
|
+
uninstalled_paths = all_fonts.filter_map do |font|
|
|
342
342
|
uninstall_font_at_location(font.path)
|
|
343
|
-
end
|
|
343
|
+
end
|
|
344
344
|
|
|
345
345
|
return if uninstalled_paths.empty?
|
|
346
346
|
|
data/lib/fontist/font_finder.rb
CHANGED
|
@@ -75,7 +75,7 @@ module Fontist
|
|
|
75
75
|
def extract_resource_names(formula)
|
|
76
76
|
return [] unless formula.resources
|
|
77
77
|
|
|
78
|
-
Array(formula.resources).
|
|
78
|
+
Array(formula.resources).filter_map(&:name)
|
|
79
79
|
end
|
|
80
80
|
|
|
81
81
|
def build_font_match(formula, name, resource)
|
|
@@ -123,7 +123,6 @@ module Fontist
|
|
|
123
123
|
matcher = FormatMatcher.new(@format_spec)
|
|
124
124
|
matcher.filter_resources(resources)
|
|
125
125
|
end
|
|
126
|
-
|
|
127
126
|
end
|
|
128
127
|
|
|
129
128
|
# Result object for font matches
|
|
@@ -98,16 +98,14 @@ module Fontist
|
|
|
98
98
|
end
|
|
99
99
|
|
|
100
100
|
def resource_options
|
|
101
|
-
@resource_options ||=
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
end
|
|
110
|
-
end
|
|
101
|
+
@resource_options ||= if @formula.resources.size == 1 || !@formula.v5?
|
|
102
|
+
@formula.resources.first
|
|
103
|
+
elsif @format_spec&.has_constraints?
|
|
104
|
+
matcher = FormatMatcher.new(@format_spec)
|
|
105
|
+
matcher.select_preferred_resource(@formula.resources)
|
|
106
|
+
else
|
|
107
|
+
find_desktop_resource || @formula.resources.first
|
|
108
|
+
end
|
|
111
109
|
end
|
|
112
110
|
|
|
113
111
|
def find_desktop_resource
|
|
@@ -135,7 +133,9 @@ module Fontist
|
|
|
135
133
|
file_names = styles.map { |s| s.source_font || s.font }
|
|
136
134
|
|
|
137
135
|
if @formula.v5? && resource_options&.source == "google" && file_names.any?
|
|
138
|
-
resource_basenames = Array(resource_options.files).map
|
|
136
|
+
resource_basenames = Array(resource_options.files).map do |f|
|
|
137
|
+
File.basename(f)
|
|
138
|
+
end
|
|
139
139
|
unless file_names.any? { |f| resource_basenames.include?(f) }
|
|
140
140
|
return resource_basenames
|
|
141
141
|
end
|
|
@@ -169,7 +169,7 @@ module Fontist
|
|
|
169
169
|
@subdirectories ||= begin
|
|
170
170
|
extracts = [@formula.extract].flatten.compact
|
|
171
171
|
# options is a collection, so we need to flatten it too
|
|
172
|
-
options = extracts.flat_map
|
|
172
|
+
options = extracts.flat_map(&:options).compact
|
|
173
173
|
options.filter_map(&:fonts_sub_dir)
|
|
174
174
|
end
|
|
175
175
|
end
|
|
@@ -296,12 +296,12 @@ module Fontist
|
|
|
296
296
|
def temp_path_for(source_path, format)
|
|
297
297
|
base = File.basename(source_path, ".*")
|
|
298
298
|
dir = @format_spec&.transcode_path || Dir.mktmpdir
|
|
299
|
-
FileUtils.mkdir_p(dir)
|
|
299
|
+
FileUtils.mkdir_p(dir)
|
|
300
300
|
File.join(dir, "#{base}.#{format}")
|
|
301
301
|
end
|
|
302
302
|
|
|
303
303
|
def cleanup_temp_file(path)
|
|
304
|
-
|
|
304
|
+
FileUtils.rm_f(path)
|
|
305
305
|
rescue StandardError
|
|
306
306
|
# Ignore cleanup errors
|
|
307
307
|
end
|
|
@@ -116,7 +116,9 @@ module Fontist
|
|
|
116
116
|
end
|
|
117
117
|
|
|
118
118
|
# Check if Fontisan can convert from any available format
|
|
119
|
-
convertible = available_formats.find
|
|
119
|
+
convertible = available_formats.find do |f|
|
|
120
|
+
self.class.can_convert?(f, requested)
|
|
121
|
+
end
|
|
120
122
|
if convertible
|
|
121
123
|
return {
|
|
122
124
|
strategy: :convert,
|
|
@@ -163,7 +165,7 @@ module Fontist
|
|
|
163
165
|
def find_variable_resource(resources)
|
|
164
166
|
return nil unless @spec.prefer_variable
|
|
165
167
|
|
|
166
|
-
resources.find
|
|
168
|
+
resources.find(&:variable_font?)
|
|
167
169
|
end
|
|
168
170
|
|
|
169
171
|
def axes_match?(available_axes)
|
data/lib/fontist/format_spec.rb
CHANGED
data/lib/fontist/formula.rb
CHANGED
|
@@ -50,7 +50,8 @@ module Fontist
|
|
|
50
50
|
|
|
51
51
|
key_value do
|
|
52
52
|
# Only serialize schema_version if it's v5 (5), not for v4 formulas
|
|
53
|
-
map "schema_version", to: :schema_version, render_nil: false,
|
|
53
|
+
map "schema_version", to: :schema_version, render_nil: false,
|
|
54
|
+
render_default: false
|
|
54
55
|
map "name", to: :name
|
|
55
56
|
map "description", to: :description
|
|
56
57
|
map "homepage", to: :homepage
|
|
@@ -96,9 +97,9 @@ module Fontist
|
|
|
96
97
|
end
|
|
97
98
|
|
|
98
99
|
def all
|
|
99
|
-
formulas = Dir[Fontist.formulas_path.join("**/*.yml").to_s].
|
|
100
|
+
formulas = Dir[Fontist.formulas_path.join("**/*.yml").to_s].filter_map do |path|
|
|
100
101
|
Formula.from_file(path)
|
|
101
|
-
end
|
|
102
|
+
end
|
|
102
103
|
|
|
103
104
|
FormulaCollection.new(formulas)
|
|
104
105
|
end
|
|
@@ -48,14 +48,14 @@ module Fontist
|
|
|
48
48
|
def filter_by_format_spec(formulas)
|
|
49
49
|
matcher = FormatMatcher.new(@format_spec)
|
|
50
50
|
|
|
51
|
-
formulas.
|
|
51
|
+
formulas.filter_map do |formula|
|
|
52
52
|
next formula unless formula.v5?
|
|
53
53
|
|
|
54
54
|
matching = matcher.filter_resources(formula.resources)
|
|
55
55
|
if matching.any?
|
|
56
56
|
formula.dup.tap { |f| f.resources = matching }
|
|
57
57
|
end
|
|
58
|
-
end
|
|
58
|
+
end
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
def ensure_fontist_version(formulas)
|
|
@@ -99,7 +99,9 @@ module Fontist
|
|
|
99
99
|
end
|
|
100
100
|
|
|
101
101
|
def raise_format_not_available_error(formulas)
|
|
102
|
-
available = formulas.flat_map
|
|
102
|
+
available = formulas.flat_map do |f|
|
|
103
|
+
Array(f.resources).map(&:format)
|
|
104
|
+
end.compact.uniq
|
|
103
105
|
raise Errors::FormatNotAvailableError.new(
|
|
104
106
|
@font_name,
|
|
105
107
|
@format_spec.format || @format_spec.prefer_format,
|
|
@@ -69,7 +69,7 @@ module Fontist
|
|
|
69
69
|
|
|
70
70
|
unless ofl_path.exist? || apache_path.exist? || ufl_path.exist?
|
|
71
71
|
raise ArgumentError,
|
|
72
|
-
"Source path does not contain expected font directories: "\
|
|
72
|
+
"Source path does not contain expected font directories: " \
|
|
73
73
|
"#{@source_path}"
|
|
74
74
|
end
|
|
75
75
|
end
|
|
@@ -183,7 +183,7 @@ module Fontist
|
|
|
183
183
|
description: font_file.description,
|
|
184
184
|
}
|
|
185
185
|
rescue StandardError => e
|
|
186
|
-
warn "Warning: Failed to parse font file #{filename}: "\
|
|
186
|
+
warn "Warning: Failed to parse font file #{filename}: " \
|
|
187
187
|
"#{e.message}"
|
|
188
188
|
end
|
|
189
189
|
end
|
|
@@ -199,11 +199,11 @@ module Fontist
|
|
|
199
199
|
return [] unless metadata.fonts
|
|
200
200
|
|
|
201
201
|
fonts_array = metadata.fonts.is_a?(Array) ? metadata.fonts : [metadata.fonts]
|
|
202
|
-
fonts_array.
|
|
202
|
+
fonts_array.filter_map do |font|
|
|
203
203
|
weight = font.respond_to?(:weight) ? font.weight : font["weight"]
|
|
204
204
|
style = font.respond_to?(:style) ? font.style : font["style"]
|
|
205
205
|
variant_name(weight, style)
|
|
206
|
-
end.
|
|
206
|
+
end.uniq
|
|
207
207
|
end
|
|
208
208
|
|
|
209
209
|
# Generate variant name from weight and style
|
|
@@ -136,7 +136,7 @@ github_data: nil, version: 4, source_path: nil)
|
|
|
136
136
|
|
|
137
137
|
# Get all unique categories
|
|
138
138
|
def categories
|
|
139
|
-
all_fonts.
|
|
139
|
+
all_fonts.filter_map(&:category).uniq.sort
|
|
140
140
|
end
|
|
141
141
|
|
|
142
142
|
# Get fonts available in TTF format
|
|
@@ -190,7 +190,7 @@ github_data: nil, version: 4, source_path: nil)
|
|
|
190
190
|
|
|
191
191
|
# Generate formulas for all fonts
|
|
192
192
|
def to_formulas
|
|
193
|
-
all_fonts.
|
|
193
|
+
all_fonts.filter_map { |f| to_formula(f.family) }
|
|
194
194
|
end
|
|
195
195
|
|
|
196
196
|
# Save formulas to disk
|
|
@@ -198,12 +198,12 @@ github_data: nil, version: 4, source_path: nil)
|
|
|
198
198
|
families = family_name ? [font_by_name(family_name)] : all_fonts
|
|
199
199
|
families = families.compact
|
|
200
200
|
|
|
201
|
-
families.
|
|
201
|
+
families.filter_map do |family|
|
|
202
202
|
formula = to_formula(family.family)
|
|
203
203
|
next unless formula
|
|
204
204
|
|
|
205
205
|
save_formula(formula, family.family, output_dir)
|
|
206
|
-
end
|
|
206
|
+
end
|
|
207
207
|
end
|
|
208
208
|
|
|
209
209
|
# Find filename for a variant
|
|
@@ -322,8 +322,8 @@ github_data: nil, version: 4, source_path: nil)
|
|
|
322
322
|
def index_github_data
|
|
323
323
|
return {} if @github_data_raw.empty?
|
|
324
324
|
|
|
325
|
-
@github_data_raw.
|
|
326
|
-
|
|
325
|
+
@github_data_raw.to_h do |family|
|
|
326
|
+
[family.family, family]
|
|
327
327
|
end
|
|
328
328
|
end
|
|
329
329
|
|
|
@@ -367,8 +367,8 @@ github_data: nil, version: 4, source_path: nil)
|
|
|
367
367
|
|
|
368
368
|
# Index fonts by family name
|
|
369
369
|
def index_by_family(fonts)
|
|
370
|
-
fonts.
|
|
371
|
-
|
|
370
|
+
fonts.to_h do |font|
|
|
371
|
+
[font.family, font]
|
|
372
372
|
end
|
|
373
373
|
end
|
|
374
374
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative "base_formula_builder"
|
|
4
4
|
require_relative "../../../utils/downloader"
|
|
5
|
-
require_relative "../../font_metadata_extractor"
|
|
5
|
+
require_relative "../../font_metadata_extractor" # lib/fontist/import/font_metadata_extractor.rb
|
|
6
6
|
|
|
7
7
|
module Fontist
|
|
8
8
|
module Import
|
|
@@ -111,8 +111,11 @@ module Fontist
|
|
|
111
111
|
end
|
|
112
112
|
|
|
113
113
|
def detect_actual_format(urls, declared_format)
|
|
114
|
-
extensions = urls.
|
|
115
|
-
|
|
114
|
+
extensions = urls.filter_map do |url|
|
|
115
|
+
url.split("/").last[/\.(\w+)$/, 1]&.downcase
|
|
116
|
+
end.uniq
|
|
117
|
+
if extensions.size == 1 && %w[ttf otf woff
|
|
118
|
+
woff2].include?(extensions.first)
|
|
116
119
|
extensions.first
|
|
117
120
|
else
|
|
118
121
|
declared_format
|
|
@@ -174,7 +177,10 @@ module Fontist
|
|
|
174
177
|
# For variable fonts, ALL styles should be marked as variable
|
|
175
178
|
if family.variable_font?
|
|
176
179
|
style["variable_font"] = true
|
|
177
|
-
|
|
180
|
+
if family.axes&.any?
|
|
181
|
+
style["variable_axes"] =
|
|
182
|
+
family.axes.map(&:tag)
|
|
183
|
+
end
|
|
178
184
|
else
|
|
179
185
|
style["variable_font"] = false
|
|
180
186
|
end
|
|
@@ -77,7 +77,7 @@ module Fontist
|
|
|
77
77
|
font_fields = message.find_fields("fonts")
|
|
78
78
|
return nil if font_fields.empty?
|
|
79
79
|
|
|
80
|
-
font_fields.
|
|
80
|
+
font_fields.filter_map do |field|
|
|
81
81
|
next unless field.message_field?
|
|
82
82
|
|
|
83
83
|
# field.value is a Hash for message fields in unibuf
|
|
@@ -94,7 +94,7 @@ module Fontist
|
|
|
94
94
|
"full_name" => field_value(font_msg, "full_name"),
|
|
95
95
|
"copyright" => field_value(font_msg, "copyright"),
|
|
96
96
|
}.compact
|
|
97
|
-
end
|
|
97
|
+
end
|
|
98
98
|
end
|
|
99
99
|
|
|
100
100
|
# Extract axes array
|
|
@@ -102,7 +102,7 @@ module Fontist
|
|
|
102
102
|
axis_fields = message.find_fields("axes")
|
|
103
103
|
return nil if axis_fields.empty?
|
|
104
104
|
|
|
105
|
-
axis_fields.
|
|
105
|
+
axis_fields.filter_map do |field|
|
|
106
106
|
next unless field.message_field?
|
|
107
107
|
|
|
108
108
|
axis_hash = field.value
|
|
@@ -115,7 +115,7 @@ module Fontist
|
|
|
115
115
|
"max_value" => field_float(axis_msg, "max_value"),
|
|
116
116
|
"default_value" => field_float(axis_msg, "default_value"),
|
|
117
117
|
}.compact
|
|
118
|
-
end
|
|
118
|
+
end
|
|
119
119
|
end
|
|
120
120
|
|
|
121
121
|
# Extract source information
|
|
@@ -142,7 +142,7 @@ module Fontist
|
|
|
142
142
|
file_fields = source_msg.find_fields("files")
|
|
143
143
|
return nil if file_fields.empty?
|
|
144
144
|
|
|
145
|
-
file_fields.
|
|
145
|
+
file_fields.filter_map do |field|
|
|
146
146
|
next unless field.message_field?
|
|
147
147
|
|
|
148
148
|
file_hash = field.value
|
|
@@ -153,7 +153,7 @@ module Fontist
|
|
|
153
153
|
"source_file" => field_value(file_msg, "source_file"),
|
|
154
154
|
"dest_file" => field_value(file_msg, "dest_file"),
|
|
155
155
|
}.compact
|
|
156
|
-
end
|
|
156
|
+
end
|
|
157
157
|
end
|
|
158
158
|
|
|
159
159
|
# Extract registry default overrides as hash
|
|
@@ -113,7 +113,7 @@ module Fontist
|
|
|
113
113
|
# @param title [String] Section title (deprecated - use header instead)
|
|
114
114
|
def self.section(title)
|
|
115
115
|
Fontist.ui.say("")
|
|
116
|
-
Fontist.ui.say("── #{title} " + "─" * (76 - title.length))
|
|
116
|
+
Fontist.ui.say("── #{title} " + ("─" * (76 - title.length)))
|
|
117
117
|
Fontist.ui.say("")
|
|
118
118
|
end
|
|
119
119
|
|
|
@@ -247,7 +247,7 @@ module Fontist
|
|
|
247
247
|
return unless results[:errors]&.any?
|
|
248
248
|
|
|
249
249
|
Fontist.ui.say(" #{Paint['⚠',
|
|
250
|
-
:yellow]} Note: #{results[:failed]} font#{results[:failed] > 1
|
|
250
|
+
:yellow]} Note: #{results[:failed]} font#{'s' if results[:failed] > 1} failed during import.")
|
|
251
251
|
Fontist.ui.say("")
|
|
252
252
|
end
|
|
253
253
|
|
|
@@ -266,10 +266,10 @@ module Fontist
|
|
|
266
266
|
return if total.zero?
|
|
267
267
|
|
|
268
268
|
if results[:successful] > (total * 0.5)
|
|
269
|
-
Fontist.ui.say(Paint[" 🎉 Great success! #{results[:successful]} formula#{results[:successful] > 1
|
|
269
|
+
Fontist.ui.say(Paint[" 🎉 Great success! #{results[:successful]} formula#{'s' if results[:successful] > 1} created!",
|
|
270
270
|
:green, :bright])
|
|
271
271
|
elsif results[:successful].positive?
|
|
272
|
-
Fontist.ui.say(Paint[" 👍 Keep going! #{results[:successful]} formula#{results[:successful] > 1
|
|
272
|
+
Fontist.ui.say(Paint[" 👍 Keep going! #{results[:successful]} formula#{'s' if results[:successful] > 1} created.",
|
|
273
273
|
:yellow, :bright])
|
|
274
274
|
end
|
|
275
275
|
|
|
@@ -277,7 +277,7 @@ module Fontist
|
|
|
277
277
|
end
|
|
278
278
|
|
|
279
279
|
def calculate_total(results)
|
|
280
|
-
results[:total] || (results[:successful] || 0) + (results[:failed] || 0) + (results[:skipped] || 0)
|
|
280
|
+
results[:total] || ((results[:successful] || 0) + (results[:failed] || 0) + (results[:skipped] || 0))
|
|
281
281
|
end
|
|
282
282
|
end
|
|
283
283
|
end
|
|
@@ -111,7 +111,7 @@ force: false, verbose: false, import_cache: nil, schema_version: 4)
|
|
|
111
111
|
Fontist.ui.say("#{Paint[progress,
|
|
112
112
|
:white]} #{Paint["#{percentage}%",
|
|
113
113
|
:yellow]} | #{Paint[family_name, :cyan,
|
|
114
|
-
:bright]} #{Paint["(#{fonts_count} font#{fonts_count > 1
|
|
114
|
+
:bright]} #{Paint["(#{fonts_count} font#{'s' if fonts_count > 1})", :black,
|
|
115
115
|
:bright]}")
|
|
116
116
|
|
|
117
117
|
start_time = Time.now
|
|
@@ -438,9 +438,7 @@ module Fontist
|
|
|
438
438
|
|
|
439
439
|
entry_path = File.join(extract_dir, entry.full_name)
|
|
440
440
|
FileUtils.mkdir_p(File.dirname(entry_path))
|
|
441
|
-
File.
|
|
442
|
-
f.write(entry.read)
|
|
443
|
-
end
|
|
441
|
+
File.binwrite(entry_path, entry.read)
|
|
444
442
|
end
|
|
445
443
|
end
|
|
446
444
|
|
|
@@ -93,7 +93,8 @@ module Fontist
|
|
|
93
93
|
private
|
|
94
94
|
|
|
95
95
|
def load_yaml_without_aliases(path)
|
|
96
|
-
data = YAML.safe_load(File.read(path), aliases: true,
|
|
96
|
+
data = YAML.safe_load(File.read(path), aliases: true,
|
|
97
|
+
permitted_classes: [Date])
|
|
97
98
|
JSON.parse(JSON.generate(data))
|
|
98
99
|
end
|
|
99
100
|
|
data/lib/fontist/import.rb
CHANGED
|
@@ -4,7 +4,8 @@ module Fontist
|
|
|
4
4
|
autoload :CreateFormula, "#{__dir__}/import/create_formula"
|
|
5
5
|
autoload :Files, "#{__dir__}/import/files"
|
|
6
6
|
autoload :FontMetadataExtractor, "#{__dir__}/import/font_metadata_extractor"
|
|
7
|
-
autoload :FontParsingErrorCollector,
|
|
7
|
+
autoload :FontParsingErrorCollector,
|
|
8
|
+
"#{__dir__}/import/font_parsing_error_collector"
|
|
8
9
|
autoload :FontStyle, "#{__dir__}/import/font_style"
|
|
9
10
|
autoload :FormulaBuilder, "#{__dir__}/import/formula_builder"
|
|
10
11
|
autoload :FormulaSerializer, "#{__dir__}/import/formula_serializer"
|
|
@@ -57,8 +57,8 @@ module Fontist
|
|
|
57
57
|
def initialize(directory_path, files, scanned_at)
|
|
58
58
|
@directory_path = directory_path
|
|
59
59
|
@files = files.freeze # Immutable
|
|
60
|
-
@files_by_filename = files.
|
|
61
|
-
|
|
60
|
+
@files_by_filename = files.to_h do |f|
|
|
61
|
+
[f[:filename], f]
|
|
62
62
|
end.freeze
|
|
63
63
|
@scanned_at = scanned_at
|
|
64
64
|
end
|
|
@@ -53,14 +53,14 @@ module Fontist
|
|
|
53
53
|
# cache: Optional hash of path => cached_version
|
|
54
54
|
# Returns: Array of font metadata hashes
|
|
55
55
|
def self.scan_batch(paths, cache: {})
|
|
56
|
-
paths.
|
|
56
|
+
paths.filter_map do |path|
|
|
57
57
|
cached = cache[path]
|
|
58
58
|
if cached
|
|
59
59
|
scan_with_cache(path, cached)
|
|
60
60
|
else
|
|
61
61
|
scan_font_file(path)
|
|
62
62
|
end
|
|
63
|
-
end
|
|
63
|
+
end
|
|
64
64
|
end
|
|
65
65
|
|
|
66
66
|
# Compute SHA256 signature of first 1KB for quick change detection
|
data/lib/fontist/indexes.rb
CHANGED
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
module Fontist
|
|
2
2
|
module Indexes
|
|
3
|
-
autoload :BaseFontCollectionIndex,
|
|
4
|
-
|
|
3
|
+
autoload :BaseFontCollectionIndex,
|
|
4
|
+
"#{__dir__}/indexes/base_font_collection_index"
|
|
5
|
+
autoload :DefaultFamilyFontIndex,
|
|
6
|
+
"#{__dir__}/indexes/default_family_font_index"
|
|
5
7
|
autoload :DirectoryChange, "#{__dir__}/indexes/directory_change"
|
|
6
8
|
autoload :DirectorySnapshot, "#{__dir__}/indexes/directory_snapshot"
|
|
7
9
|
autoload :FilenameIndex, "#{__dir__}/indexes/filename_index"
|
|
8
10
|
autoload :FontIndex, "#{__dir__}/indexes/font_index"
|
|
9
11
|
autoload :FontistIndex, "#{__dir__}/indexes/fontist_index"
|
|
10
12
|
autoload :FormulaKeyToPath, "#{__dir__}/indexes/formula_key_to_path"
|
|
11
|
-
autoload :IncrementalIndexUpdater,
|
|
13
|
+
autoload :IncrementalIndexUpdater,
|
|
14
|
+
"#{__dir__}/indexes/incremental_index_updater"
|
|
12
15
|
autoload :IncrementalScanner, "#{__dir__}/indexes/incremental_scanner"
|
|
13
16
|
autoload :IndexMixin, "#{__dir__}/indexes/index_mixin"
|
|
14
|
-
autoload :PreferredFamilyFontIndex,
|
|
17
|
+
autoload :PreferredFamilyFontIndex,
|
|
18
|
+
"#{__dir__}/indexes/preferred_family_font_index"
|
|
15
19
|
autoload :SystemIndex, "#{__dir__}/indexes/system_index"
|
|
16
20
|
autoload :UserIndex, "#{__dir__}/indexes/user_index"
|
|
17
21
|
end
|
|
@@ -29,11 +29,11 @@ module Fontist
|
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
def postscript_names
|
|
32
|
-
fonts.
|
|
32
|
+
fonts.filter_map(&:postscript_name)
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
def font_families
|
|
36
|
-
fonts.
|
|
36
|
+
fonts.filter_map(&:font_family_name).uniq
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
def primary_family_name
|
data/lib/fontist/repo.rb
CHANGED
data/lib/fontist/system_index.rb
CHANGED
|
@@ -426,7 +426,7 @@ module Fontist
|
|
|
426
426
|
|
|
427
427
|
def scan_directory_mtimes
|
|
428
428
|
dirs = extract_font_directories
|
|
429
|
-
dirs.
|
|
429
|
+
dirs.to_h { |dir| [dir, directory_mtime(dir)] }
|
|
430
430
|
end
|
|
431
431
|
|
|
432
432
|
def directory_mtime(dir)
|
|
@@ -444,10 +444,10 @@ module Fontist
|
|
|
444
444
|
templates = SystemFont.system_config["system"][os]["paths"]
|
|
445
445
|
|
|
446
446
|
# Extract directory part before wildcards
|
|
447
|
-
base_dirs = templates.
|
|
447
|
+
base_dirs = templates.filter_map do |pattern|
|
|
448
448
|
# Remove glob patterns to get base directory
|
|
449
449
|
pattern.split("/*").first
|
|
450
|
-
end.
|
|
450
|
+
end.uniq
|
|
451
451
|
|
|
452
452
|
# Add fontist fonts directory
|
|
453
453
|
base_dirs << Fontist.fonts_path.to_s
|
|
@@ -458,10 +458,10 @@ module Fontist
|
|
|
458
458
|
def parse_directory_mtimes
|
|
459
459
|
return {} unless directory_mtimes
|
|
460
460
|
|
|
461
|
-
|
|
461
|
+
directory_mtimes.to_h do |entry|
|
|
462
462
|
dir, mtime = entry.split(":", 2)
|
|
463
463
|
[dir, mtime.to_i]
|
|
464
|
-
end
|
|
464
|
+
end
|
|
465
465
|
end
|
|
466
466
|
|
|
467
467
|
def save_metadata
|
|
@@ -135,9 +135,9 @@ module Fontist
|
|
|
135
135
|
|
|
136
136
|
def headers
|
|
137
137
|
obj = Helpers.url_object(@file)
|
|
138
|
-
obj.respond_to?(:headers) &&
|
|
138
|
+
(obj.respond_to?(:headers) &&
|
|
139
139
|
obj.headers &&
|
|
140
|
-
obj.headers.to_h.
|
|
140
|
+
obj.headers.to_h.to_h { |k, v| [k.to_s, v] }) || # rubocop:disable Style/HashTransformKeys, Metrics/LineLength
|
|
141
141
|
{}
|
|
142
142
|
end
|
|
143
143
|
|
data/lib/fontist/utils/system.rb
CHANGED
|
@@ -3,7 +3,7 @@ module Fontist
|
|
|
3
3
|
module System
|
|
4
4
|
# Platform override from environment (ONLY platform tags supported)
|
|
5
5
|
def self.platform_override
|
|
6
|
-
ENV
|
|
6
|
+
ENV.fetch("FONTIST_PLATFORM_OVERRIDE", nil)
|
|
7
7
|
end
|
|
8
8
|
|
|
9
9
|
def self.platform_override?
|
|
@@ -154,7 +154,7 @@ module Fontist
|
|
|
154
154
|
|
|
155
155
|
# Convert to comparable integer: major * 10000 + minor * 100 + patch
|
|
156
156
|
# This allows: 10.11.6 = 101106, 26.0.0 = 260000
|
|
157
|
-
major * 10000 + minor * 100 + patch
|
|
157
|
+
(major * 10000) + (minor * 100) + patch
|
|
158
158
|
end
|
|
159
159
|
|
|
160
160
|
def self.version_in_range?(min_version, max_version)
|