fontist 1.8.12 → 1.10.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,17 +3,37 @@ module Fontist
3
3
  class GeneralError < StandardError; end
4
4
 
5
5
  class BinaryCallError < GeneralError; end
6
+
6
7
  class FontIndexCorrupted < GeneralError; end
8
+
7
9
  class FontNotFoundError < GeneralError; end
10
+
11
+ # for backward compatibility with metanorma,
12
+ # it depends on this exception to automatically download formulas
8
13
  class FormulaIndexNotFoundError < GeneralError; end
14
+
15
+ class MainRepoNotFoundError < FormulaIndexNotFoundError; end
16
+
9
17
  class InvalidResourceError < GeneralError; end
18
+
10
19
  class LicensingError < GeneralError; end
20
+
11
21
  class ManifestCouldNotBeFoundError < GeneralError; end
22
+
12
23
  class ManifestCouldNotBeReadError < GeneralError; end
24
+
13
25
  class MissingAttributeError < GeneralError; end
26
+
27
+ class RepoNotFoundError < GeneralError; end
28
+
29
+ class RepoCouldNotBeUpdatedError < GeneralError; end
30
+
14
31
  class TamperedFileError < GeneralError; end
32
+
15
33
  class TimeoutError < GeneralError; end
34
+
16
35
  class UnknownFontTypeError < GeneralError; end
36
+
17
37
  class UnknownArchiveError < GeneralError; end
18
38
 
19
39
  class FontError < GeneralError
data/lib/fontist/font.rb CHANGED
@@ -166,7 +166,7 @@ module Fontist
166
166
  end
167
167
 
168
168
  def uninstall_font
169
- paths = find_fontist_font
169
+ paths = find_fontist_paths
170
170
  return unless paths
171
171
 
172
172
  paths.each do |path|
@@ -176,8 +176,13 @@ module Fontist
176
176
  paths
177
177
  end
178
178
 
179
- def find_fontist_font
180
- Fontist::FontistFont.find(name)
179
+ def find_fontist_paths
180
+ fonts = Fontist::SystemIndex.fontist_index.find(name, nil)
181
+ return unless fonts
182
+
183
+ fonts.map do |font|
184
+ font[:path]
185
+ end
181
186
  end
182
187
 
183
188
  def installed_paths
@@ -203,9 +208,9 @@ module Fontist
203
208
  end
204
209
 
205
210
  def font_list
206
- return unless formula
211
+ return if formulas.empty?
207
212
 
208
- list_styles([formula])
213
+ list_styles(formulas)
209
214
  end
210
215
 
211
216
  def list_styles(formulas)
@@ -54,11 +54,12 @@ module Fontist
54
54
  end
55
55
 
56
56
  def download_file(source)
