fontist 1.9.0 → 1.11.1

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.
@@ -7,8 +7,8 @@ module Fontist
7
7
  end
8
8
 
9
9
  def call
10
- style = { family_name: @info["Preferred family"] || @info["Family"],
11
- style: @info["Preferred subfamily"] || @info["Subfamily"],
10
+ style = { family_name: @info["Family"],
11
+ style: @info["Subfamily"],
12
12
  full_name: @info["Full name"],
13
13
  post_script_name: @info["PostScript name"],
14
14
  version: version(@info["Version"]),
@@ -16,6 +16,14 @@ module Fontist
16
16
  filename: File.basename(@path),
17
17
  copyright: @info["Copyright"] }
18
18
 
19
+ if @info["Preferred family"]
20
+ style[:preferred_family_name] = @info["Preferred family"]
21
+ end
22
+
23
+ if @info["Preferred subfamily"]
24
+ style[:preferred_style] = @info["Preferred subfamily"]
25
+ end
26
+
19
27
  OpenStruct.new(style)
20
28
  end
21
29
 
@@ -2,6 +2,12 @@
2
2
  {
3
3
  family_name: "<%= s.family_name %>",
4
4
  style: "<%= s.style %>",
5
+ <%- if s.preferred_family_name -%>
6
+ preferred_family_name: "<%= s.preferred_family_name %>",
7
+ <%- end -%>
8
+ <%- if s.preferred_style -%>
9
+ preferred_type: "<%= s.preferred_style %>",
10
+ <%- end -%>
5
11
  full_name: "<%= s.full_name %>",
6
12
  <%- if s.post_script_name -%>
7
13
  post_script_name: "<%= s.post_script_name %>",
data/lib/fontist/index.rb CHANGED
@@ -19,25 +19,28 @@ module Fontist
19
19
  end
20
20
 
21
21
  def self.do_rebuild_for_main_repo_with
22
- Fontist.formula_index_path = Fontist.formulas_repo_path.join("index.yml")
22
+ Fontist.formula_preferred_family_index_path =
23
+ Fontist.formulas_repo_path.join("index.yml")
23
24
  Fontist.formula_filename_index_path =
24
25
  Fontist.formulas_repo_path.join("filename_index.yml")
25
26
 
26
27
  rebuild
27
28
 
28
- Fontist.formula_index_path = nil
29
+ Fontist.formula_preferred_family_index_path = nil
29
30
  Fontist.formula_filename_index_path = nil
30
31
  end
31
32
 
32
33
  def self.rebuild
33
- Fontist::Indexes::FontIndex.rebuild
34
+ Fontist::Indexes::DefaultFamilyFontIndex.rebuild
35
+ Fontist::Indexes::PreferredFamilyFontIndex.rebuild
34
36
  Fontist::Indexes::FilenameIndex.rebuild
35
37
 
36
38
  reset_cache
37
39
  end
38
40
 
39
41
  def self.reset_cache
40
- Fontist::Indexes::FontIndex.reset_cache
42
+ Fontist::Indexes::DefaultFamilyFontIndex.reset_cache
43
+ Fontist::Indexes::PreferredFamilyFontIndex.reset_cache
41
44
  Fontist::Indexes::FilenameIndex.reset_cache
42
45
  end
43
46
  end
@@ -0,0 +1,21 @@
1
+ require_relative "base_index"
2
+
3
+ module Fontist
4
+ module Indexes
5
+ class DefaultFamilyFontIndex < BaseIndex
6
+ def self.path
7
+ Fontist.formula_index_path
8
+ end
9
+
10
+ def add_formula(formula)
11
+ formula.fonts.each do |font|
12
+ add_index_formula(font.name, formula.to_index_formula)
13
+ end
14
+ end
15
+
16
+ def normalize_key(key)
17
+ key.downcase
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,21 +1,16 @@
1
- require_relative "base_index"
1
+ require_relative "default_family_font_index"
2
+ require_relative "preferred_family_font_index"
2
3
 
3
4
  module Fontist
4
5
  module Indexes
5
- class FontIndex < BaseIndex
6
- def self.path
7
- Fontist.formula_index_path
8
- end
9
-
10
- def add_formula(formula)
11
- formula.fonts.each do |font|
12
- add_index_formula(font.name, formula.to_index_formula)
6
+ class FontIndex
7
+ def self.from_yaml
8
+ if Fontist.preferred_family?
9
+ PreferredFamilyFontIndex.from_yaml
10
+ else
11
+ DefaultFamilyFontIndex.from_yaml
13
12
  end
14
13
  end
15
-
16
- def normalize_key(key)
17
- key.downcase
18
- end
19
14
  end
20
15
  end
21
16
  end
@@ -0,0 +1,24 @@
1
+ require_relative "base_index"
2
+
3
+ module Fontist
4
+ module Indexes
5
+ class PreferredFamilyFontIndex < BaseIndex
6
+ def self.path
7
+ Fontist.formula_preferred_family_index_path
8
+ end
9
+
10
+ def add_formula(formula)
11
+ formula.fonts.each do |font|
12
+ font.styles.each do |style|
13
+ font_name = style.preferred_family_name || font.name
14
+ add_index_formula(font_name, formula.to_index_formula)
15
+ end
16
+ end
17
+ end
18
+
19
+ def normalize_key(key)
20
+ key.downcase
21
+ end
22
+ end
23
+ end
24
+ end
data/lib/fontist/repo.rb CHANGED
@@ -29,6 +29,12 @@ module Fontist
29
29
  Index.rebuild
30
30
  end
31
31
 
32
+ def list
33
+ Dir.glob(Fontist.private_formulas_path.join("*"))
34
+ .select { |path| File.directory?(path) }
35
+ .map { |path| File.basename(path) }
36
+ end
37
+
32
38
  private
33
39
 
34
40
  def ensure_private_formulas_path_exists
@@ -1,7 +1,8 @@
1
1
  module Fontist
2
2
  class RepoCLI < Thor
3
3
  desc "setup NAME URL",
4
- "Setup a custom fontist repo named NAME for the repository at URL"
4
+ "Setup a custom fontist repo named NAME for the repository at URL " \
5
+ "and fetches its formulas"
5
6
  def setup(name, url)
6
7
  Repo.setup(name, url)
7
8
  Fontist.ui.success(
@@ -32,6 +33,14 @@ module Fontist
32
33
  handle_repo_not_found(name)
33
34
  end
34
35
 
36
+ desc "list", "List fontist repos"
37
+ def list
38
+ Repo.list.each do |name|
39
+ Fontist.ui.say(name)
40
+ end
41
+ CLI::STATUS_SUCCESS
42
+ end
43
+
35
44
  private
36
45
 
37
46
  def handle_repo_not_found(name)
@@ -3,10 +3,9 @@ require_relative "formula_paths"
3
3
 
4
4
  module Fontist
5
5
  class SystemFont
6
- def initialize(font:, style: nil, sources: nil)
6
+ def initialize(font:, style: nil)
7
7
  @font = font
8
8
  @style = style
9
- @user_sources = sources || []
10
9
  end
11
10
 
12
11
  def self.font_paths
@@ -36,8 +35,8 @@ module Fontist
36
35
  Dir.glob(Fontist.fonts_path.join("**"))
37
36
  end
38
37
 
39
- def self.find(font, sources: [])
40
- new(font: font, sources: sources).find
38
+ def self.find(font)
39
+ new(font: font).find
41
40
  end
42
41
 
43
42
  def self.find_styles(font, style)
@@ -57,18 +56,14 @@ module Fontist
57
56
 
58
57
  private
59
58
 
60
- attr_reader :font, :style, :user_sources
59
+ attr_reader :font, :style
61
60
 
62
61
  def find_by_index
63
- SystemIndex.new(all_paths).find(font, style)
62
+ SystemIndex.system_index.find(font, style)
64
63
  end
65
64
 
66
65
  def find_by_formulas
67
- FormulaPaths.new(all_paths).find(font, style)
68
- end
69
-
70
- def all_paths
71
- @all_paths ||= Dir.glob(user_sources) + self.class.font_paths
66
+ FormulaPaths.new(self.class.font_paths).find(font, style)
72
67
  end
73
68
  end
74
69
  end
@@ -4,22 +4,73 @@ module Fontist
4
4
  class SystemIndex
5
5
  include Utils::Locking
6
6
 
7
+ class DefaultFamily
8
+ def family_name(name)
9
+ name.font_family
10
+ end
11
+
12
+ def type(name)
13
+ name.font_subfamily
14
+ end
15
+ end
16
+
17
+ class PreferredFamily
18
+ def family_name(name)
19
+ return name.font_family if name.preferred_family.empty?
20
+
21
+ name.preferred_family
22
+ end
23
+
24
+ def type(name)
25
+ return name.font_subfamily if name.preferred_subfamily.empty?
26
+
27
+ name.preferred_subfamily
28
+ end
29
+ end
30
+
31
+ PLATFORM_MACINTOSH = 1
32
+ PLATFORM_MICROSOFT = 3
33
+
34
+ ENCODING_MAC_ROMAN = 0
35
+ ENCODING_MS_UNICODE_BMP = 1
36
+
37
+ LANGUAGE_MAC_ENGLISH = 0
38
+ LANGUAGE_MS_ENGLISH_AMERICAN = 0x409
39
+
7
40
  attr_reader :font_paths
8
41
 
9
- def self.find(font, style)
10
- new(SystemFont.font_paths).find(font, style)
42
+ def self.system_index
43
+ if Fontist.preferred_family?
44
+ new(Fontist.system_preferred_family_index_path,
45
+ SystemFont.font_paths,
46
+ PreferredFamily.new)
47
+ else
48
+ new(Fontist.system_index_path,
49
+ SystemFont.font_paths,
50
+ DefaultFamily.new)
51
+ end
11
52
  end
12
53
 
13
- def self.rebuild
14
- new(SystemFont.font_paths).rebuild
54
+ def self.fontist_index
55
+ if Fontist.preferred_family?
56
+ new(Fontist.fontist_preferred_family_index_path,
57
+ SystemFont.fontist_font_paths,
58
+ PreferredFamily.new)
59
+ else
60
+ new(Fontist.fontist_index_path,
61
+ SystemFont.fontist_font_paths,
62
+ DefaultFamily.new)
63
+ end
15
64
  end
16
65
 
17
- def initialize(font_paths)
66
+ def initialize(index_path, font_paths, family)
67
+ @index_path = index_path
18
68
  @font_paths = font_paths
69
+ @family = family
19
70
  end
20
71
 
21
72
  def find(font, style)
22
- fonts = system_index.select do |file|
73
+ fonts = index.select do |file|
23
74
  file[:family_name].casecmp?(font) &&
24
75
  (style.nil? || file[:type].casecmp?(style))
25
76
  end
@@ -28,27 +79,27 @@ module Fontist
28
79
  end
29
80
 
30
81
  def rebuild
31
- build_system_index
82
+ build_index
32
83
  end
33
84
 
34
85
  private
35
86
 
36
- def system_index
37
- @system_index ||= build_system_index
87
+ def index
88
+ @index ||= build_index
38
89
  end
39
90
 
40
- def build_system_index
91
+ def build_index
41
92
  lock(lock_path) do
42
- do_build_system_index
93
+ do_build_index
43
94
  end
44
95
  end
45
96
 
46
97
  def lock_path
47
- Fontist.system_index_path.to_s + ".lock"
98
+ "#{@index_path}.lock"
48
99
  end
49
100
 
50
- def do_build_system_index
51
- previous_index = load_system_index
101
+ def do_build_index
102
+ previous_index = load_index
52
103
  updated_index = detect_paths(font_paths, previous_index)
53
104
  updated_index.tap do |index|
54
105
  save_index(index) if changed?(updated_index, previous_index)
@@ -59,21 +110,23 @@ module Fontist
59
110
  this.map { |x| x[:path] }.uniq.sort != other.map { |x| x[:path] }.uniq.sort
60
111
  end
61
112
 
62
- def load_system_index
63
- index = File.exist?(Fontist.system_index_path) ? YAML.load_file(Fontist.system_index_path) : []
113
+ def load_index
114
+ index = File.exist?(@index_path) ? YAML.load_file(@index_path) : []
115
+ check_index(index)
116
+ index
117
+ end
64
118
 
119
+ def check_index(index)
65
120
  index.each do |item|
66
121
  missing_keys = %i[path full_name family_name type] - item.keys
67
122
  unless missing_keys.empty?
68
123
  raise(Errors::FontIndexCorrupted, <<~MSG.chomp)
69
124
  Font index is corrupted.
70
125
  Item #{item.inspect} misses required attributes: #{missing_keys.join(', ')}.
71
- You can remove the index file (#{Fontist.system_index_path}) and try again.
126
+ You can remove the index file (#{@index_path}) and try again.
72
127
  MSG
73
128
  end
74
129
  end
75
-
76
- index
77
130
  end
78
131
 
79
132
  def detect_paths(paths, index)
@@ -95,14 +148,18 @@ module Fontist
95
148
  else
96
149
  raise Errors::UnknownFontTypeError.new(path)
97
150
  end
151
+ rescue StandardError
152
+ Fontist.ui.error($!.message)
153
+ Fontist.ui.error(
154
+ "Warning: File at #{path} not recognized as a font file.",
155
+ )
98
156
  end
99
157
 
100
158
  def detect_file_font(path)
101
- file = TTFunk::File.open(path)
159
+ content = File.read(path, mode: "rb")
160
+ file = TTFunk::File.new(content)
161
+
102
162
  parse_font(file, path)
103
- rescue StandardError
104
- warn $!.message
105
- warn "Warning: File at #{path} not recognized as a font file."
106
163
  end
107
164
 
108
165
  def detect_collection_fonts(path)
@@ -118,20 +175,42 @@ module Fontist
118
175
 
119
176
  {
120
177
  path: path,
121
- full_name: parse_text(x.font_name.first),
122
- family_name: parse_text(x.preferred_family.first || x.font_family.first),
123
- type: parse_text(x.preferred_subfamily.first || x.font_subfamily.first),
178
+ full_name: english_name(x.font_name),
179
+ family_name: english_name(@family.family_name(x)),
180
+ type: english_name(@family.type(x)),
124
181
  }
125
182
  end
126
183
 
127
- def parse_text(text)
184
+ def english_name(name)
185
+ visible_characters(find_english(name))
186
+ end
187
+
188
+ def find_english(name)
189
+ name.find { |x| microsoft_english?(x) } ||
190
+ name.find { |x| mac_english?(x) } ||
191
+ name.last
192
+ end
193
+
194
+ def microsoft_english?(string)
195
+ string.platform_id == PLATFORM_MICROSOFT &&
196
+ string.encoding_id == ENCODING_MS_UNICODE_BMP &&
197
+ string.language_id == LANGUAGE_MS_ENGLISH_AMERICAN
198
+ end
199
+
200
+ def mac_english?(string)
201
+ string.platform_id == PLATFORM_MACINTOSH &&
202
+ string.encoding_id == ENCODING_MAC_ROMAN &&
203
+ string.language_id == LANGUAGE_MAC_ENGLISH
204
+ end
205
+
206
+ def visible_characters(text)
128
207
  text.gsub(/[^[:print:]]/, "").to_s
129
208
  end
130
209
 
131
210
  def save_index(index)
132
- dir = File.dirname(Fontist.system_index_path)
211
+ dir = File.dirname(@index_path)
133
212
  FileUtils.mkdir_p(dir) unless File.exist?(dir)
134
- File.write(Fontist.system_index_path, YAML.dump(index))
213
+ File.write(@index_path, YAML.dump(index))
135
214
  end
136
215
  end
137
216
  end