fontist 1.7.3 → 1.8.5
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/release.yml +38 -0
- data/.github/workflows/rspec.yml +58 -0
- data/README.md +48 -4
- data/{bin → exe}/fontist +0 -0
- data/fontist.gemspec +10 -7
- data/lib/fontist.rb +9 -2
- data/lib/fontist/cli.rb +64 -55
- data/lib/fontist/errors.rb +63 -12
- data/lib/fontist/font.rb +33 -64
- data/lib/fontist/font_installer.rb +118 -0
- data/lib/fontist/font_path.rb +29 -0
- data/lib/fontist/fontist_font.rb +3 -49
- data/lib/fontist/formula.rb +101 -35
- data/lib/fontist/formula_paths.rb +43 -0
- data/lib/fontist/helpers.rb +7 -0
- data/lib/fontist/import/create_formula.rb +3 -2
- data/lib/fontist/import/extractors.rb +4 -0
- data/lib/fontist/import/extractors/cpio_extractor.rb +39 -0
- data/lib/fontist/import/extractors/gzip_extractor.rb +27 -0
- data/lib/fontist/import/extractors/rpm_extractor.rb +45 -0
- data/lib/fontist/import/extractors/tar_extractor.rb +47 -0
- data/lib/fontist/import/google/skiplist.yml +3 -0
- data/lib/fontist/import/google_check.rb +1 -1
- data/lib/fontist/import/google_import.rb +3 -4
- data/lib/fontist/import/otfinfo_generate.rb +1 -1
- data/lib/fontist/import/recursive_extraction.rb +26 -8
- data/lib/fontist/import/sil_import.rb +99 -0
- data/lib/fontist/index.rb +11 -0
- data/lib/fontist/indexes/base_index.rb +82 -0
- data/lib/fontist/indexes/filename_index.rb +19 -0
- data/lib/fontist/indexes/font_index.rb +21 -0
- data/lib/fontist/indexes/index_formula.rb +36 -0
- data/lib/fontist/manifest/install.rb +4 -5
- data/lib/fontist/manifest/locations.rb +9 -1
- data/lib/fontist/system_font.rb +32 -62
- data/lib/fontist/system_index.rb +47 -5
- data/lib/fontist/utils.rb +5 -0
- data/lib/fontist/utils/cache.rb +12 -4
- data/lib/fontist/utils/cpio/cpio.rb +199 -0
- data/lib/fontist/utils/cpio_extractor.rb +47 -0
- data/lib/fontist/utils/exe_extractor.rb +1 -1
- data/lib/fontist/utils/gzip_extractor.rb +24 -0
- data/lib/fontist/utils/locking.rb +17 -0
- data/lib/fontist/utils/rpm_extractor.rb +37 -0
- data/lib/fontist/utils/tar_extractor.rb +61 -0
- data/lib/fontist/utils/zip_extractor.rb +1 -1
- data/lib/fontist/version.rb +1 -1
- metadata +74 -26
- data/.github/workflows/macosx.yml +0 -33
- data/.github/workflows/ubuntu.yml +0 -30
- data/.github/workflows/windows.yml +0 -32
- data/bin/check_google +0 -8
- data/bin/console +0 -11
- data/bin/convert_formulas +0 -8
- data/bin/generate_otfinfo +0 -8
- data/bin/import_google +0 -8
- data/bin/rspec +0 -29
- data/bin/setup +0 -7
- data/lib/fontist/font_formula.rb +0 -169
- data/lib/fontist/formula_template.rb +0 -122
- data/lib/fontist/formulas.rb +0 -56
- data/lib/fontist/registry.rb +0 -43
data/lib/fontist/errors.rb
CHANGED
@@ -1,16 +1,67 @@
|
|
1
1
|
module Fontist
|
2
2
|
module Errors
|
3
|
-
class
|
4
|
-
|
5
|
-
class
|
6
|
-
class
|
7
|
-
class
|
8
|
-
class
|
9
|
-
class
|
10
|
-
class
|
11
|
-
class
|
12
|
-
class
|
13
|
-
class
|
14
|
-
class
|
3
|
+
class GeneralError < StandardError; end
|
4
|
+
|
5
|
+
class BinaryCallError < GeneralError; end
|
6
|
+
class FontIndexCorrupted < GeneralError; end
|
7
|
+
class FontNotFoundError < GeneralError; end
|
8
|
+
class FormulaIndexNotFoundError < GeneralError; end
|
9
|
+
class InvalidResourceError < GeneralError; end
|
10
|
+
class LicensingError < GeneralError; end
|
11
|
+
class ManifestCouldNotBeFoundError < GeneralError; end
|
12
|
+
class ManifestCouldNotBeReadError < GeneralError; end
|
13
|
+
class MissingAttributeError < GeneralError; end
|
14
|
+
class TamperedFileError < GeneralError; end
|
15
|
+
class TimeoutError < GeneralError; end
|
16
|
+
class UnknownFontTypeError < GeneralError; end
|
17
|
+
class UnknownArchiveError < GeneralError; end
|
18
|
+
|
19
|
+
class FontError < GeneralError
|
20
|
+
attr_reader :font, :style
|
21
|
+
|
22
|
+
def initialize(msg, font = nil, style = nil)
|
23
|
+
@font = font
|
24
|
+
@style = style
|
25
|
+
|
26
|
+
super(msg)
|
27
|
+
end
|
28
|
+
|
29
|
+
def name
|
30
|
+
messages = []
|
31
|
+
messages << "Font name: '#{@font}'"
|
32
|
+
messages << "Style: '#{@style}'" if @style
|
33
|
+
messages.join("; ")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class MissingFontError < FontError
|
38
|
+
def initialize(font, style = nil)
|
39
|
+
name = prepare_name(font, style)
|
40
|
+
msg = "#{name} font is missing, please run `fontist install '#{font}'` to download the font."
|
41
|
+
|
42
|
+
super(msg, font, style)
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def prepare_name(font, style)
|
48
|
+
names = []
|
49
|
+
names << "'#{font}'"
|
50
|
+
names << "'#{style}'" if style
|
51
|
+
names.join(" ")
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class UnsupportedFontError < FontError
|
56
|
+
def initialize(font)
|
57
|
+
msg = <<~MSG.chomp
|
58
|
+
Font '#{font}' not found locally nor available in the Fontist formula repository.
|
59
|
+
Perhaps it is available at the latest Fontist formula repository.
|
60
|
+
You can update the formula repository using the command `fontist update` and try again.
|
61
|
+
MSG
|
62
|
+
|
63
|
+
super(msg, font)
|
64
|
+
end
|
65
|
+
end
|
15
66
|
end
|
16
67
|
end
|
data/lib/fontist/font.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
|
+
require "fontist/font_installer"
|
2
|
+
require "fontist/font_path"
|
3
|
+
|
1
4
|
module Fontist
|
2
5
|
class Font
|
3
6
|
def initialize(options = {})
|
4
|
-
@name = options
|
5
|
-
@confirmation = options
|
6
|
-
@force = options
|
7
|
+
@name = options[:name]
|
8
|
+
@confirmation = options[:confirmation] || "no"
|
9
|
+
@force = options[:force] || false
|
7
10
|
|
8
11
|
check_or_create_fontist_path!
|
9
12
|
end
|
@@ -20,10 +23,6 @@ module Fontist
|
|
20
23
|
new(name: name, confirmation: confirmation, force: force).install
|
21
24
|
end
|
22
25
|
|
23
|
-
def self.try_install(name, confirmation: "no")
|
24
|
-
new(name: name, confirmation: confirmation).try_install
|
25
|
-
end
|
26
|
-
|
27
26
|
def self.uninstall(name)
|
28
27
|
new(name: name).uninstall
|
29
28
|
end
|
@@ -37,43 +36,31 @@ module Fontist
|
|
37
36
|
end
|
38
37
|
|
39
38
|
def find
|
40
|
-
find_system_font || downloadable_font ||
|
41
|
-
Fontist::Errors::NonSupportedFontError
|
42
|
-
)
|
39
|
+
find_system_font || downloadable_font || raise_non_supported_font
|
43
40
|
end
|
44
41
|
|
45
42
|
def install
|
46
|
-
(find_system_font unless @force) || download_font ||
|
47
|
-
Fontist::Errors::NonSupportedFontError
|
48
|
-
)
|
49
|
-
end
|
50
|
-
|
51
|
-
def try_install
|
52
|
-
download_font
|
43
|
+
(find_system_font unless @force) || download_font || raise_non_supported_font
|
53
44
|
end
|
54
45
|
|
55
46
|
def uninstall
|
56
|
-
uninstall_font || downloadable_font ||
|
57
|
-
Fontist::Errors::NonSupportedFontError
|
58
|
-
)
|
47
|
+
uninstall_font || downloadable_font || raise_non_supported_font
|
59
48
|
end
|
60
49
|
|
61
50
|
def status
|
62
|
-
return
|
51
|
+
return installed_paths unless @name
|
63
52
|
|
64
|
-
|
65
|
-
Fontist::Errors::NonSupportedFontError
|
66
|
-
)
|
53
|
+
find_system_font || downloadable_font || raise_non_supported_font
|
67
54
|
end
|
68
55
|
|
69
56
|
def list
|
70
57
|
return all_list unless @name
|
71
58
|
|
72
|
-
font_list ||
|
59
|
+
font_list || raise_non_supported_font
|
73
60
|
end
|
74
61
|
|
75
62
|
def all
|
76
|
-
Fontist::Formula.all.
|
63
|
+
Fontist::Formula.all.map(&:fonts).flatten
|
77
64
|
end
|
78
65
|
|
79
66
|
private
|
@@ -87,9 +74,14 @@ module Fontist
|
|
87
74
|
return
|
88
75
|
end
|
89
76
|
|
77
|
+
print_paths(paths)
|
78
|
+
end
|
79
|
+
|
80
|
+
def print_paths(paths)
|
90
81
|
Fontist.ui.say("Fonts found at:")
|
91
82
|
paths.each do |path|
|
92
|
-
|
83
|
+
font_path = FontPath.new(path)
|
84
|
+
Fontist.ui.say(font_path.to_s)
|
93
85
|
end
|
94
86
|
end
|
95
87
|
|
@@ -101,7 +93,7 @@ module Fontist
|
|
101
93
|
end
|
102
94
|
|
103
95
|
def font_installer(formula)
|
104
|
-
|
96
|
+
FontInstaller.new(formula)
|
105
97
|
end
|
106
98
|
|
107
99
|
def formula
|
@@ -110,20 +102,14 @@ module Fontist
|
|
110
102
|
|
111
103
|
def downloadable_font
|
112
104
|
if formula
|
113
|
-
raise(
|
114
|
-
Fontist::Errors::MissingFontError,
|
115
|
-
"#{name} fonts are missing, please run " \
|
116
|
-
"`fontist install '#{name}'` to " \
|
117
|
-
"download the font."
|
118
|
-
)
|
105
|
+
raise Fontist::Errors::MissingFontError.new(name)
|
119
106
|
end
|
120
107
|
end
|
121
108
|
|
122
109
|
def download_font
|
123
110
|
if formula
|
124
111
|
check_and_confirm_required_license(formula)
|
125
|
-
paths = font_installer(formula).
|
126
|
-
confirmation: confirmation)
|
112
|
+
paths = font_installer(formula).install(confirmation: confirmation)
|
127
113
|
|
128
114
|
Fontist.ui.say("Fonts installed at:")
|
129
115
|
paths.each do |path|
|
@@ -136,7 +122,7 @@ module Fontist
|
|
136
122
|
if formula.license_required && !confirmation.casecmp("yes").zero?
|
137
123
|
@confirmation = show_license_and_ask_for_input(formula.license)
|
138
124
|
|
139
|
-
|
125
|
+
unless confirmation&.casecmp?("yes")
|
140
126
|
raise Fontist::Errors::LicensingError.new(
|
141
127
|
"Fontist will not download these fonts unless you accept the terms."
|
142
128
|
)
|
@@ -181,39 +167,18 @@ module Fontist
|
|
181
167
|
Fontist::FontistFont.find(name)
|
182
168
|
end
|
183
169
|
|
184
|
-
def
|
185
|
-
|
170
|
+
def installed_paths
|
171
|
+
print_paths(SystemFont.font_paths)
|
186
172
|
end
|
187
173
|
|
188
174
|
def all_formulas
|
189
|
-
Fontist::Formula.all
|
190
|
-
end
|
191
|
-
|
192
|
-
def font_status
|
193
|
-
return unless formula
|
194
|
-
|
195
|
-
statuses = installed_styles([formula])
|
196
|
-
statuses.empty? ? nil : statuses
|
197
|
-
end
|
198
|
-
|
199
|
-
def installed_styles(formulas)
|
200
|
-
filter_blank(formulas) do |formula|
|
201
|
-
filter_blank(formula.fonts) do |font|
|
202
|
-
filter_blank(font.styles) do |style|
|
203
|
-
path(style)
|
204
|
-
end
|
205
|
-
end
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
|
-
def filter_blank(elements)
|
210
|
-
elements.map { |e| [e, yield(e)] }
|
211
|
-
.to_h
|
212
|
-
.reject { |_k, v| v.nil? || v.empty? }
|
175
|
+
Fontist::Formula.all
|
213
176
|
end
|
214
177
|
|
215
178
|
def path(style)
|
216
|
-
font_paths.
|
179
|
+
font_paths.detect do |path|
|
180
|
+
File.basename(path) == style.font
|
181
|
+
end
|
217
182
|
end
|
218
183
|
|
219
184
|
def font_paths
|
@@ -247,5 +212,9 @@ module Fontist
|
|
247
212
|
def installed(style)
|
248
213
|
path(style) ? true : false
|
249
214
|
end
|
215
|
+
|
216
|
+
def raise_non_supported_font
|
217
|
+
raise Fontist::Errors::UnsupportedFontError.new(@name)
|
218
|
+
end
|
250
219
|
end
|
251
220
|
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require "fontist/utils"
|
2
|
+
|
3
|
+
module Fontist
|
4
|
+
class FontInstaller
|
5
|
+
include Utils::ZipExtractor
|
6
|
+
include Utils::ExeExtractor
|
7
|
+
include Utils::MsiExtractor
|
8
|
+
include Utils::SevenZipExtractor
|
9
|
+
include Utils::RpmExtractor
|
10
|
+
include Utils::GzipExtractor
|
11
|
+
include Utils::CpioExtractor
|
12
|
+
include Utils::TarExtractor
|
13
|
+
|
14
|
+
def initialize(formula)
|
15
|
+
@formula = formula
|
16
|
+
end
|
17
|
+
|
18
|
+
def install(confirmation:)
|
19
|
+
if @formula.license_required && !"yes".casecmp?(confirmation)
|
20
|
+
raise(Fontist::Errors::LicensingError)
|
21
|
+
end
|
22
|
+
|
23
|
+
reinitialize
|
24
|
+
install_font
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
attr_reader :formula
|
30
|
+
|
31
|
+
def reinitialize
|
32
|
+
@downloaded = false
|
33
|
+
end
|
34
|
+
|
35
|
+
def install_font
|
36
|
+
fonts_paths = run_in_temp_dir { extract }
|
37
|
+
fonts_paths.empty? ? nil : fonts_paths
|
38
|
+
end
|
39
|
+
|
40
|
+
def run_in_temp_dir
|
41
|
+
Dir.mktmpdir(nil, Dir.tmpdir) do |dir|
|
42
|
+
@temp_dir = Pathname.new(dir)
|
43
|
+
|
44
|
+
result = yield
|
45
|
+
|
46
|
+
@temp_dir = nil
|
47
|
+
|
48
|
+
result
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def extract
|
53
|
+
resource = @formula.resources.first
|
54
|
+
|
55
|
+
[@formula.extract].flatten.each do |operation|
|
56
|
+
resource = extract_by_operation(operation, resource)
|
57
|
+
end
|
58
|
+
|
59
|
+
fonts_paths = resource
|
60
|
+
|
61
|
+
fonts_paths
|
62
|
+
end
|
63
|
+
|
64
|
+
def extract_by_operation(operation, resource)
|
65
|
+
method = "#{operation.format}_extract"
|
66
|
+
if operation.options
|
67
|
+
send(method, resource, **operation.options.to_h)
|
68
|
+
else
|
69
|
+
send(method, resource)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def fonts_path
|
74
|
+
Fontist.fonts_path
|
75
|
+
end
|
76
|
+
|
77
|
+
def download_file(source)
|
78
|
+
url = source.urls.first
|
79
|
+
Fontist.ui.say(%(Downloading font "#{@formula.key}" from #{url}))
|
80
|
+
|
81
|
+
downloaded_file = Fontist::Utils::Downloader.download(
|
82
|
+
url,
|
83
|
+
sha: source.sha256,
|
84
|
+
file_size: source.file_size,
|
85
|
+
progress_bar: true
|
86
|
+
)
|
87
|
+
|
88
|
+
@downloaded = true
|
89
|
+
downloaded_file
|
90
|
+
end
|
91
|
+
|
92
|
+
def font_file?(filename)
|
93
|
+
source_files.include?(filename)
|
94
|
+
end
|
95
|
+
|
96
|
+
def source_files
|
97
|
+
@source_files ||= @formula.fonts.flat_map do |font|
|
98
|
+
font.styles.map do |style|
|
99
|
+
style.source_font || style.font
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def target_filename(source_filename)
|
105
|
+
target_filenames[source_filename]
|
106
|
+
end
|
107
|
+
|
108
|
+
def target_filenames
|
109
|
+
@target_filenames ||= @formula.fonts.flat_map do |font|
|
110
|
+
font.styles.map do |style|
|
111
|
+
source = style.source_font || style.font
|
112
|
+
target = style.font
|
113
|
+
[source, target]
|
114
|
+
end
|
115
|
+
end.to_h
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "fontist/indexes/filename_index"
|
2
|
+
|
3
|
+
module Fontist
|
4
|
+
class FontPath
|
5
|
+
def initialize(path)
|
6
|
+
@path = path
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_s
|
10
|
+
[].tap do |s|
|
11
|
+
s << "-"
|
12
|
+
s << @path
|
13
|
+
s << "(from #{formulas.join(' or ')} formula)" if formulas.any?
|
14
|
+
end.join(" ")
|
15
|
+
end
|
16
|
+
|
17
|
+
def formulas
|
18
|
+
@formulas ||= if fontist_font?
|
19
|
+
Indexes::FilenameIndex.from_yaml.load_index_formulas(File.basename(@path)).map(&:name)
|
20
|
+
else
|
21
|
+
[]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def fontist_font?
|
26
|
+
@path.start_with?(Fontist.fonts_path.to_s)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/fontist/fontist_font.rb
CHANGED
@@ -2,8 +2,6 @@ module Fontist
|
|
2
2
|
class FontistFont
|
3
3
|
def initialize(font_name:)
|
4
4
|
@font_name = font_name
|
5
|
-
|
6
|
-
check_and_register_font_formulas
|
7
5
|
end
|
8
6
|
|
9
7
|
def self.find(name)
|
@@ -11,60 +9,16 @@ module Fontist
|
|
11
9
|
end
|
12
10
|
|
13
11
|
def find
|
14
|
-
|
15
|
-
|
16
|
-
filenames = fonts_filenames
|
17
|
-
return if filenames.empty?
|
18
|
-
|
19
|
-
paths = font_paths.select do |path|
|
20
|
-
filenames.any? { |f| File.basename(path).casecmp?(f) }
|
21
|
-
end
|
12
|
+
styles = FormulaPaths.new(font_paths).find(@font_name)
|
13
|
+
return unless styles
|
22
14
|
|
23
|
-
|
15
|
+
styles.map { |x| x[:path] }
|
24
16
|
end
|
25
17
|
|
26
18
|
private
|
27
19
|
|
28
|
-
def fonts_filenames
|
29
|
-
fonts.map { |font| font.styles.map(&:font) }.flatten
|
30
|
-
end
|
31
|
-
|
32
|
-
def fonts
|
33
|
-
by_key || by_name || []
|
34
|
-
end
|
35
|
-
|
36
|
-
def by_key
|
37
|
-
_key, formula = formulas.detect do |key, _value|
|
38
|
-
key.to_s.casecmp?(@font_name)
|
39
|
-
end
|
40
|
-
|
41
|
-
return unless formula
|
42
|
-
|
43
|
-
formula.fonts
|
44
|
-
end
|
45
|
-
|
46
|
-
def by_name
|
47
|
-
_key, formula = formulas.detect do |_key, value|
|
48
|
-
value.fonts.map(&:name).map(&:downcase).include?(@font_name.downcase)
|
49
|
-
end
|
50
|
-
|
51
|
-
return unless formula
|
52
|
-
|
53
|
-
formula.fonts.select do |font|
|
54
|
-
font.name.casecmp?(@font_name)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def formulas
|
59
|
-
@formulas ||= Fontist::Registry.instance.formulas.to_h
|
60
|
-
end
|
61
|
-
|
62
20
|
def font_paths
|
63
21
|
Dir.glob(Fontist.fonts_path.join("**"))
|
64
22
|
end
|
65
|
-
|
66
|
-
def check_and_register_font_formulas
|
67
|
-
$check_and_register_font_formulas ||= Fontist::Formulas.register_formulas
|
68
|
-
end
|
69
23
|
end
|
70
24
|
end
|