fontist 3.0.23 → 3.0.25
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/lib/fontist/font_path.rb +1 -1
- data/lib/fontist/formula.rb +5 -5
- data/lib/fontist/indexes/base_font_collection_index.rb +1 -0
- data/lib/fontist/indexes/font_index.rb +8 -0
- data/lib/fontist/indexes/index_mixin.rb +63 -3
- data/lib/fontist/indexes/lookup_index.rb +34 -0
- data/lib/fontist/system_index.rb +25 -8
- data/lib/fontist/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7e161f1ace760cebffefd73f61835fef3abb2875972836c3ad7e82324a465d11
|
|
4
|
+
data.tar.gz: 85f425e3a050b0e9674e32b413d750bde0d40e4e34f3c261c6138dadc571e0a5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 282670c9e6c9ebc53dedbaa927e80259a489f44bc33392d388c977ad909209b721b354b7922a2190f0e7554221a63ca3c15a234a55b100e27bdce92cca1e496e
|
|
7
|
+
data.tar.gz: 46ca6895943eefe3a7dce37a6e4cf08241530b6dfacc9fef5233f259ea091ab9d94aac2d4bdd903cc468948d3783a6ceff66219fd04f3514576f88a4a62048ef
|
data/lib/fontist/font_path.rb
CHANGED
|
@@ -14,7 +14,7 @@ module Fontist
|
|
|
14
14
|
|
|
15
15
|
def formulas
|
|
16
16
|
@formulas ||= if fontist_font?
|
|
17
|
-
Indexes::FilenameIndex.
|
|
17
|
+
Indexes::FilenameIndex.lookup_index.load_index_formulas(File.basename(@path)).flat_map(&:name)
|
|
18
18
|
else
|
|
19
19
|
[]
|
|
20
20
|
end
|
data/lib/fontist/formula.rb
CHANGED
|
@@ -122,15 +122,15 @@ module Fontist
|
|
|
122
122
|
end
|
|
123
123
|
|
|
124
124
|
def find(font_name)
|
|
125
|
-
Indexes::FontIndex.
|
|
125
|
+
Indexes::FontIndex.lookup_index.load_formulas(font_name).first
|
|
126
126
|
end
|
|
127
127
|
|
|
128
128
|
def find_many(font_name)
|
|
129
|
-
Indexes::FontIndex.
|
|
129
|
+
Indexes::FontIndex.lookup_index.load_formulas(font_name)
|
|
130
130
|
end
|
|
131
131
|
|
|
132
132
|
def find_fonts(font_name)
|
|
133
|
-
formulas = Indexes::FontIndex.
|
|
133
|
+
formulas = Indexes::FontIndex.lookup_index.load_formulas(font_name)
|
|
134
134
|
|
|
135
135
|
formulas.map do |formula|
|
|
136
136
|
formula.all_fonts.select do |f|
|
|
@@ -140,7 +140,7 @@ module Fontist
|
|
|
140
140
|
end
|
|
141
141
|
|
|
142
142
|
def find_styles(font_name, style_name)
|
|
143
|
-
formulas = Indexes::FontIndex.
|
|
143
|
+
formulas = Indexes::FontIndex.lookup_index.load_formulas(font_name)
|
|
144
144
|
|
|
145
145
|
formulas.map do |formula|
|
|
146
146
|
formula.all_fonts.map do |f|
|
|
@@ -173,7 +173,7 @@ module Fontist
|
|
|
173
173
|
end
|
|
174
174
|
|
|
175
175
|
def find_by_font_file(font_file)
|
|
176
|
-
key = Indexes::FilenameIndex.
|
|
176
|
+
key = Indexes::FilenameIndex.lookup_index
|
|
177
177
|
.load_index_formulas(File.basename(font_file))
|
|
178
178
|
.flat_map(&:name)
|
|
179
179
|
.first
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
|
|
1
3
|
module Fontist
|
|
2
4
|
module Indexes
|
|
5
|
+
autoload :LookupIndex, "#{__dir__}/lookup_index"
|
|
6
|
+
|
|
3
7
|
# IndexMixin provides common functionality for font index classes.
|
|
4
8
|
#
|
|
5
9
|
# == Performance Optimization (Tech Debt)
|
|
@@ -72,9 +76,38 @@ module Fontist
|
|
|
72
76
|
# to force a fresh parse on next access
|
|
73
77
|
Fontist::FromFileCache.clear
|
|
74
78
|
|
|
75
|
-
# Delete the index file
|
|
76
|
-
# This is important for tests to
|
|
79
|
+
# Delete the index file and its lookup sidecar to force a
|
|
80
|
+
# rebuild on next access. This is important for tests to
|
|
81
|
+
# ensure clean state
|
|
77
82
|
FileUtils.rm_f(path)
|
|
83
|
+
FileUtils.rm_f("#{path}.json")
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Read-only lookups over the sidecar JSON beside the index
|
|
87
|
+
# file, which skips binding every entry into model objects. The
|
|
88
|
+
# sidecar is (re)written whenever the index file is written,
|
|
89
|
+
# and regenerated here when it is missing or stale.
|
|
90
|
+
def lookup_index
|
|
91
|
+
entries_hash = sidecar_entries || rebuild_sidecar_entries
|
|
92
|
+
normalizer = new.method(:normalize_key)
|
|
93
|
+
LookupIndex.new(entries_hash, normalizer: normalizer)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def sidecar_entries
|
|
97
|
+
sidecar_path = "#{path}.json"
|
|
98
|
+
return unless File.exist?(sidecar_path)
|
|
99
|
+
return if File.exist?(path) &&
|
|
100
|
+
File.mtime(sidecar_path) < File.mtime(path)
|
|
101
|
+
|
|
102
|
+
JSON.parse(File.read(sidecar_path))["entries"]
|
|
103
|
+
rescue JSON::ParserError, TypeError
|
|
104
|
+
nil
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def rebuild_sidecar_entries
|
|
108
|
+
entries_hash = from_file(path).entries_hash
|
|
109
|
+
File.write("#{path}.json", JSON.dump("entries" => entries_hash))
|
|
110
|
+
entries_hash
|
|
78
111
|
end
|
|
79
112
|
end
|
|
80
113
|
|
|
@@ -158,6 +191,19 @@ module Fontist
|
|
|
158
191
|
|
|
159
192
|
FileUtils.mkdir_p(File.dirname(file_path))
|
|
160
193
|
File.write(file_path, to_yaml)
|
|
194
|
+
write_lookup_sidecar(file_path)
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def write_lookup_sidecar(file_path)
|
|
198
|
+
File.write("#{file_path}.json",
|
|
199
|
+
JSON.dump("entries" => entries_hash))
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
# key -> formula paths, in the sidecar's JSON-friendly shape
|
|
203
|
+
def entries_hash
|
|
204
|
+
Array(entries).to_h do |entry|
|
|
205
|
+
[normalize_key(entry.key), entry.formula_path]
|
|
206
|
+
end
|
|
161
207
|
end
|
|
162
208
|
|
|
163
209
|
private
|
|
@@ -209,15 +255,29 @@ module Fontist
|
|
|
209
255
|
def create_and_add_entry(key, paths)
|
|
210
256
|
entry = FormulaKeyToPath.new(key: key, formula_path: paths)
|
|
211
257
|
entries << entry
|
|
258
|
+
@entries_lookup_id = nil
|
|
212
259
|
@index_build_cache[key] = entry if @index_build_cache
|
|
213
260
|
end
|
|
214
261
|
|
|
262
|
+
# O(1) key lookup over the entries; rebuilt whenever the entries
|
|
263
|
+
# array identity changes (rebuilds parse fresh instances, and
|
|
264
|
+
# in-place additions drop the cached hash)
|
|
265
|
+
def entries_lookup
|
|
266
|
+
entries_id = Array(entries).object_id
|
|
267
|
+
if @entries_lookup_id != entries_id
|
|
268
|
+
@entries_lookup_id = entries_id
|
|
269
|
+
@entries_lookup = Array(entries)
|
|
270
|
+
.group_by { |entry| normalize_key(entry.key) }
|
|
271
|
+
end
|
|
272
|
+
@entries_lookup
|
|
273
|
+
end
|
|
274
|
+
|
|
215
275
|
def index_formula(key)
|
|
216
276
|
Array(entries).detect { |f| normalize_key(f.key) == normalize_key(key) }
|
|
217
277
|
end
|
|
218
278
|
|
|
219
279
|
def index_formulas(key)
|
|
220
|
-
|
|
280
|
+
entries_lookup[normalize_key(key)] || []
|
|
221
281
|
end
|
|
222
282
|
|
|
223
283
|
def relative_formula_path(path)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module Fontist
|
|
2
|
+
module Indexes
|
|
3
|
+
# Read-only lookups over the JSON sidecar written beside an index
|
|
4
|
+
# file. Binding every index entry into model objects dominates the
|
|
5
|
+
# cost of loading an index; the sidecar holds the key-to-path map
|
|
6
|
+
# as plain data, and FormulaKeyToPath entries are materialized only
|
|
7
|
+
# for the requested key.
|
|
8
|
+
class LookupIndex
|
|
9
|
+
def initialize(entries_hash, normalizer:)
|
|
10
|
+
@entries_hash = entries_hash
|
|
11
|
+
@normalizer = normalizer
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def load_index_formulas(key)
|
|
15
|
+
[
|
|
16
|
+
FormulaKeyToPath.new(
|
|
17
|
+
key: key,
|
|
18
|
+
formula_path: paths_for(@normalizer.call(key)),
|
|
19
|
+
),
|
|
20
|
+
]
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def load_formulas(key)
|
|
24
|
+
load_index_formulas(key).flat_map(&:to_full)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def paths_for(normalized_key)
|
|
30
|
+
@entries_hash[normalized_key] || []
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
data/lib/fontist/system_index.rb
CHANGED
|
@@ -209,15 +209,13 @@ module Fontist
|
|
|
209
209
|
|
|
210
210
|
return nil if current_fonts.nil? || current_fonts.empty?
|
|
211
211
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
file.family_name&.casecmp?(font) && file.type&.casecmp?(style)
|
|
212
|
+
bucket = family_lookup(current_fonts)[font.to_s.downcase] || []
|
|
213
|
+
found_fonts =
|
|
214
|
+
if style.nil?
|
|
215
|
+
bucket
|
|
216
|
+
else
|
|
217
|
+
bucket.select { |file| file.type&.casecmp?(style) }
|
|
219
218
|
end
|
|
220
|
-
end
|
|
221
219
|
|
|
222
220
|
# Apply format filtering if specified
|
|
223
221
|
if format_spec&.has_constraints? && found_fonts
|
|
@@ -229,6 +227,25 @@ module Fontist
|
|
|
229
227
|
found_fonts.empty? ? nil : found_fonts
|
|
230
228
|
end
|
|
231
229
|
|
|
230
|
+
# Drops the cached family lookup; called when fonts are removed in
|
|
231
|
+
# place (a rebuild replaces the fonts array, which re-keys the
|
|
232
|
+
# lookup by itself)
|
|
233
|
+
def invalidate_lookups!
|
|
234
|
+
@family_lookup_fonts_id = nil
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
# O(1) family-name lookup over the indexed fonts; rebuilt whenever
|
|
238
|
+
# the fonts array identity changes
|
|
239
|
+
def family_lookup(current_fonts)
|
|
240
|
+
fonts_id = Array(current_fonts).object_id
|
|
241
|
+
if @family_lookup_fonts_id != fonts_id
|
|
242
|
+
@family_lookup_fonts_id = fonts_id
|
|
243
|
+
@family_lookup = Array(current_fonts)
|
|
244
|
+
.group_by { |file| file.family_name&.downcase }
|
|
245
|
+
end
|
|
246
|
+
@family_lookup
|
|
247
|
+
end
|
|
248
|
+
|
|
232
249
|
def index
|
|
233
250
|
if @read_only_mode && !fonts.nil?
|
|
234
251
|
return fonts
|
data/lib/fontist/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: fontist
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.0.
|
|
4
|
+
version: 3.0.25
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
@@ -452,6 +452,7 @@ files:
|
|
|
452
452
|
- lib/fontist/indexes/incremental_index_updater.rb
|
|
453
453
|
- lib/fontist/indexes/incremental_scanner.rb
|
|
454
454
|
- lib/fontist/indexes/index_mixin.rb
|
|
455
|
+
- lib/fontist/indexes/lookup_index.rb
|
|
455
456
|
- lib/fontist/indexes/preferred_family_font_index.rb
|
|
456
457
|
- lib/fontist/indexes/system_index.rb
|
|
457
458
|
- lib/fontist/indexes/user_index.rb
|