fontist 1.13.2 → 1.14.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,87 @@
1
+ module Fontist
2
+ class Fontconfig
3
+ def self.update
4
+ new.update
5
+ end
6
+
7
+ def self.remove(options = {})
8
+ new(options).remove
9
+ end
10
+
11
+ def initialize(options = {})
12
+ @options = options
13
+ end
14
+
15
+ def update
16
+ ensure_fontconfig_installed
17
+ create_config
18
+ regenerate_fontconfig_cache
19
+ end
20
+
21
+ def remove
22
+ return handle_file_not_found unless config_exists?
23
+
24
+ regenerate_fontconfig_cache if fontconfig_installed?
25
+ remove_config
26
+ end
27
+
28
+ private
29
+
30
+ def ensure_fontconfig_installed
31
+ raise Errors::FontconfigNotFoundError unless fontconfig_installed?
32
+ end
33
+
34
+ def fontconfig_installed?
35
+ Utils::System.fontconfig_installed?
36
+ end
37
+
38
+ def create_config
39
+ return if File.exist?(config_path)
40
+
41
+ FileUtils.mkdir_p(File.dirname(config_path))
42
+ File.write(config_path, config_content)
43
+ end
44
+
45
+ def config_path
46
+ File.join(xdg_config_home, "fontconfig", "conf.d", "10-fontist.conf")
47
+ end
48
+
49
+ def xdg_config_home
50
+ ENV["XDG_CONFIG_HOME"] || File.join(Dir.home, ".config")
51
+ end
52
+
53
+ def config_content
54
+ <<~CONTENT
55
+ <?xml version='1.0'?>
56
+ <!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
57
+ <fontconfig>
58
+ <dir>#{Fontist.fonts_path}</dir>
59
+ </fontconfig>
60
+ CONTENT
61
+ end
62
+
63
+ def regenerate_fontconfig_cache
64
+ Helpers.run("fc-cache -f")
65
+ end
66
+
67
+ def ensure_file_exists
68
+ return if @options[:force]
69
+
70
+ raise Errors::FontconfigFileNotFoundError unless File.exist?(config_path)
71
+ end
72
+
73
+ def config_exists?
74
+ File.exist?(config_path)
75
+ end
76
+
77
+ def handle_file_not_found
78
+ return if @options[:force]
79
+
80
+ raise Errors::FontconfigFileNotFoundError
81
+ end
82
+
83
+ def remove_config
84
+ FileUtils.rm(config_path)
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,29 @@
1
+ module Fontist
2
+ class FontconfigCLI < Thor
3
+ include CLI::ClassOptions
4
+
5
+ desc "update", "Update fontconfig configuration to use fontist fonts"
6
+ def update
7
+ handle_class_options(options)
8
+ Fontconfig.update
9
+ Fontist.ui.success("Fontconfig file has been successfully updated.")
10
+ CLI::STATUS_SUCCESS
11
+ rescue Errors::FontconfigNotFoundError => e
12
+ Fontist.ui.error(e.message)
13
+ CLI::STATUS_FONTCONFIG_NOT_FOUND
14
+ end
15
+
16
+ desc "remove", "Remove fontist file in fontconfig configuration"
17
+ option :force, type: :boolean, aliases: :f,
18
+ desc: "Proceed even if does not exist"
19
+ def remove
20
+ handle_class_options(options)
21
+ Fontconfig.remove(options)
22
+ Fontist.ui.success("Fontconfig file has been successfully removed.")
23
+ CLI::STATUS_SUCCESS
24
+ rescue Errors::FontconfigFileNotFoundError => e
25
+ Fontist.ui.error(e.message)
26
+ CLI::STATUS_FONTCONFIG_FILE_NOT_FOUND
27
+ end
28
+ end
29
+ end
@@ -3,5 +3,26 @@ module Fontist
3
3
  def self.parse_to_object(data)
4
4
  JSON.parse(data.to_json, object_class: OpenStruct)
5
5
  end
6
+
7
+ def self.run(command)
8
+ Fontist.ui.debug("Run `#{command}`")
9
+
10
+ result = `#{command}`
11
+ unless $CHILD_STATUS.to_i.zero?
12
+ raise Errors::BinaryCallError,
13
+ "Failed to run #{command}, status: #{$CHILD_STATUS}"
14
+ end
15
+
16
+ result
17
+ end
18
+
19
+ def self.silence_stream(stream)
20
+ old_stream = stream.dup
21
+ stream.reopen(RbConfig::CONFIG["host_os"] =~ /mswin|mingw/ ? "NUL:" : "/dev/null") # rubocop:disable Performance/RegexpMatch, Metrics/LineLength
22
+ stream.sync = true
23
+ yield
24
+ ensure
25
+ stream.reopen(old_stream)
26
+ end
6
27
  end
7
28
  end
