fontist 1.19.0 → 1.21.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/deploy-pages.yml +48 -0
- data/.github/workflows/tebako-pack.yml +61 -0
- data/.github/workflows/test-and-release.yml +2 -1
- data/LICENSE.txt +1 -2
- data/README.adoc +24 -2
- data/docs/.gitignore +136 -0
- data/docs/.vitepress/config.ts +83 -0
- data/docs/guide/api-ruby.md +190 -0
- data/docs/guide/ci.md +29 -0
- data/docs/guide/fontconfig.md +23 -0
- data/docs/guide/index.md +67 -0
- data/docs/guide/proxy.md +47 -0
- data/docs/guide/why.md +7 -0
- data/docs/index.md +40 -0
- data/docs/package-lock.json +1791 -0
- data/docs/package.json +17 -0
- data/docs/public/hero.png +0 -0
- data/docs/public/logo.png +0 -0
- data/docs/reference/index.md +143 -0
- data/exe/fontist +1 -2
- data/fontist.gemspec +3 -0
- data/lib/fontist/cli/class_options.rb +7 -0
- data/lib/fontist/cli/thor_ext.rb +79 -0
- data/lib/fontist/cli.rb +2 -0
- data/lib/fontist/config.rb +2 -1
- data/lib/fontist/font.rb +55 -10
- data/lib/fontist/font_installer.rb +22 -51
- data/lib/fontist/formula.rb +77 -3
- data/lib/fontist/formula_suggestion.rb +55 -0
- data/lib/fontist/helpers.rb +2 -0
- data/lib/fontist/import/create_formula.rb +77 -35
- data/lib/fontist/import/formula_builder.rb +63 -81
- data/lib/fontist/import/google/api.rb +25 -0
- data/lib/fontist/import/google/create_google_formula.rb +89 -0
- data/lib/fontist/import/google_import.rb +63 -32
- data/lib/fontist/import/recursive_extraction.rb +0 -16
- data/lib/fontist/manifest/locations.rb +2 -0
- data/lib/fontist/resources/archive_resource.rb +55 -0
- data/lib/fontist/resources/google_resource.rb +64 -0
- data/lib/fontist/style_version.rb +4 -0
- data/lib/fontist/utils/cache.rb +16 -0
- data/lib/fontist/utils/downloader.rb +9 -2
- data/lib/fontist/utils/ui.rb +10 -2
- data/lib/fontist/version.rb +1 -1
- data/lib/fontist.rb +13 -1
- metadata +67 -6
- data/lib/fontist/import/google/new_fonts_fetcher.rb +0 -146
- data/lib/fontist/import/google/skiplist.yml +0 -12
- data/lib/fontist/import/google_check.rb +0 -27
data/docs/package.json
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
{
|
2
|
+
"scripts": {
|
3
|
+
"dev": "vitepress dev",
|
4
|
+
"build": "vitepress build",
|
5
|
+
"preview": "vitepress preview",
|
6
|
+
"format": "prettier -w ."
|
7
|
+
},
|
8
|
+
"type": "module",
|
9
|
+
"devDependencies": {
|
10
|
+
"@types/node": "latest",
|
11
|
+
"prettier": "^3.2.4",
|
12
|
+
"typescript": "latest",
|
13
|
+
"vitepress": "^1.0.0-rc.44",
|
14
|
+
"vue": "^3.4.15",
|
15
|
+
"vue-tsc": "^1.8.27"
|
16
|
+
}
|
17
|
+
}
|
Binary file
|
Binary file
|
@@ -0,0 +1,143 @@
|
|
1
|
+
# Fontist CLI reference
|
2
|
+
|
3
|
+
<!-- This can be converted to a folder & multiple pages at any time. -->
|
4
|
+
|
5
|
+
## `fontist cache`
|
6
|
+
|
7
|
+
The only subcommand available on `fontist cache` is `fontist cache clear`. It clears the `~/.fontist` cache.
|
8
|
+
|
9
|
+
```sh
|
10
|
+
fontist cache clear
|
11
|
+
```
|
12
|
+
|
13
|
+
```
|
14
|
+
Cache has been successfully removed.
|
15
|
+
```
|
16
|
+
|
17
|
+
## `fontist config`
|
18
|
+
|
19
|
+
`fontist config` lets you edit the Fontist config file from the command line instead of opening an editor. There are four subcommands available:
|
20
|
+
|
21
|
+
- `fontist config delete <key>`
|
22
|
+
- `fontist config keys`
|
23
|
+
- `fontist config set <key> <value>`
|
24
|
+
- `fontist config show`
|
25
|
+
|
26
|
+
Here's an example of these commands being used to edit the config file:
|
27
|
+
|
28
|
+
```sh
|
29
|
+
fontist config keys
|
30
|
+
fontist config set font_path /var/myfonts
|
31
|
+
fontist config delete font_path
|
32
|
+
fontist config show
|
33
|
+
```
|
34
|
+
|
35
|
+
```
|
36
|
+
$ fontist config keys
|
37
|
+
Available keys:
|
38
|
+
fonts_path (default: /home/octocat/.fontist/fonts)
|
39
|
+
open_timeout (default: 10)
|
40
|
+
read_timeout (default: 10)
|
41
|
+
|
42
|
+
$ fontist config set fonts_path /var/myfonts
|
43
|
+
'fonts_path' set to '/var/myfonts'.
|
44
|
+
|
45
|
+
$ fontist config delete fonts_path
|
46
|
+
'fonts_path' reset to default ('/home/octocat/.fontist/fonts').
|
47
|
+
|
48
|
+
$ fontist config show
|
49
|
+
Config is empty.
|
50
|
+
```
|
51
|
+
|
52
|
+
### Config reference
|
53
|
+
|
54
|
+
<!-- Move this into its own '/reference/config' page if this grows a lot. -->
|
55
|
+
|
56
|
+
- **`fonts_path`:** Where to put the `.ttf` files. Defaults to `~/.fontist/fonts`
|
57
|
+
|
58
|
+
- **`open_timeout`:** Defaults to 10.
|
59
|
+
|
60
|
+
- **`read_timeout`:** Defaults to 10.
|
61
|
+
|
62
|
+
## `fontist status [font-name]`
|
63
|
+
|
64
|
+
Prints the paths to a particular installed font or all fonts if the `font-name` is omitted. This searches **all fonts available on your system** even those not managed by Fontist.
|
65
|
+
|
66
|
+
```sh
|
67
|
+
fontist status
|
68
|
+
```
|
69
|
+
|
70
|
+
```
|
71
|
+
Fonts found at:
|
72
|
+
- /usr/share/fonts/truetype/ubuntu/UbuntuMono-B.ttf
|
73
|
+
- /usr/share/fonts/truetype/ubuntu/UbuntuMono-BI.ttf
|
74
|
+
- /usr/share/fonts/truetype/ubuntu/UbuntuMono-R.ttf
|
75
|
+
- /usr/share/fonts/truetype/ubuntu/UbuntuMono-RI.ttf
|
76
|
+
- /home/octocat/.fontist/fonts/Arial.ttf (from ms_truetype formula)
|
77
|
+
- /home/octocat/.fontist/fonts/ArialBI.ttf (from ms_truetype formula)
|
78
|
+
- /home/octocat/.fontist/fonts/ArialBd.ttf (from ms_truetype formula)
|
79
|
+
- /home/octocat/.fontist/fonts/ArialI.ttf (from ms_truetype formula)
|
80
|
+
```
|
81
|
+
|
82
|
+
Here's an example narrowed to a specific font:
|
83
|
+
|
84
|
+
```sh
|
85
|
+
fontist status "Open Sans"
|
86
|
+
```
|
87
|
+
|
88
|
+
```
|
89
|
+
Fonts found at:
|
90
|
+
- /home/octocat/.fontist/fonts/OpenSans-Bold.ttf (from open_sans formula)
|
91
|
+
- /home/octocat/.fontist/fonts/OpenSans-BoldItalic.ttf (from open_sans formula)
|
92
|
+
- /home/octocat/.fontist/fonts/OpenSans-Italic.ttf (from open_sans formula)
|
93
|
+
- /home/octocat/.fontist/fonts/OpenSans-Regular.ttf (from open_sans formula)
|
94
|
+
```
|
95
|
+
|
96
|
+
## `fontist list [font-name]`
|
97
|
+
|
98
|
+
Lists the installation status of `font-name` or all fonts if no font name provided.
|
99
|
+
|
100
|
+
```sh
|
101
|
+
fontist status
|
102
|
+
```
|
103
|
+
|
104
|
+
```
|
105
|
+
Fonts found at:
|
106
|
+
- /usr/share/fonts/truetype/ubuntu/UbuntuMono-B.ttf
|
107
|
+
- /usr/share/fonts/truetype/ubuntu/UbuntuMono-BI.ttf
|
108
|
+
- /usr/share/fonts/truetype/ubuntu/UbuntuMono-R.ttf
|
109
|
+
- /usr/share/fonts/truetype/ubuntu/UbuntuMono-RI.ttf
|
110
|
+
- /home/octocat/.fontist/fonts/Arial.ttf (from ms_truetype formula)
|
111
|
+
- /home/octocat/.fontist/fonts/ArialBI.ttf (from ms_truetype formula)
|
112
|
+
- /home/octocat/.fontist/fonts/ArialBd.ttf (from ms_truetype formula)
|
113
|
+
- /home/octocat/.fontist/fonts/ArialI.ttf (from ms_truetype formula)
|
114
|
+
```
|
115
|
+
|
116
|
+
Here's an example getting the status of a specific font:
|
117
|
+
|
118
|
+
```sh
|
119
|
+
fontist status "Fira Mono"
|
120
|
+
```
|
121
|
+
|
122
|
+
```
|
123
|
+
Font "Fira Mono" not found locally.
|
124
|
+
'Fira Mono' font is missing, please run `fontist install 'Fira Mono'` to download the font.
|
125
|
+
```
|
126
|
+
|
127
|
+
## Environment variables
|
128
|
+
|
129
|
+
### `FONTIST_PATH`
|
130
|
+
|
131
|
+
By default Fontist uses the `~/.fontist` directory to store fonts and its files. It can be changed with the `FONTIST_PATH` environment variable.
|
132
|
+
|
133
|
+
```sh
|
134
|
+
FONTIST_PATH=/var/fontist2 fontist update
|
135
|
+
```
|
136
|
+
|
137
|
+
## Excluded fonts
|
138
|
+
|
139
|
+
`fontist` excludes some fonts from usage when they break other software:
|
140
|
+
|
141
|
+
- `NISC18030.ttf` (GB18030 Bitmap) - macOS [fontist/fontist#344](https://github.com/fontist/fontist/issues/344)
|
142
|
+
|
143
|
+
[📑 View the up-to-date list of known problematic fonts on GitHub](https://github.com/fontist/fontist/blob/main/lib/fontist/exclude.yml)
|
data/exe/fontist
CHANGED
data/fontist.gemspec
CHANGED
@@ -31,6 +31,7 @@ Gem::Specification.new do |spec|
|
|
31
31
|
|
32
32
|
spec.add_runtime_dependency "down", "~> 5.0"
|
33
33
|
spec.add_runtime_dependency "extract_ttc", "~> 0.1"
|
34
|
+
spec.add_runtime_dependency "fuzzy_match", "~> 2.1"
|
34
35
|
spec.add_runtime_dependency "json", "~> 2.0"
|
35
36
|
spec.add_runtime_dependency "nokogiri", "~> 1.0"
|
36
37
|
spec.add_runtime_dependency "mime-types", "~> 3.0"
|
@@ -50,4 +51,6 @@ Gem::Specification.new do |spec|
|
|
50
51
|
spec.add_development_dependency "rubocop", "~> 1.22.1"
|
51
52
|
spec.add_development_dependency "rubocop-rails", "~> 2.9"
|
52
53
|
spec.add_development_dependency "rubocop-performance", "~> 1.10"
|
54
|
+
spec.add_development_dependency "vcr"
|
55
|
+
spec.add_development_dependency "webmock"
|
53
56
|
end
|
@@ -22,6 +22,12 @@ module Fontist
|
|
22
22
|
type: :boolean,
|
23
23
|
desc: "Avoid using cache during download"
|
24
24
|
|
25
|
+
base.class_option :interactive,
|
26
|
+
aliases: :i,
|
27
|
+
type: :boolean,
|
28
|
+
default: true,
|
29
|
+
desc: "Interactive mode"
|
30
|
+
|
25
31
|
base.class_option :formulas_path,
|
26
32
|
type: :string,
|
27
33
|
desc: "Path to formulas"
|
@@ -32,6 +38,7 @@ module Fontist
|
|
32
38
|
Fontist.preferred_family = options[:preferred_family]
|
33
39
|
Fontist.log_level = log_level(options)
|
34
40
|
Fontist.use_cache = !options[:no_cache]
|
41
|
+
Fontist.interactive = options[:interactive]
|
35
42
|
|
36
43
|
if options[:formulas_path]
|
37
44
|
Fontist.formulas_path = Pathname.new(options[:formulas_path])
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require "fontist/utils/ui"
|
2
|
+
|
3
|
+
module Fontist
|
4
|
+
module ThorExt
|
5
|
+
# Sources:
|
6
|
+
# - https://github.com/mattbrictson/gem/blob/main/lib/example/thor_ext.rb
|
7
|
+
# - https://mattbrictson.com/blog/fixing-thor-cli-behavior
|
8
|
+
#
|
9
|
+
# Configures Thor to behave more like a typical CLI, with better help
|
10
|
+
# and error handling.
|
11
|
+
#
|
12
|
+
# - Passing -h or --help to a command will show help for that command.
|
13
|
+
# - Unrecognized options will be treated as errors.
|
14
|
+
# - Error messages will be printed in red to stderr, without stack trace.
|
15
|
+
# - Errors will cause Thor to exit with a non-zero status.
|
16
|
+
#
|
17
|
+
# To take advantage of this behavior, your CLI should subclass Thor
|
18
|
+
# and extend this module.
|
19
|
+
#
|
20
|
+
# class CLI < Thor
|
21
|
+
# extend ThorExt::Start
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# Start your CLI with:
|
25
|
+
#
|
26
|
+
# CLI.start
|
27
|
+
#
|
28
|
+
# In tests, prevent Kernel.exit from being called when an error occurs,
|
29
|
+
# like this:
|
30
|
+
#
|
31
|
+
# CLI.start(args, exit_on_failure: false)
|
32
|
+
module Start
|
33
|
+
def self.extended(base)
|
34
|
+
super
|
35
|
+
base.check_unknown_options!
|
36
|
+
end
|
37
|
+
|
38
|
+
def start(given_args = ARGV, config = {})
|
39
|
+
config[:shell] ||= Thor::Base.shell.new
|
40
|
+
handle_help_switches(given_args) do |args|
|
41
|
+
dispatch(nil, args, nil, config)
|
42
|
+
end
|
43
|
+
rescue StandardError => e
|
44
|
+
handle_exception_on_start(e, config)
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
50
|
+
def handle_help_switches(given_args)
|
51
|
+
yield(given_args.dup)
|
52
|
+
rescue Thor::UnknownArgumentError => e
|
53
|
+
retry_with_args = []
|
54
|
+
|
55
|
+
if given_args.first == "help"
|
56
|
+
retry_with_args = ["help"] if given_args.length > 1
|
57
|
+
elsif e.unknown.intersect?(%w[-h --help])
|
58
|
+
retry_with_args = ["help", (given_args - e.unknown).first]
|
59
|
+
end
|
60
|
+
raise unless retry_with_args.any?
|
61
|
+
|
62
|
+
yield(retry_with_args)
|
63
|
+
end
|
64
|
+
|
65
|
+
def handle_exception_on_start(error, config)
|
66
|
+
return if error.is_a?(Errno::EPIPE)
|
67
|
+
raise if Fontist.ui.debug? || !config.fetch(:exit_on_failure, true)
|
68
|
+
|
69
|
+
message = error.message.to_s
|
70
|
+
if message.empty? || !error.is_a?(Thor::Error)
|
71
|
+
message.prepend("[#{error.class}] ")
|
72
|
+
end
|
73
|
+
config[:shell]&.say_error(message, :red)
|
74
|
+
exit(false)
|
75
|
+
end
|
76
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
data/lib/fontist/cli.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require "thor"
|
2
2
|
require "fontist/cli/class_options"
|
3
|
+
require "fontist/cli/thor_ext"
|
3
4
|
require "fontist/repo_cli"
|
4
5
|
require "fontist/cache_cli"
|
5
6
|
require "fontist/import_cli"
|
@@ -9,6 +10,7 @@ require "fontist/config_cli"
|
|
9
10
|
module Fontist
|
10
11
|
class CLI < Thor
|
11
12
|
include ClassOptions
|
13
|
+
extend ThorExt::Start
|
12
14
|
|
13
15
|
STATUS_SUCCESS = 0
|
14
16
|
STATUS_UNKNOWN_ERROR = 1
|
data/lib/fontist/config.rb
CHANGED
data/lib/fontist/font.rb
CHANGED
@@ -2,6 +2,7 @@ require "fontist/font_installer"
|
|
2
2
|
require "fontist/font_path"
|
3
3
|
require "fontist/formula_picker"
|
4
4
|
require "fontist/fontconfig"
|
5
|
+
require "fontist/formula_suggestion"
|
5
6
|
|
6
7
|
module Fontist
|
7
8
|
class Font
|
@@ -109,17 +110,48 @@ module Fontist
|
|
109
110
|
end
|
110
111
|
|
111
112
|
def install_formula
|
112
|
-
download_formula || raise_formula_not_found
|
113
|
+
download_formula || make_suggestions || raise_formula_not_found
|
113
114
|
end
|
114
115
|
|
115
116
|
def download_formula
|
116
|
-
formula = Formula.
|
117
|
+
formula = Formula.find_by_key_or_name(@name)
|
117
118
|
return unless formula
|
118
119
|
return unless formula.downloadable?
|
119
120
|
|
120
121
|
request_formula_installation(formula)
|
121
122
|
end
|
122
123
|
|
124
|
+
def make_suggestions
|
125
|
+
return unless Fontist.interactive?
|
126
|
+
|
127
|
+
suggestions = fuzzy_search_formulas
|
128
|
+
return if suggestions.empty?
|
129
|
+
|
130
|
+
choice = offer_to_choose(suggestions)
|
131
|
+
return unless choice
|
132
|
+
|
133
|
+
request_formula_installation(choice)
|
134
|
+
end
|
135
|
+
|
136
|
+
def fuzzy_search_formulas
|
137
|
+
@formula_suggestion ||= FormulaSuggestion.new
|
138
|
+
@formula_suggestion.find(@name)
|
139
|
+
end
|
140
|
+
|
141
|
+
def offer_to_choose(formulas)
|
142
|
+
Fontist.ui.say("Formula '#{@name}' not found. Did you mean?")
|
143
|
+
|
144
|
+
formulas.each_with_index do |formula, index|
|
145
|
+
Fontist.ui.say("[#{index}] #{formula.name}")
|
146
|
+
end
|
147
|
+
|
148
|
+
choice = Fontist.ui.ask("Please type number or " \
|
149
|
+
"press ENTER to skip installation:").chomp
|
150
|
+
return unless choice.to_i.to_s == choice
|
151
|
+
|
152
|
+
formulas[choice.to_i]
|
153
|
+
end
|
154
|
+
|
123
155
|
def raise_formula_not_found
|
124
156
|
raise Errors::FormulaNotFoundError.new(@name)
|
125
157
|
end
|
@@ -184,6 +216,11 @@ module Fontist
|
|
184
216
|
confirmation = check_and_confirm_required_license(formula)
|
185
217
|
paths = font_installer(formula).install(confirmation: confirmation)
|
186
218
|
|
219
|
+
if paths.nil? || paths.empty?
|
220
|
+
Fontist.ui.error("Fonts not found in formula #{formula}")
|
221
|
+
return
|
222
|
+
end
|
223
|
+
|
187
224
|
Fontist.ui.say("Fonts installed at:")
|
188
225
|
paths.each do |path|
|
189
226
|
Fontist.ui.say("- #{path}")
|
@@ -193,7 +230,7 @@ module Fontist
|
|
193
230
|
def check_and_confirm_required_license(formula)
|
194
231
|
return @confirmation unless formula.license_required
|
195
232
|
|
196
|
-
show_license(formula
|
233
|
+
show_license(formula) unless @hide_licenses
|
197
234
|
return @confirmation if @confirmation.casecmp?("yes")
|
198
235
|
|
199
236
|
confirmation = ask_for_agreement
|
@@ -204,8 +241,8 @@ module Fontist
|
|
204
241
|
)
|
205
242
|
end
|
206
243
|
|
207
|
-
def show_license(
|
208
|
-
Fontist.ui.say(license_agrement_message(
|
244
|
+
def show_license(formula)
|
245
|
+
Fontist.ui.say(license_agrement_message(formula))
|
209
246
|
end
|
210
247
|
|
211
248
|
def ask_for_agreement
|
@@ -215,20 +252,28 @@ module Fontist
|
|
215
252
|
)
|
216
253
|
end
|
217
254
|
|
218
|
-
def license_agrement_message(
|
255
|
+
def license_agrement_message(formula)
|
256
|
+
human_name = human_name(formula)
|
257
|
+
|
219
258
|
<<~MSG
|
220
|
-
FONT LICENSE ACCEPTANCE REQUIRED FOR "#{
|
259
|
+
FONT LICENSE ACCEPTANCE REQUIRED FOR "#{human_name}":
|
221
260
|
|
222
261
|
Fontist can install this font if you accept its licensing conditions.
|
223
262
|
|
224
|
-
FONT LICENSE BEGIN ("#{
|
263
|
+
FONT LICENSE BEGIN ("#{human_name}")
|
225
264
|
-----------------------------------------------------------------------
|
226
|
-
#{license}
|
265
|
+
#{formula.license}
|
227
266
|
-----------------------------------------------------------------------
|
228
|
-
FONT LICENSE END ("#{
|
267
|
+
FONT LICENSE END ("#{human_name}")
|
229
268
|
MSG
|
230
269
|
end
|
231
270
|
|
271
|
+
def human_name(formula)
|
272
|
+
return formula.name if @by_formula
|
273
|
+
|
274
|
+
formula.font_by_name(@name).name
|
275
|
+
end
|
276
|
+
|
232
277
|
def update_fontconfig
|
233
278
|
return unless @update_fontconfig
|
234
279
|
|
@@ -1,5 +1,7 @@
|
|
1
1
|
require "fontist/utils"
|
2
2
|
require "excavate"
|
3
|
+
require_relative "resources/archive_resource"
|
4
|
+
require_relative "resources/google_resource"
|
3
5
|
|
4
6
|
module Fontist
|
5
7
|
class FontInstaller
|
@@ -48,63 +50,32 @@ module Fontist
|
|
48
50
|
end
|
49
51
|
|
50
52
|
def install_font
|
51
|
-
fonts_paths =
|
53
|
+
fonts_paths = do_install_font
|
52
54
|
fonts_paths.empty? ? nil : fonts_paths
|
53
55
|
end
|
54
56
|
|
55
|
-
def
|
56
|
-
|
57
|
-
@temp_dir = Pathname.new(dir)
|
58
|
-
|
59
|
-
result = yield
|
60
|
-
|
61
|
-
@temp_dir = nil
|
62
|
-
|
63
|
-
result
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
def extract
|
68
|
-
archive = download_file(@formula.resources.first)
|
69
|
-
|
70
|
-
install_fonts_from_archive(archive)
|
71
|
-
end
|
72
|
-
|
73
|
-
def install_fonts_from_archive(archive)
|
74
|
-
Fontist.ui.say(%(Installing font "#{@formula.key}".))
|
57
|
+
def do_install_font
|
58
|
+
Fontist.ui.say(%(Installing from formula "#{@formula.key}".))
|
75
59
|
|
76
60
|
Array.new.tap do |fonts_paths|
|
77
|
-
|
61
|
+
resource.files(source_files) do |path|
|
78
62
|
fonts_paths << install_font_file(path) if font_file?(path)
|
79
63
|
end
|
80
64
|
end
|
81
65
|
end
|
82
66
|
|
83
|
-
def
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
result = try_download_file(request, source)
|
90
|
-
return result unless result.is_a?(Errors::InvalidResourceError)
|
91
|
-
|
92
|
-
errors << result
|
93
|
-
end
|
67
|
+
def resource
|
68
|
+
resource_class = if @formula.source == "google"
|
69
|
+
Resources::GoogleResource
|
70
|
+
else
|
71
|
+
Resources::ArchiveResource
|
72
|
+
end
|
94
73
|
|
95
|
-
|
74
|
+
resource_class.new(resource_options, no_progress: @no_progress)
|
96
75
|
end
|
97
76
|
|
98
|
-
def
|
99
|
-
|
100
|
-
request,
|
101
|
-
sha: source.sha256,
|
102
|
-
file_size: source.file_size,
|
103
|
-
progress_bar: !@no_progress
|
104
|
-
)
|
105
|
-
rescue Errors::InvalidResourceError => e
|
106
|
-
Fontist.ui.say(e.message)
|
107
|
-
e
|
77
|
+
def resource_options
|
78
|
+
@formula.resources.first
|
108
79
|
end
|
109
80
|
|
110
81
|
def font_file?(path)
|
@@ -116,16 +87,16 @@ module Fontist
|
|
116
87
|
end
|
117
88
|
|
118
89
|
def source_files
|
119
|
-
@source_files ||=
|
120
|
-
|
121
|
-
|
122
|
-
|
90
|
+
@source_files ||= fonts.flat_map do |font|
|
91
|
+
font.styles.map do |style|
|
92
|
+
style.source_font || style.font
|
93
|
+
end
|
123
94
|
end
|
124
95
|
end
|
125
96
|
|
126
|
-
def
|
127
|
-
|
128
|
-
|
97
|
+
def fonts
|
98
|
+
@formula.fonts.select do |font|
|
99
|
+
@font_name.nil? || font.name.casecmp?(@font_name)
|
129
100
|
end
|
130
101
|
end
|
131
102
|
|
data/lib/fontist/formula.rb
CHANGED
@@ -5,6 +5,11 @@ require "git"
|
|
5
5
|
|
6
6
|
module Fontist
|
7
7
|
class Formula
|
8
|
+
NAMESPACES = {
|
9
|
+
"sil" => "SIL",
|
10
|
+
"macos" => "macOS",
|
11
|
+
}.freeze
|
12
|
+
|
8
13
|
def self.update_formulas_repo
|
9
14
|
Update.call
|
10
15
|
end
|
@@ -15,6 +20,12 @@ module Fontist
|
|
15
20
|
end
|
16
21
|
end
|
17
22
|
|
23
|
+
def self.all_keys
|
24
|
+
Dir[Fontist.formulas_path.join("**/*.yml").to_s].map do |path|
|
25
|
+
path.sub("#{Fontist.formulas_path}/", "").sub(".yml", "")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
18
29
|
def self.find(font_name)
|
19
30
|
Indexes::FontIndex.from_yaml.load_formulas(font_name).first
|
20
31
|
end
|
@@ -45,6 +56,10 @@ module Fontist
|
|
45
56
|
end.flatten
|
46
57
|
end
|
47
58
|
|
59
|
+
def self.find_by_key_or_name(name)
|
60
|
+
find_by_key(name) || find_by_name(name)
|
61
|
+
end
|
62
|
+
|
48
63
|
def self.find_by_key(key)
|
49
64
|
path = Fontist.formulas_path.join("#{key}.yml")
|
50
65
|
return unless File.exist?(path)
|
@@ -52,6 +67,16 @@ module Fontist
|
|
52
67
|
new_from_file(path)
|
53
68
|
end
|
54
69
|
|
70
|
+
def self.find_by_name(name)
|
71
|
+
key = name_to_key(name)
|
72
|
+
|
73
|
+
find_by_key(key)
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.name_to_key(name)
|
77
|
+
name.downcase.gsub(" ", "_")
|
78
|
+
end
|
79
|
+
|
55
80
|
def self.find_by_font_file(font_file)
|
56
81
|
key = Indexes::FilenameIndex
|
57
82
|
.from_yaml
|
@@ -69,7 +94,7 @@ module Fontist
|
|
69
94
|
|
70
95
|
def initialize(data, path)
|
71
96
|
@data = data
|
72
|
-
@path = path
|
97
|
+
@path = real_path(path)
|
73
98
|
end
|
74
99
|
|
75
100
|
def to_index_formula
|
@@ -84,12 +109,24 @@ module Fontist
|
|
84
109
|
@data.key?("resources")
|
85
110
|
end
|
86
111
|
|
112
|
+
def source
|
113
|
+
return unless @data["resources"]
|
114
|
+
|
115
|
+
@data["resources"].values.first["source"]
|
116
|
+
end
|
117
|
+
|
87
118
|
def path
|
88
119
|
@path
|
89
120
|
end
|
90
121
|
|
91
122
|
def key
|
92
|
-
|
123
|
+
@key ||= {}
|
124
|
+
@key[@path] ||= key_from_path
|
125
|
+
end
|
126
|
+
|
127
|
+
def name
|
128
|
+
@name ||= {}
|
129
|
+
@name[key] ||= namespace.empty? ? base_name : "#{namespace}/#{base_name}"
|
93
130
|
end
|
94
131
|
|
95
132
|
def description
|
@@ -142,6 +179,12 @@ module Fontist
|
|
142
179
|
@data["instructions"]
|
143
180
|
end
|
144
181
|
|
182
|
+
def font_by_name(name)
|
183
|
+
fonts.find do |font|
|
184
|
+
font.name.casecmp?(name)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
145
188
|
def fonts_by_name(name)
|
146
189
|
fonts.select do |font|
|
147
190
|
font.name.casecmp?(name)
|
@@ -166,9 +209,40 @@ module Fontist
|
|
166
209
|
|
167
210
|
private
|
168
211
|
|
212
|
+
def real_path(path)
|
213
|
+
Dir.glob(path).first
|
214
|
+
end
|
215
|
+
|
169
216
|
def key_from_path
|
170
217
|
escaped = Regexp.escape("#{Fontist.formulas_path}/")
|
171
|
-
@path.sub(Regexp.new("^#{escaped}"), "").sub(/\.yml$/, "")
|
218
|
+
@path.sub(Regexp.new("^#{escaped}"), "").sub(/\.yml$/, "").to_s
|
219
|
+
end
|
220
|
+
|
221
|
+
def namespace
|
222
|
+
namespace_from_mappings || namespace_from_key
|
223
|
+
end
|
224
|
+
|
225
|
+
def namespace_from_mappings
|
226
|
+
parts = key.split("/")
|
227
|
+
namespace_from_key = parts.take(parts.size - 1).join("/")
|
228
|
+
NAMESPACES[namespace_from_key]
|
229
|
+
end
|
230
|
+
|
231
|
+
def namespace_from_key
|
232
|
+
parts = key.downcase.gsub("_", " ").split("/")
|
233
|
+
parts.take(parts.size - 1).map do |namespace|
|
234
|
+
namespace.split.map(&:capitalize).join(" ")
|
235
|
+
end.join("/")
|
236
|
+
end
|
237
|
+
|
238
|
+
def base_name
|
239
|
+
@data["name"] || base_name_from_key
|
240
|
+
end
|
241
|
+
|
242
|
+
def base_name_from_key
|
243
|
+
key.split("/").last
|
244
|
+
.downcase.gsub("_", " ")
|
245
|
+
.split.map(&:capitalize).join(" ")
|
172
246
|
end
|
173
247
|
|
174
248
|
def fonts_by_family
|