57
- url = source.urls.first
57
+ request = source.urls.first
58
+ url = request.respond_to?(:url) ? request.url : request
58
59
  Fontist.ui.say(%(Downloading font "#{@formula.key}" from #{url}))
59
60
 
60
61
  Fontist::Utils::Downloader.download(
61
- url,
62
+ request,
62
63
  sha: source.sha256,
63
64
  file_size: source.file_size,
64
65
  progress_bar: !@no_progress
@@ -1,17 +1,12 @@
1
1
  require "fontist/index"
2
2
  require "fontist/helpers"
3
+ require "fontist/update"
3
4
  require "git"
4
5
 
5
6
  module Fontist
6
7
  class Formula
7
8
  def self.update_formulas_repo
8
- if Dir.exist?(Fontist.formulas_repo_path)
9
- Git.open(Fontist.formulas_repo_path).pull
10
- else
11
- Git.clone(Fontist.formulas_repo_url,
12
- Fontist.formulas_repo_path,
13
- depth: 1)
14
- end
9
+ Update.call
15
10
  end
16
11
 
17
12
  def self.all
@@ -129,7 +129,7 @@ module Fontist
129
129
 
130
130
  fonts = groups.map do |name, group|
131
131
  { name: name,
132
- styles: group.map(&style_type) }
132
+ styles: styles_from_files(group, style_type) }
133
133
  end
134
134
 
135
135
  fonts.sort_by do |x|
@@ -137,6 +137,10 @@ module Fontist
137
137
  end
138
138
  end
139
139
 
140
+ def styles_from_files(files, style_type)
141
+ files.map(&style_type).sort_by { |x| x[:type] }
142
+ end
143
+
140
144
  def extract
141
145
  @extractor.operations
142
146
  end
@@ -156,6 +156,10 @@ module Fontist
156
156
  h.merge!(family_name: style.family_name,
157
157
  type: style.style,
158
158
  full_name: style.full_name)
159
+ if style.preferred_family_name
160
+ h[:preferred_family_name] = style.preferred_family_name
161
+ end
162
+ h[:preferred_type] = style.preferred_style if style.preferred_style
159
163
  h.merge!(style.to_h.select do |k, _|
160
164
  %i(post_script_name version description copyright).include?(k)
161
165
  end.compact)
@@ -10,7 +10,8 @@ module Fontist
10
10
  otfinfo: Otfinfo::OtfinfoRequirement.new,
11
11
  }.freeze
12
12
 
13
- STYLE_ATTRIBUTES = %i[family_name type full_name post_script_name
13
+ STYLE_ATTRIBUTES = %i[family_name type preferred_family_name
14
+ preferred_type full_name post_script_name
14
15
  version description copyright font
15
16
  source_font].freeze
16
17
 
@@ -35,11 +36,19 @@ module Fontist
35
36
  end
36
37
 
37
38
  def family_name
38
- info["Preferred family"] || info["Family"]
39
+ info["Family"]
39
40
  end
40
41
 
41
42
  def type
42
- info["Preferred subfamily"] || info["Subfamily"]
43
+ info["Subfamily"]
44
+ end
45
+
46
+ def preferred_family_name
47
+ info["Preferred family"]
48
+ end
49
+
50
+ def preferred_type
51
+ info["Preferred subfamily"]
43
52
  end
44
53
 
45
54
  def full_name
@@ -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
@@ -3,9 +3,45 @@ require_relative "indexes/filename_index"
3
3
 
4
4
  module Fontist
5
5
  class Index
6
+ def self.rebuild_for_main_repo
7
+ unless Dir.exist?(Fontist.private_formulas_path)
8
+ return do_rebuild_for_main_repo_with
9
+ end
10
+
11
+ Dir.mktmpdir do |dir|
12
+ tmp_private_path = File.join(dir, "private")
13
+ FileUtils.mv(Fontist.private_formulas_path, tmp_private_path)
14
+
15
+ do_rebuild_for_main_repo_with
16
+
17
+ FileUtils.mv(tmp_private_path, Fontist.private_formulas_path)
18
+ end
19
+ end
20
+
21
+ def self.do_rebuild_for_main_repo_with
22
+ Fontist.formula_preferred_family_index_path =
23
+ Fontist.formulas_repo_path.join("index.yml")
24
+ Fontist.formula_filename_index_path =
25
+ Fontist.formulas_repo_path.join("filename_index.yml")
26
+
27
+ rebuild
28
+
29
+ Fontist.formula_preferred_family_index_path = nil
30
+ Fontist.formula_filename_index_path = nil
31
+ end
32
+
6
33
  def self.rebuild
7
- Fontist::Indexes::FontIndex.rebuild
34
+ Fontist::Indexes::DefaultFamilyFontIndex.rebuild
35
+ Fontist::Indexes::PreferredFamilyFontIndex.rebuild
8
36
  Fontist::Indexes::FilenameIndex.rebuild
37
+
38
+ reset_cache
39
+ end
40
+
41
+ def self.reset_cache
42
+ Fontist::Indexes::DefaultFamilyFontIndex.reset_cache
43
+ Fontist::Indexes::PreferredFamilyFontIndex.reset_cache
44
+ Fontist::Indexes::FilenameIndex.reset_cache
9
45
  end
10
46
  end
11
47
  end
@@ -5,10 +5,14 @@ module Fontist
5
5
  class BaseIndex
6
6
  def self.from_yaml
7
7
  @from_yaml ||= begin
8
- unless File.exist?(path)
9
- raise Errors::FormulaIndexNotFoundError.new("Please fetch `#{path}` index with `fontist update`.")
8
+ unless Dir.exist?(Fontist.formulas_repo_path)
9
+ raise Errors::MainRepoNotFoundError.new(
10
+ "Please fetch formulas with `fontist update`.",
11
+ )
10
12
  end
11
13
 
14
+ rebuild unless File.exist?(path)
15
+
12
16
  data = YAML.load_file(path)
13
17
  new(data)
14
18
  end
@@ -18,6 +22,10 @@ module Fontist
18
22
  raise NotImplementedError, "Please define path of an index"
19
23
  end
20
24
 
25
+ def self.reset_cache
26
+ @from_yaml = nil
27
+ end
28
+
21
29
  def self.rebuild
22
30
  index = new
23
31
  index.build
@@ -59,6 +67,8 @@ module Fontist
59
67
  end
60
68
 
61
69
  def to_yaml
70
+ dir = File.dirname(self.class.path)
71
+ FileUtils.mkdir_p(dir) unless File.exist?(dir)
62
72
  File.write(self.class.path, YAML.dump(to_h))
63
73
  end
64
74
 
@@ -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
@@ -0,0 +1,60 @@
1
+ require "git"
2
+
3
+ module Fontist
4
+ class Repo
5
+ class << self
6
+ def setup(name, url)
7
+ ensure_private_formulas_path_exists
8
+ fetch_repo(name, url)
9
+ Index.rebuild
10
+ end
11
+
12
+ def update(name)
13
+ path = repo_path(name)
14
+ unless Dir.exist?(path)
15
+ raise(Errors::RepoNotFoundError, "No such repo '#{name}'.")
16
+ end
17
+
18
+ Git.open(path).pull
19
+ Index.rebuild
20
+ end
21
+
22
+ def remove(name)
23
+ path = repo_path(name)
24
+ unless Dir.exist?(path)
25
+ raise(Errors::RepoNotFoundError, "No such repo '#{name}'.")
26
+ end
27
+
28
+ FileUtils.rm_r(path)
29
+ Index.rebuild
30
+ end
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
+
38
+ private
39
+
40
+ def ensure_private_formulas_path_exists
41
+ Fontist.private_formulas_path.tap do |path|
42
+ FileUtils.mkdir_p(path) unless Dir.exist?(path)
43
+ end
44
+ end
45
+
46
+ def fetch_repo(name, url)
47
+ path = repo_path(name)
48
+ if Dir.exist?(path)
49
+ Git.open(path).pull
50
+ else
51
+ Git.clone(url, path, depth: 1)
52
+ end
53
+ end
54
+
55
+ def repo_path(name)
56
+ Fontist.private_formulas_path.join(name)
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,51 @@
1
+ module Fontist
2
+ class RepoCLI < Thor
3
+ desc "setup NAME URL",
4
+ "Setup a custom fontist repo named NAME for the repository at URL " \
5
+ "and fetches its formulas"
6
+ def setup(name, url)
7
+ Repo.setup(name, url)
8
+ Fontist.ui.success(
9
+ "Fontist repo '#{name}' from '#{url}' has been successfully set up.",
10
+ )
11
+ CLI::STATUS_SUCCESS
12
+ end
13
+
14
+ desc "update NAME", "Update formulas in a fontist repo named NAME"
15
+ def update(name)
16
+ Repo.update(name)
17
+ Fontist.ui.success(
18
+ "Fontist repo '#{name}' has been successfully updated.",
19
+ )
20
+ CLI::STATUS_SUCCESS
21
+ rescue Errors::RepoNotFoundError
22
+ handle_repo_not_found(name)
23
+ end
24
+
25
+ desc "remove NAME", "Remove fontist repo named NAME"
26
+ def remove(name)
27
+ Repo.remove(name)
28
+ Fontist.ui.success(
29
+ "Fontist repo '#{name}' has been successfully removed.",
30
+ )
31
+ CLI::STATUS_SUCCESS
32
+ rescue Errors::RepoNotFoundError
33
+ handle_repo_not_found(name)
34
+ end
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
+
44
+ private
45
+
46
+ def handle_repo_not_found(name)
47
+ Fontist.ui.error("Fontist repo '#{name}' is not found.")
48
+ CLI::STATUS_REPO_NOT_FOUND
49
+ end
50
+ end
51
+ end