fontist 3.0.2 → 3.0.4
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/import/sil_importer.rb +2 -2
- data/lib/fontist/indexes/base_font_collection_index.rb +8 -0
- data/lib/fontist/macos/catalog/catalog_manager.rb +1 -1
- data/lib/fontist/manifest.rb +34 -3
- data/lib/fontist/system_index.rb +13 -4
- data/lib/fontist/utils/downloader.rb +1 -5
- data/lib/fontist/utils/user_agent.rb +95 -0
- data/lib/fontist/utils.rb +2 -1
- data/lib/fontist/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5b2847a2098f7dc8ca7652bf08d8e01d5f2a0e826230631bbba3d7cc01831933
|
|
4
|
+
data.tar.gz: 777c69708edc12acfaee0f01d492e9c3eb573822e428da489726fed8a52e4ac7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: da58a8c87b799c5db8241c5e951b26bd17a2e17d8bea327a4c479de1679c40feb6272bdc71a024e0fad6e4dd16743278e57a370c9d6ef021784a07968d6814a6
|
|
7
|
+
data.tar.gz: 22bb4499aa794f0534f850932df74aca65724e7019760fb7f6517233d1290cb2f5c2d3697e6046288acde4d21cb128b787f1d153aaaf50e1791c81a272d60b64
|
|
@@ -272,7 +272,7 @@ module Fontist
|
|
|
272
272
|
end
|
|
273
273
|
|
|
274
274
|
def font_links
|
|
275
|
-
html = URI.parse(ROOT).open.read
|
|
275
|
+
html = URI.parse(ROOT).open("User-Agent" => Fontist::Utils::UserAgent.random_user_agent).read
|
|
276
276
|
document = Nokogiri::HTML.parse(html)
|
|
277
277
|
document.css("table.products div.title > a")
|
|
278
278
|
end
|
|
@@ -392,7 +392,7 @@ module Fontist
|
|
|
392
392
|
end
|
|
393
393
|
|
|
394
394
|
def find_archive_url_by_page_uri(uri)
|
|
395
|
-
response = uri.open
|
|
395
|
+
response = uri.open("User-Agent" => Fontist::Utils::UserAgent.random_user_agent)
|
|
396
396
|
current_url = response.base_uri
|
|
397
397
|
html = response.read
|
|
398
398
|
document = Nokogiri::HTML.parse(html)
|
|
@@ -60,6 +60,14 @@ module Fontist
|
|
|
60
60
|
self
|
|
61
61
|
end
|
|
62
62
|
|
|
63
|
+
# Disable read-only mode, restoring normal index_changed? checks.
|
|
64
|
+
#
|
|
65
|
+
# @return [self] Returns self for chaining
|
|
66
|
+
def disable_read_only_mode
|
|
67
|
+
collection.disable_read_only_mode
|
|
68
|
+
self
|
|
69
|
+
end
|
|
70
|
+
|
|
63
71
|
# Returns all fonts in the index
|
|
64
72
|
#
|
|
65
73
|
# @return [Array<SystemIndexFont>] All indexed fonts
|
|
@@ -55,7 +55,7 @@ module Fontist
|
|
|
55
55
|
Fontist.ui.say("Downloading Font#{version} catalog from #{url}...") if Fontist.ui.respond_to?(:say)
|
|
56
56
|
|
|
57
57
|
URI(url).open(
|
|
58
|
-
"User-Agent" =>
|
|
58
|
+
"User-Agent" => Fontist::Utils::UserAgent.random_user_agent,
|
|
59
59
|
) do |response|
|
|
60
60
|
File.write(catalog_file, response.read)
|
|
61
61
|
end
|
data/lib/fontist/manifest.rb
CHANGED
|
@@ -33,9 +33,15 @@ module Fontist
|
|
|
33
33
|
def style_paths(locations: false)
|
|
34
34
|
ary = Array(styles)
|
|
35
35
|
(ary.empty? ? [nil] : ary).flat_map do |style|
|
|
36
|
-
find_font_with_name(name, style)
|
|
37
|
-
|
|
36
|
+
paths = find_font_with_name(name, style)
|
|
37
|
+
|
|
38
|
+
if paths.nil? && locations
|
|
39
|
+
try_install_missing_font
|
|
40
|
+
paths = find_font_with_name(name, style)
|
|
41
|
+
raise Errors::MissingFontError.new(name, style) if paths.nil?
|
|
38
42
|
end
|
|
43
|
+
|
|
44
|
+
paths
|
|
39
45
|
end.compact
|
|
40
46
|
end
|
|
41
47
|
|
|
@@ -96,6 +102,27 @@ module Fontist
|
|
|
96
102
|
|
|
97
103
|
private
|
|
98
104
|
|
|
105
|
+
def try_install_missing_font
|
|
106
|
+
Fontist.ui.debug("self-healing install attempt for #{name.inspect}")
|
|
107
|
+
Fontist::Font.install(
|
|
108
|
+
name,
|
|
109
|
+
force: true,
|
|
110
|
+
confirmation: "no",
|
|
111
|
+
no_progress: true,
|
|
112
|
+
hide_licenses: true,
|
|
113
|
+
format_spec: format_spec,
|
|
114
|
+
)
|
|
115
|
+
rescue Fontist::Errors::FontError,
|
|
116
|
+
Fontist::Errors::LicensingError,
|
|
117
|
+
Fontist::Errors::PlatformMismatchError,
|
|
118
|
+
Fontist::Errors::FormulaIndexNotFoundError => e
|
|
119
|
+
Fontist.ui.debug(
|
|
120
|
+
"self-healing install for #{name.inspect} " \
|
|
121
|
+
"failed: #{e.class}: #{e.message}",
|
|
122
|
+
)
|
|
123
|
+
nil
|
|
124
|
+
end
|
|
125
|
+
|
|
99
126
|
def validate_location_parameter!(location)
|
|
100
127
|
return unless location
|
|
101
128
|
return if location.is_a?(Symbol)
|
|
@@ -183,7 +210,11 @@ module Fontist
|
|
|
183
210
|
|
|
184
211
|
yield
|
|
185
212
|
ensure
|
|
186
|
-
# Always
|
|
213
|
+
# Always restore normal mode after the operation so the read-only flag
|
|
214
|
+
# does not leak across calls and turn the singletons effectively stale.
|
|
215
|
+
Fontist::Indexes::FontistIndex.instance.disable_read_only_mode
|
|
216
|
+
Fontist::Indexes::UserIndex.instance.disable_read_only_mode
|
|
217
|
+
Fontist::Indexes::SystemIndex.instance.disable_read_only_mode
|
|
187
218
|
Fontist::SystemFont.disable_find_styles_cache
|
|
188
219
|
end
|
|
189
220
|
|
data/lib/fontist/system_index.rb
CHANGED
|
@@ -229,11 +229,12 @@ module Fontist
|
|
|
229
229
|
end
|
|
230
230
|
|
|
231
231
|
def index
|
|
232
|
-
# Fast path: if read_only mode is set, skip index_changed? check entirely
|
|
233
|
-
# But we still need to build
|
|
234
|
-
|
|
232
|
+
# Fast path: if read_only mode is set, skip index_changed? check entirely.
|
|
233
|
+
# But we still need to build on first access — treat an empty fonts list
|
|
234
|
+
# the same as nil, since Lutaml initializes `instances :fonts` to `[]`
|
|
235
|
+
# rather than nil when the on-disk index file is absent.
|
|
236
|
+
if @read_only_mode && !fonts.nil? && !fonts.empty?
|
|
235
237
|
return fonts
|
|
236
|
-
# Fall through to build the index on first access
|
|
237
238
|
end
|
|
238
239
|
|
|
239
240
|
return fonts unless index_changed?
|
|
@@ -257,6 +258,14 @@ module Fontist
|
|
|
257
258
|
self
|
|
258
259
|
end
|
|
259
260
|
|
|
261
|
+
# Disable read-only mode so future `index` calls go through
|
|
262
|
+
# `index_changed?` again. Paired with `read_only_mode` to scope the
|
|
263
|
+
# optimization to a single block (see Manifest.with_performance_optimizations).
|
|
264
|
+
def disable_read_only_mode
|
|
265
|
+
@read_only_mode = false
|
|
266
|
+
self
|
|
267
|
+
end
|
|
268
|
+
|
|
260
269
|
def index_changed?
|
|
261
270
|
return true if fonts.nil? || fonts.empty?
|
|
262
271
|
return false if @index_check_done # Skip if already verified in this session
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
module Fontist
|
|
2
2
|
module Utils
|
|
3
3
|
class Downloader
|
|
4
|
-
DEFAULT_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) " \
|
|
5
|
-
"AppleWebKit/537.36 (KHTML, like Gecko) " \
|
|
6
|
-
"Chrome/131.0.0.0 Safari/537.36".freeze
|
|
7
|
-
|
|
8
4
|
class << self
|
|
9
5
|
def download(*args)
|
|
10
6
|
new(*args).download
|
|
@@ -143,7 +139,7 @@ module Fontist
|
|
|
143
139
|
obj.headers &&
|
|
144
140
|
obj.headers.to_h.to_h { |k, v| [k.to_s, v] }) || {} # rubocop:disable Style/HashTransformKeys, Metrics/LineLength
|
|
145
141
|
|
|
146
|
-
|
|
142
|
+
Utils::UserAgent.browser_headers.merge(formula_headers)
|
|
147
143
|
end
|
|
148
144
|
|
|
149
145
|
def extract_raw_url
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Fontist
|
|
4
|
+
module Utils
|
|
5
|
+
module UserAgent
|
|
6
|
+
PROFILES = [
|
|
7
|
+
{
|
|
8
|
+
user_agent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) " \
|
|
9
|
+
"AppleWebKit/537.36 (KHTML, like Gecko) " \
|
|
10
|
+
"Chrome/131.0.0.0 Safari/537.36",
|
|
11
|
+
platform: '"macOS"',
|
|
12
|
+
chrome_version: "131",
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
user_agent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " \
|
|
16
|
+
"AppleWebKit/537.36 (KHTML, like Gecko) " \
|
|
17
|
+
"Chrome/130.0.0.0 Safari/537.36",
|
|
18
|
+
platform: '"Windows"',
|
|
19
|
+
chrome_version: "130",
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
user_agent: "Mozilla/5.0 (X11; Linux x86_64) " \
|
|
23
|
+
"AppleWebKit/537.36 (KHTML, like Gecko) " \
|
|
24
|
+
"Chrome/132.0.0.0 Safari/537.36",
|
|
25
|
+
platform: '"Linux"',
|
|
26
|
+
chrome_version: "132",
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
user_agent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) " \
|
|
30
|
+
"AppleWebKit/537.36 (KHTML, like Gecko) " \
|
|
31
|
+
"Chrome/130.0.0.0 Safari/537.36",
|
|
32
|
+
platform: '"macOS"',
|
|
33
|
+
chrome_version: "130",
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
user_agent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " \
|
|
37
|
+
"AppleWebKit/537.36 (KHTML, like Gecko) " \
|
|
38
|
+
"Chrome/132.0.0.0 Safari/537.36",
|
|
39
|
+
platform: '"Windows"',
|
|
40
|
+
chrome_version: "132",
|
|
41
|
+
},
|
|
42
|
+
].freeze
|
|
43
|
+
|
|
44
|
+
ACCEPT = "text/html,application/xhtml+xml,application/xml;q=0.9," \
|
|
45
|
+
"image/avif,image/webp,image/apng,*/*;q=0.8," \
|
|
46
|
+
"application/signed-exchange;v=b3;q=0.7"
|
|
47
|
+
|
|
48
|
+
ACCEPT_LANGUAGE = "en-US,en;q=0.9"
|
|
49
|
+
|
|
50
|
+
STATIC_HEADERS = {
|
|
51
|
+
"Accept" => ACCEPT,
|
|
52
|
+
"Accept-Language" => ACCEPT_LANGUAGE,
|
|
53
|
+
"Cache-Control" => "no-cache",
|
|
54
|
+
"Pragma" => "no-cache",
|
|
55
|
+
"Sec-Ch-Ua-Mobile" => "?0",
|
|
56
|
+
"Sec-Fetch-Dest" => "document",
|
|
57
|
+
"Sec-Fetch-Mode" => "navigate",
|
|
58
|
+
"Sec-Fetch-Site" => "cross-site",
|
|
59
|
+
"Sec-Fetch-User" => "?1",
|
|
60
|
+
"Upgrade-Insecure-Requests" => "1",
|
|
61
|
+
}.freeze
|
|
62
|
+
|
|
63
|
+
class << self
|
|
64
|
+
def random_profile
|
|
65
|
+
PROFILES.sample
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def browser_headers
|
|
69
|
+
profile = random_profile
|
|
70
|
+
build_headers(profile)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def random_user_agent
|
|
74
|
+
random_profile[:user_agent]
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
private
|
|
78
|
+
|
|
79
|
+
def build_headers(profile)
|
|
80
|
+
STATIC_HEADERS.merge(
|
|
81
|
+
"User-Agent" => profile[:user_agent],
|
|
82
|
+
"Sec-Ch-Ua" => build_sec_ch_ua(profile[:chrome_version]),
|
|
83
|
+
"Sec-Ch-Ua-Platform" => profile[:platform],
|
|
84
|
+
)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def build_sec_ch_ua(chrome_version)
|
|
88
|
+
"\"Google Chrome\";v=\"#{chrome_version}\", " \
|
|
89
|
+
"\"Chromium\";v=\"#{chrome_version}\", " \
|
|
90
|
+
"\"Not_A Brand\";v=\"24\""
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
data/lib/fontist/utils.rb
CHANGED
|
@@ -9,6 +9,7 @@ module Fontist
|
|
|
9
9
|
autoload :Locking, "#{__dir__}/utils/locking"
|
|
10
10
|
autoload :System, "#{__dir__}/utils/system"
|
|
11
11
|
autoload :UI, "#{__dir__}/utils/ui"
|
|
12
|
+
autoload :UserAgent, "#{__dir__}/utils/user_agent"
|
|
12
13
|
|
|
13
14
|
# Converts a glob pattern to case-insensitive by replacing each
|
|
14
15
|
# alphabetic character with a character class [aA]
|
|
@@ -70,7 +71,7 @@ module Fontist
|
|
|
70
71
|
|
|
71
72
|
# On case-insensitive filesystems (Windows, macOS), use simple patterns
|
|
72
73
|
# On case-sensitive filesystems (Linux), use character class patterns
|
|
73
|
-
if %i[windows
|
|
74
|
+
if %i[windows macos].include?(Fontist::Utils::System.user_os)
|
|
74
75
|
# Case-insensitive filesystem - simple patterns work fine
|
|
75
76
|
extensions.map { |ext| File.join(prefix, "*.#{ext}") }
|
|
76
77
|
else
|
data/lib/fontist/version.rb
CHANGED
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: 3.0.
|
|
4
|
+
version: 3.0.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-05-
|
|
11
|
+
date: 2026-05-15 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: down
|
|
@@ -509,6 +509,7 @@ files:
|
|
|
509
509
|
- lib/fontist/utils/locking.rb
|
|
510
510
|
- lib/fontist/utils/system.rb
|
|
511
511
|
- lib/fontist/utils/ui.rb
|
|
512
|
+
- lib/fontist/utils/user_agent.rb
|
|
512
513
|
- lib/fontist/validate_cli.rb
|
|
513
514
|
- lib/fontist/validation.rb
|
|
514
515
|
- lib/fontist/validator.rb
|