fontist 1.18.2 → 1.20.0
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/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
|