@@ -55,12 +55,32 @@ module Fontist
55
55
  end
56
56
 
57
57
  def save(builder)
58
- filename = Import.name_to_filename(builder.name)
59
- path = @options[:formula_dir] ? File.join(@options[:formula_dir], filename) : filename
58
+ path = vacant_path
60
59
  yaml = YAML.dump(Helpers::HashHelper.stringify_keys(builder.formula))
61
60
  File.write(path, yaml)
62
61
  path
63
62
  end
63
+
64
+ def vacant_path
65
+ path = path_from_name
66
+ return path unless @options[:keep_existing] && File.exist?(path)
67
+
68
+ 2.upto(9) do |i|
69
+ candidate = path.sub(/\.yml$/, "#{i}.yml")
70
+ return candidate unless File.exist?(candidate)
71
+ end
72
+
73
+ raise Errors::GeneralError, "Formula #{path} already exists."
74
+ end
75
+
76
+ def path_from_name
77
+ filename = Import.name_to_filename(builder.name)
78
+ if @options[:formula_dir]
79
+ File.join(@options[:formula_dir], filename)
80
+ else
81
+ filename
82
+ end
83
+ end
64
84
  end
65
85
  end
66
86
  end
@@ -26,9 +26,9 @@ module Fontist
26
26
 
27
27
  def read
28
28
  switch_to_temp_dir do |tmp_dir|
29
- extract_ttfs(tmp_dir).map do |path|
30
- Otf::FontFile.new(path)
31
- end
29
+ extract_ttfs(tmp_dir)
30
+ .map { |path| Otf::FontFile.new(path) }
31
+ .reject { |font_file| hidden_or_pua_encoded?(font_file) }
32
32
  end
33
33
  end
34
34
 
@@ -47,6 +47,10 @@ module Fontist
47
47
  end
48
48
  end
49
49
 
50
+ def hidden_or_pua_encoded?(font_file)
51
+ font_file.family_name.start_with?(".")
52
+ end
53
+
50
54
  def detect_extension
51
55
  base_extension = "ttc"
52
56
 
@@ -4,9 +4,10 @@ require_relative "text_helper"
4
4
  module Fontist
5
5
  module Import
6
6
  class FormulaBuilder
7
- FORMULA_ATTRIBUTES = %i[description homepage resources
7
+ FORMULA_ATTRIBUTES = %i[platforms description homepage resources
8
8
  font_collections fonts extract copyright
9
- license_url open_license digest command].freeze
9
+ license_url requires_license_agreement
10
+ open_license digest command].freeze
10
11
 
11
12
  attr_writer :archive,
12
13
  :url,
@@ -28,9 +29,15 @@ module Fontist
28
29
  def name
29
30
  return @options[:name] if @options[:name]
30
31
 
31
- unique_names = both_fonts.map(&:family_name).uniq
32
- TextHelper.longest_common_prefix(unique_names) ||
33
- both_fonts.first.family_name
32
+ common = %i[family_name type]
33
+ .map { |attr| both_fonts.map(&attr).uniq }
34
+ .map { |names| TextHelper.longest_common_prefix(names) }
35
+ .map { |prefix| prefix unless prefix == "Regular" }
36
+ .compact
37
+ .join(" ")
38
+ return common unless common.empty?
39
+
40
+ both_fonts.map(&:family_name).first
34
41
  end
35
42
 
36
43
  private
@@ -50,6 +57,10 @@ module Fontist
50
57
  files
51
58
  end
52
59
 
60
+ def platforms
61
+ @options[:platforms]
62
+ end
63
+
53
64
  def description
54
65
  name
55
66
  end
@@ -175,12 +186,17 @@ module Fontist
175
186
  both_fonts.map(&:license_url).compact.first
176
187
  end
177
188
 
189
+ def requires_license_agreement
190
+ @options[:requires_license_agreement]
191
+ end
192
+
178
193
  def open_license
179
- unless @license_text
194
+ unless @license_text || requires_license_agreement
180
195
  Fontist.ui.error("WARN: please add license manually")
181
- return
182
196
  end
183
197
 
198
+ return unless @license_text
199
+
184
200
  Fontist.ui.error("WARN: ensure it's an open license, otherwise " \
185
201
  "change the 'open_license' attribute to " \
186
202
  "'requires_license_agreement'")
@@ -4,15 +4,7 @@ module Fontist
4
4
  module SystemHelper
5
5
  class << self
6
6
  def run(command)
7
- Fontist.ui.debug("Run `#{command}`")
8
-
9
- result = `#{command}`
10
- unless $CHILD_STATUS.to_i.zero?
11
- raise Errors::BinaryCallError,
12
- "Failed to run #{command}, status: #{$CHILD_STATUS}"
13
- end
14
-
15
- result
7
+ Fontist::Helpers.run(command)
16
8
  end
17
9
  end
18
10
  end