fontist 1.18.2 → 1.20.0
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/LICENSE.txt +1 -2
- data/README.adoc +28 -4
- 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/fontist.gemspec +3 -0
- data/lib/fontist/cli/class_options.rb +7 -0
- data/lib/fontist/cli.rb +1 -0
- data/lib/fontist/config.rb +23 -7
- data/lib/fontist/config_cli.rb +26 -8
- data/lib/fontist/errors.rb +2 -0
- data/lib/fontist/font.rb +50 -10
- data/lib/fontist/formula.rb +71 -3
- data/lib/fontist/formula_suggestion.rb +55 -0
- data/lib/fontist/version.rb +1 -1
- data/lib/fontist.rb +9 -1
- metadata +61 -2
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/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])
|
data/lib/fontist/cli.rb
CHANGED
@@ -27,6 +27,7 @@ module Fontist
|
|
27
27
|
STATUS_FONTCONFIG_NOT_FOUND = 14
|
28
28
|
STATUS_FONTCONFIG_FILE_NOT_FOUND = 15
|
29
29
|
STATUS_FONTIST_VERSION_ERROR = 15
|
30
|
+
STATUS_INVALID_CONFIG_ATTRIBUTE = 16
|
30
31
|
|
31
32
|
ERROR_TO_STATUS = {
|
32
33
|
Fontist::Errors::UnsupportedFontError => [STATUS_NON_SUPPORTED_FONT_ERROR],
|
data/lib/fontist/config.rb
CHANGED
@@ -15,42 +15,58 @@ module Fontist
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def set(key, value)
|
18
|
+
attr = key.to_sym
|
19
|
+
unless default_values.key?(attr)
|
20
|
+
raise Errors::InvalidConfigAttributeError,
|
21
|
+
"No such attribute '#{attr}' exists."
|
22
|
+
end
|
23
|
+
|
18
24
|
v = normalize_value(value)
|
19
|
-
|
25
|
+
if respond_to?("#{attr}=")
|
26
|
+
public_send("#{attr}=", v)
|
27
|
+
else
|
28
|
+
@custom_values[attr] = v
|
29
|
+
end
|
20
30
|
|
21
31
|
persist
|
22
32
|
end
|
23
33
|
|
24
34
|
def delete(key)
|
25
|
-
@custom_values.delete(key.
|
35
|
+
@custom_values.delete(key.to_sym)
|
26
36
|
|
27
37
|
persist
|
28
38
|
end
|
29
39
|
|
30
40
|
def default_value(key)
|
31
|
-
default_values[key.
|
41
|
+
default_values[key.to_sym]
|
32
42
|
end
|
33
43
|
|
34
44
|
def default_values
|
35
|
-
{
|
36
|
-
|
45
|
+
{ fonts_path: Fontist.fontist_path.join("fonts"),
|
46
|
+
open_timeout: 10,
|
47
|
+
read_timeout: 10 }
|
37
48
|
end
|
38
49
|
|
39
50
|
def persist
|
51
|
+
values = @custom_values.transform_keys(&:to_s)
|
40
52
|
FileUtils.mkdir_p(File.dirname(Fontist.config_path))
|
41
|
-
File.write(Fontist.config_path, YAML.dump(
|
53
|
+
File.write(Fontist.config_path, YAML.dump(values))
|
42
54
|
end
|
43
55
|
|
44
56
|
def load
|
45
57
|
@custom_values = load_config_file
|
46
58
|
end
|
47
59
|
|
60
|
+
def fonts_path=(value)
|
61
|
+
@custom_values[:fonts_path] = File.expand_path(value)
|
62
|
+
end
|
63
|
+
|
48
64
|
private
|
49
65
|
|
50
66
|
def load_config_file
|
51
67
|
return {} unless File.exist?(Fontist.config_path)
|
52
68
|
|
53
|
-
YAML.load_file(Fontist.config_path)
|
69
|
+
YAML.load_file(Fontist.config_path).transform_keys(&:to_sym)
|
54
70
|
end
|
55
71
|
|
56
72
|
def normalize_value(value)
|
data/lib/fontist/config_cli.rb
CHANGED
@@ -2,15 +2,19 @@ module Fontist
|
|
2
2
|
class ConfigCLI < Thor
|
3
3
|
include CLI::ClassOptions
|
4
4
|
|
5
|
-
STATUS_SUCCESS = 0
|
6
|
-
|
7
5
|
desc "show", "Show values of the current config"
|
8
6
|
def show
|
9
7
|
handle_class_options(options)
|
10
8
|
values = Config.instance.custom_values
|
11
|
-
|
12
|
-
|
13
|
-
|
9
|
+
|
10
|
+
if values.empty?
|
11
|
+
Fontist.ui.success("Config is empty.")
|
12
|
+
else
|
13
|
+
Fontist.ui.success("Current config:")
|
14
|
+
Fontist.ui.success(format_hash(values))
|
15
|
+
end
|
16
|
+
|
17
|
+
CLI::STATUS_SUCCESS
|
14
18
|
end
|
15
19
|
|
16
20
|
desc "set KEY VALUE", "Set the KEY attribute to VALUE in the current config"
|
@@ -18,7 +22,10 @@ module Fontist
|
|
18
22
|
handle_class_options(options)
|
19
23
|
Config.instance.set(key, value)
|
20
24
|
Fontist.ui.success("'#{key}' set to '#{value}'.")
|
21
|
-
STATUS_SUCCESS
|
25
|
+
CLI::STATUS_SUCCESS
|
26
|
+
rescue Errors::InvalidConfigAttributeError => e
|
27
|
+
Fontist.ui.error(e.message)
|
28
|
+
CLI::STATUS_INVALID_CONFIG_ATTRIBUTE
|
22
29
|
end
|
23
30
|
|
24
31
|
desc "delete KEY", "Delete the KEY attribute from the current config"
|
@@ -28,13 +35,24 @@ module Fontist
|
|
28
35
|
Fontist.ui.success(
|
29
36
|
"'#{key}' reset to default ('#{Config.instance.default_value(key)}').",
|
30
37
|
)
|
31
|
-
STATUS_SUCCESS
|
38
|
+
CLI::STATUS_SUCCESS
|
39
|
+
end
|
40
|
+
|
41
|
+
desc "keys", "Print all available config attributes"
|
42
|
+
def keys
|
43
|
+
handle_class_options(options)
|
44
|
+
Fontist.ui.say("Available keys:")
|
45
|
+
Config.instance.default_values.each do |key, value|
|
46
|
+
Fontist.ui.say("#{key} (default: #{value})")
|
47
|
+
end
|
48
|
+
CLI::STATUS_SUCCESS
|
32
49
|
end
|
33
50
|
|
34
51
|
private
|
35
52
|
|
36
53
|
def format_hash(hash)
|
37
|
-
|
54
|
+
h = hash.transform_keys(&:to_s)
|
55
|
+
YAML.dump(h).gsub(/^---.*$/, "").strip
|
38
56
|
end
|
39
57
|
end
|
40
58
|
end
|
data/lib/fontist/errors.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
|
@@ -193,7 +225,7 @@ module Fontist
|
|
193
225
|
def check_and_confirm_required_license(formula)
|
194
226
|
return @confirmation unless formula.license_required
|
195
227
|
|
196
|
-
show_license(formula
|
228
|
+
show_license(formula) unless @hide_licenses
|
197
229
|
return @confirmation if @confirmation.casecmp?("yes")
|
198
230
|
|
199
231
|
confirmation = ask_for_agreement
|
@@ -204,8 +236,8 @@ module Fontist
|
|
204
236
|
)
|
205
237
|
end
|
206
238
|
|
207
|
-
def show_license(
|
208
|
-
Fontist.ui.say(license_agrement_message(
|
239
|
+
def show_license(formula)
|
240
|
+
Fontist.ui.say(license_agrement_message(formula))
|
209
241
|
end
|
210
242
|
|
211
243
|
def ask_for_agreement
|
@@ -215,20 +247,28 @@ module Fontist
|
|
215
247
|
)
|
216
248
|
end
|
217
249
|
|
218
|
-
def license_agrement_message(
|
250
|
+
def license_agrement_message(formula)
|
251
|
+
human_name = human_name(formula)
|
252
|
+
|
219
253
|
<<~MSG
|
220
|
-
FONT LICENSE ACCEPTANCE REQUIRED FOR "#{
|
254
|
+
FONT LICENSE ACCEPTANCE REQUIRED FOR "#{human_name}":
|
221
255
|
|
222
256
|
Fontist can install this font if you accept its licensing conditions.
|
223
257
|
|
224
|
-
FONT LICENSE BEGIN ("#{
|
258
|
+
FONT LICENSE BEGIN ("#{human_name}")
|
225
259
|
-----------------------------------------------------------------------
|
226
|
-
#{license}
|
260
|
+
#{formula.license}
|
227
261
|
-----------------------------------------------------------------------
|
228
|
-
FONT LICENSE END ("#{
|
262
|
+
FONT LICENSE END ("#{human_name}")
|
229
263
|
MSG
|
230
264
|
end
|
231
265
|
|
266
|
+
def human_name(formula)
|
267
|
+
return formula.name if @by_formula
|
268
|
+
|
269
|
+
formula.font_by_name(@name).name
|
270
|
+
end
|
271
|
+
|
232
272
|
def update_fontconfig
|
233
273
|
return unless @update_fontconfig
|
234
274
|
|
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
|
@@ -89,7 +114,13 @@ module Fontist
|
|
89
114
|
end
|
90
115
|
|
91
116
|
def key
|
92
|
-
|
117
|
+
@key ||= {}
|
118
|
+
@key[@path] ||= key_from_path
|
119
|
+
end
|
120
|
+
|
121
|
+
def name
|
122
|
+
@name ||= {}
|
123
|
+
@name[key] ||= namespace.empty? ? base_name : "#{namespace}/#{base_name}"
|
93
124
|
end
|
94
125
|
|
95
126
|
def description
|
@@ -142,6 +173,12 @@ module Fontist
|
|
142
173
|
@data["instructions"]
|
143
174
|
end
|
144
175
|
|
176
|
+
def font_by_name(name)
|
177
|
+
fonts.find do |font|
|
178
|
+
font.name.casecmp?(name)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
145
182
|
def fonts_by_name(name)
|
146
183
|
fonts.select do |font|
|
147
184
|
font.name.casecmp?(name)
|
@@ -166,9 +203,40 @@ module Fontist
|
|
166
203
|
|
167
204
|
private
|
168
205
|
|
206
|
+
def real_path(path)
|
207
|
+
Dir.glob(path).first
|
208
|
+
end
|
209
|
+
|
169
210
|
def key_from_path
|
170
211
|
escaped = Regexp.escape("#{Fontist.formulas_path}/")
|
171
|
-
@path.sub(Regexp.new("^#{escaped}"), "").sub(/\.yml$/, "")
|
212
|
+
@path.sub(Regexp.new("^#{escaped}"), "").sub(/\.yml$/, "").to_s
|
213
|
+
end
|
214
|
+
|
215
|
+
def namespace
|
216
|
+
namespace_from_mappings || namespace_from_key
|
217
|
+
end
|
218
|
+
|
219
|
+
def namespace_from_mappings
|
220
|
+
parts = key.split("/")
|
221
|
+
namespace_from_key = parts.take(parts.size - 1).join("/")
|
222
|
+
NAMESPACES[namespace_from_key]
|
223
|
+
end
|
224
|
+
|
225
|
+
def namespace_from_key
|
226
|
+
parts = key.downcase.gsub("_", " ").split("/")
|
227
|
+
parts.take(parts.size - 1).map do |namespace|
|
228
|
+
namespace.split.map(&:capitalize).join(" ")
|
229
|
+
end.join("/")
|
230
|
+
end
|
231
|
+
|
232
|
+
def base_name
|
233
|
+
@data["name"] || base_name_from_key
|
234
|
+
end
|
235
|
+
|
236
|
+
def base_name_from_key
|
237
|
+
key.split("/").last
|
238
|
+
.downcase.gsub("_", " ")
|
239
|
+
.split.map(&:capitalize).join(" ")
|
172
240
|
end
|
173
241
|
|
174
242
|
def fonts_by_family
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require "fuzzy_match"
|
2
|
+
|
3
|
+
module Fontist
|
4
|
+
class FormulaSuggestion
|
5
|
+
MINIMUM_REQUIRED_SCORE = 0.6
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@fuzzy_match = prepare_search_engine
|
9
|
+
end
|
10
|
+
|
11
|
+
def find(name)
|
12
|
+
@fuzzy_match.find_all_with_score(normalize(name))
|
13
|
+
.tap { |res| Fontist.ui.debug(prettify_result(res)) }
|
14
|
+
.select { |_key, score, _| score >= MINIMUM_REQUIRED_SCORE }
|
15
|
+
.take(10)
|
16
|
+
.map(&:first)
|
17
|
+
.map { |x| Formula.find_by_key_or_name(x) }
|
18
|
+
.select(&:downloadable?)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def normalize(name)
|
24
|
+
name.gsub(" ", "_")
|
25
|
+
end
|
26
|
+
|
27
|
+
def prepare_search_engine
|
28
|
+
dict = Formula.all_keys
|
29
|
+
stop_words = namespaces(dict).map { |ns| /^#{Regexp.escape(ns)}/i }
|
30
|
+
|
31
|
+
FuzzyMatch.new(dict, stop_words: stop_words)
|
32
|
+
end
|
33
|
+
|
34
|
+
def namespaces(keys)
|
35
|
+
keys.map do |key|
|
36
|
+
parts = key.split("/")
|
37
|
+
parts.size
|
38
|
+
parts.take(parts.size - 1).join("/")
|
39
|
+
end.uniq
|
40
|
+
end
|
41
|
+
|
42
|
+
def prettify_result(result)
|
43
|
+
list = result.map do |key, dice, leve|
|
44
|
+
sprintf(
|
45
|
+
"%<dice>.3f %<leve>.3f %<key>s",
|
46
|
+
dice: dice,
|
47
|
+
leve: leve,
|
48
|
+
key: key,
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
52
|
+
"FuzzyMatch:\n#{list.join("\n")}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/fontist/version.rb
CHANGED
data/lib/fontist.rb
CHANGED
@@ -37,7 +37,7 @@ module Fontist
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def self.fonts_path
|
40
|
-
|
40
|
+
Pathname.new(config[:fonts_path])
|
41
41
|
end
|
42
42
|
|
43
43
|
def self.formulas_repo_path
|
@@ -151,4 +151,12 @@ module Fontist
|
|
151
151
|
def self.log_level=(level)
|
152
152
|
Fontist.ui.level = level
|
153
153
|
end
|
154
|
+
|
155
|
+
def self.interactive?
|
156
|
+
@interactive || false
|
157
|
+
end
|
158
|
+
|
159
|
+
def self.interactive=(bool)
|
160
|
+
@interactive = bool
|
161
|
+
end
|
154
162
|
end
|