fontist 1.7.3 → 1.8.5

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.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/release.yml +38 -0
  3. data/.github/workflows/rspec.yml +58 -0
  4. data/README.md +48 -4
  5. data/{bin → exe}/fontist +0 -0
  6. data/fontist.gemspec +10 -7
  7. data/lib/fontist.rb +9 -2
  8. data/lib/fontist/cli.rb +64 -55
  9. data/lib/fontist/errors.rb +63 -12
  10. data/lib/fontist/font.rb +33 -64
  11. data/lib/fontist/font_installer.rb +118 -0
  12. data/lib/fontist/font_path.rb +29 -0
  13. data/lib/fontist/fontist_font.rb +3 -49
  14. data/lib/fontist/formula.rb +101 -35
  15. data/lib/fontist/formula_paths.rb +43 -0
  16. data/lib/fontist/helpers.rb +7 -0
  17. data/lib/fontist/import/create_formula.rb +3 -2
  18. data/lib/fontist/import/extractors.rb +4 -0
  19. data/lib/fontist/import/extractors/cpio_extractor.rb +39 -0
  20. data/lib/fontist/import/extractors/gzip_extractor.rb +27 -0
  21. data/lib/fontist/import/extractors/rpm_extractor.rb +45 -0
  22. data/lib/fontist/import/extractors/tar_extractor.rb +47 -0
  23. data/lib/fontist/import/google/skiplist.yml +3 -0
  24. data/lib/fontist/import/google_check.rb +1 -1
  25. data/lib/fontist/import/google_import.rb +3 -4
  26. data/lib/fontist/import/otfinfo_generate.rb +1 -1
  27. data/lib/fontist/import/recursive_extraction.rb +26 -8
  28. data/lib/fontist/import/sil_import.rb +99 -0
  29. data/lib/fontist/index.rb +11 -0
  30. data/lib/fontist/indexes/base_index.rb +82 -0
  31. data/lib/fontist/indexes/filename_index.rb +19 -0
  32. data/lib/fontist/indexes/font_index.rb +21 -0
  33. data/lib/fontist/indexes/index_formula.rb +36 -0
  34. data/lib/fontist/manifest/install.rb +4 -5
  35. data/lib/fontist/manifest/locations.rb +9 -1
  36. data/lib/fontist/system_font.rb +32 -62
  37. data/lib/fontist/system_index.rb +47 -5
  38. data/lib/fontist/utils.rb +5 -0
  39. data/lib/fontist/utils/cache.rb +12 -4
  40. data/lib/fontist/utils/cpio/cpio.rb +199 -0
  41. data/lib/fontist/utils/cpio_extractor.rb +47 -0
  42. data/lib/fontist/utils/exe_extractor.rb +1 -1
  43. data/lib/fontist/utils/gzip_extractor.rb +24 -0
  44. data/lib/fontist/utils/locking.rb +17 -0
  45. data/lib/fontist/utils/rpm_extractor.rb +37 -0
  46. data/lib/fontist/utils/tar_extractor.rb +61 -0
  47. data/lib/fontist/utils/zip_extractor.rb +1 -1
  48. data/lib/fontist/version.rb +1 -1
  49. metadata +74 -26
  50. data/.github/workflows/macosx.yml +0 -33
  51. data/.github/workflows/ubuntu.yml +0 -30
  52. data/.github/workflows/windows.yml +0 -32
  53. data/bin/check_google +0 -8
  54. data/bin/console +0 -11
  55. data/bin/convert_formulas +0 -8
  56. data/bin/generate_otfinfo +0 -8
  57. data/bin/import_google +0 -8
  58. data/bin/rspec +0 -29
  59. data/bin/setup +0 -7
  60. data/lib/fontist/font_formula.rb +0 -169
  61. data/lib/fontist/formula_template.rb +0 -122
  62. data/lib/fontist/formulas.rb +0 -56
  63. data/lib/fontist/registry.rb +0 -43
@@ -1,50 +1,43 @@
1
+ require "fontist/index"
2
+ require "fontist/helpers"
3
+ require "git"
4
+
1
5
  module Fontist
2
6
  class Formula
3
- def initialize(options = {})
4
- @font_name = options.fetch(:font_name, nil)
5
- @style_name = options.fetch(:style_name, nil)
6
-
7
- check_and_register_font_formulas
7
+ 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
8
15
  end
9
16
 
10
17
  def self.all
11
- new.all
18
+ Dir[Fontist.formulas_path.join("**/*.yml").to_s].map do |path|
19
+ Formula.new_from_file(path)
20
+ end
12
21
  end
13
22
 
14
23
  def self.find(font_name)
15
- new(font_name: font_name).find
24
+ Indexes::FontIndex.from_yaml.load_formulas(font_name).first
16
25
  end
17
26
 
18
- def self.find_fonts(name)
19
- new(font_name: name).find_fonts
20
- end
21
-
22
- def self.find_styles(font, style)
23
- new(font_name: font, style_name: style).find_styles
24
- end
27
+ def self.find_fonts(font_name)
28
+ formulas = Indexes::FontIndex.from_yaml.load_formulas(font_name)
25
29
 
26
- def all
27
- @all ||= Fontist::Registry.instance.formulas
28
- end
29
-
30
- def find
31
- formulas.values.detect do |formula|
32
- formula.fonts.any? do |f|
33
- f.name.casecmp?(font_name)
34
- end
35
- end
36
- end
37
-
38
- def find_fonts
39
- formulas.values.map do |formula|
30
+ formulas.map do |formula|
40
31
  formula.fonts.select do |f|
41
32
  f.name.casecmp?(font_name)
42
33
  end
43
34
  end.flatten
44
35
  end
45
36
 
46
- def find_styles
47
- formulas.values.map do |formula|
37
+ def self.find_styles(font_name, style_name)
38
+ formulas = Indexes::FontIndex.from_yaml.load_formulas(font_name)
39
+
40
+ formulas.map do |formula|
48
41
  formula.fonts.map do |f|
49
42
  f.styles.select do |s|
50
43
  f.name.casecmp?(font_name) && s.type.casecmp?(style_name)
@@ -53,16 +46,89 @@ module Fontist
53
46
  end.flatten
54
47
  end
55
48
 
49
+ def self.new_from_file(path)
50
+ data = YAML.load_file(path)
51
+ new(data, path)
52
+ end
53
+
54
+ def initialize(data, path)
55
+ @data = data
56
+ @path = path
57
+ end
58
+
59
+ def to_index_formula
60
+ Indexes::IndexFormula.new(path)
61
+ end
62
+
63
+ def path
64
+ @path
65
+ end
66
+
67
+ def key
68
+ @data["key"] || default_key
69
+ end
70
+
71
+ def description
72
+ @data["description"]
73
+ end
74
+
75
+ def homepage
76
+ @data["homepage"]
77
+ end
78
+
79
+ def copyright
80
+ @data["copyright"]
81
+ end
82
+
83
+ def license_url
84
+ @data["license_url"]
85
+ end
86
+
87
+ def license
88
+ @data["open_license"] || @data["requires_license_agreement"]
89
+ end
90
+
91
+ def license_required
92
+ @data["requires_license_agreement"] ? true : false
93
+ end
94
+
95
+ def extract
96
+ Helpers.parse_to_object(@data["extract"])
97
+ end
98
+
99
+ def resources
100
+ Helpers.parse_to_object(@data["resources"].values)
101
+ end
102
+
103
+ def fonts
104
+ @fonts ||= Helpers.parse_to_object(hash_collection_fonts + hash_fonts)
105
+ end
106
+
56
107
  private
57
108
 
58
- attr_reader :font_name, :style_name
109
+ def default_key
110
+ escaped = Regexp.escape(Fontist.formulas_path.to_s + "/")
111
+ @path.sub(Regexp.new("^" + escaped), "").sub(/\.yml$/, "")
112
+ end
113
+
114
+ def hash_collection_fonts
115
+ return [] unless @data["font_collections"]
116
+
117
+ @data["font_collections"].flat_map do |coll|
118
+ filenames = { "font" => coll["filename"],
119
+ "source_font" => coll["source_filename"] }
59
120
 
60
- def formulas
61
- @formulas ||= all.to_h
121
+ coll["fonts"].map do |font|
122
+ { "name" => font["name"],
123
+ "styles" => font["styles"].map { |s| filenames.merge(s) } }
124
+ end
125
+ end
62
126
  end
63
127
 
64
- def check_and_register_font_formulas
65
- $check_and_register_font_formulas ||= Fontist::Formulas.register_formulas
128
+ def hash_fonts
129
+ return [] unless @data["fonts"]
130
+
131
+ @data["fonts"]
66
132
  end
67
133
  end
68
134
  end
@@ -0,0 +1,43 @@
1
+ module Fontist
2
+ class FormulaPaths
3
+ attr_reader :font_paths
4
+
5
+ def initialize(font_paths)
6
+ @font_paths = font_paths
7
+ end
8
+
9
+ def find(font, style = nil)
10
+ styles = find_styles_by_formulas(font, style)
11
+ return if styles.empty?
12
+
13
+ fonts = styles.uniq { |s| s["font"] }.flat_map do |s|
14
+ paths = search_font_paths(s["font"])
15
+ paths.map do |path|
16
+ { full_name: s["full_name"],
17
+ path: path }
18
+ end
19
+ end
20
+
21
+ fonts.empty? ? nil : fonts
22
+ end
23
+
24
+ private
25
+
26
+ def find_styles_by_formulas(font, style)
27
+ if style
28
+ Formula.find_styles(font, style)
29
+ else
30
+ fonts = Formula.find_fonts(font)
31
+ return [] unless fonts
32
+
33
+ fonts.flat_map(&:styles)
34
+ end
35
+ end
36
+
37
+ def search_font_paths(filename)
38
+ font_paths.select do |path|
39
+ File.basename(path) == filename
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,7 @@
1
+ module Fontist
2
+ module Helpers
3
+ def self.parse_to_object(data)
4
+ JSON.parse(data.to_json, object_class: OpenStruct)
5
+ end
6
+ end
7
+ end
@@ -50,9 +50,10 @@ module Fontist
50
50
 
51
51
  def save(hash)
52
52
  filename = Import.name_to_filename(hash[:name])
53
+ path = @options[:formula_dir] ? File.join(@options[:formula_dir], filename) : filename
53
54
  yaml = YAML.dump(Helpers::HashHelper.stringify_keys(hash))
54
- File.write(filename, yaml)
55
- filename
55
+ File.write(path, yaml)
56
+ path
56
57
  end
57
58
  end
58
59
  end
@@ -3,3 +3,7 @@ require_relative "extractors/zip_extractor"
3
3
  require_relative "extractors/ole_extractor"
4
4
  require_relative "extractors/seven_zip_extractor"
5
5
  require_relative "extractors/cab_extractor"
6
+ require_relative "extractors/rpm_extractor"
7
+ require_relative "extractors/gzip_extractor"
8
+ require_relative "extractors/cpio_extractor"
9
+ require_relative "extractors/tar_extractor"
@@ -0,0 +1,39 @@
1
+ module Fontist
2
+ module Import
3
+ module Extractors
4
+ class CpioExtractor < Extractor
5
+ def extract
6
+ dir = Dir.mktmpdir
7
+ extract_cpio(@archive, dir)
8
+ dir
9
+ end
10
+
11
+ def format
12
+ "cpio"
13
+ end
14
+
15
+ private
16
+
17
+ def extract_cpio(archive, dir)
18
+ archive_file = File.open(archive, "rb")
19
+
20
+ reader_class.new(archive_file).each do |entry, file|
21
+ path = File.join(dir, entry.name)
22
+ if entry.directory?
23
+ FileUtils.mkdir_p(path)
24
+ else
25
+ File.write(path, file.read)
26
+ end
27
+ end
28
+ end
29
+
30
+ def reader_class
31
+ @reader_class ||= begin
32
+ require "fontist/utils/cpio/cpio"
33
+ CPIO::ASCIIReader
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,27 @@
1
+ module Fontist
2
+ module Import
3
+ module Extractors
4
+ class GzipExtractor < Extractor
5
+ def extract
6
+ dir = Dir.mktmpdir
7
+ extract_gzip(@archive, dir)
8
+ dir
9
+ end
10
+
11
+ def format
12
+ "gzip"
13
+ end
14
+
15
+ private
16
+
17
+ def extract_gzip(archive, dir)
18
+ Zlib::GzipReader.open(archive) do |gz|
19
+ basename = File.basename(archive, ".*")
20
+ path = File.join(dir, basename)
21
+ File.write(path, gz.read)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,45 @@
1
+ module Fontist
2
+ module Import
3
+ module Extractors
4
+ class RpmExtractor < Extractor
5
+ def extract
6
+ dir = Dir.mktmpdir
7
+ extract_rpm(@archive, dir)
8
+ dir
9
+ end
10
+
11
+ def format
12
+ "rpm"
13
+ end
14
+
15
+ private
16
+
17
+ def extract_rpm(archive, dir)
18
+ file = File.open(archive, "rb")
19
+ rpm = rpm_class.new(file)
20
+ content = rpm.payload.read
21
+ path = target_path(archive, rpm.tags, dir)
22
+
23
+ File.write(path, content)
24
+ ensure
25
+ file.close
26
+ end
27
+
28
+ def rpm_class
29
+ @rpm_class ||= begin
30
+ require "arr-pm"
31
+ RPM::File
32
+ end
33
+ end
34
+
35
+ def target_path(archive, tags, dir)
36
+ archive_format = tags[:payloadformat]
37
+ compression_format = tags[:payloadcompressor] == "gzip" ? "gz" : tags[:payloadcompressor]
38
+ basename = File.basename(archive, ".*")
39
+ filename = basename + "." + archive_format + "." + compression_format
40
+ File.join(dir, filename)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,47 @@
1
+ module Fontist
2
+ module Import
3
+ module Extractors
4
+ class TarExtractor < Extractor
5
+ def extract
6
+ dir = Dir.mktmpdir
7
+ extract_tar(@archive, dir)
8
+ dir
9
+ end
10
+
11
+ def format
12
+ "tar"
13
+ end
14
+
15
+ private
16
+
17
+ def extract_tar(archive, dir)
18
+ archive_file = File.open(archive, "rb")
19
+ reader_class.new(archive_file) do |tar|
20
+ tar.each do |tarfile|
21
+ save_tar_file(tarfile, dir)
22
+ end
23
+ end
24
+ end
25
+
26
+ def reader_class
27
+ @reader_class ||= begin
28
+ require "rubygems/package"
29
+ Gem::Package::TarReader
30
+ end
31
+ end
32
+
33
+ def save_tar_file(file, dir)
34
+ path = File.join(dir, file.full_name)
35
+
36
+ if file.directory?
37
+ FileUtils.mkdir_p(path)
38
+ else
39
+ File.open(path, "wb") do |f|
40
+ f.print(file.read)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -6,3 +6,6 @@
6
6
  - Open Sans
7
7
  - Work Sans
8
8
  - Fira Code
9
+ - Andika
10
+ - Harmattan
11
+ - Padauk
@@ -12,7 +12,7 @@ module Fontist
12
12
  private
13
13
 
14
14
  def fetch_formulas
15
- Formulas.fetch_formulas
15
+ Formula.update_formulas_repo
16
16
  end
17
17
 
18
18
  def new_fonts
@@ -156,10 +156,9 @@ module Fontist
156
156
  h.merge!(family_name: style.family_name,
157
157
  type: style.style,
158
158
  full_name: style.full_name)
159
- h.merge!(style.to_h.slice(:post_script_name,
160
- :version,
161
- :description,
162
- :copyright).compact)
159
+ h.merge!(style.to_h.select do |k, _|
160
+ %i(post_script_name version description copyright).include?(k)
161
+ end.compact)
163
162
  h.merge!(font: fix_variable_filename(style.filename))
164
163
  end
165
164
  end
@@ -25,7 +25,7 @@ module Fontist
25
25
  def font_paths(font)
26
26
  formula = Fontist::Formula.find(font)
27
27
  font_formula = Object.const_get(formula.installer)
28
- font_formula.fetch_font(nil, confirmation: "yes")
28
+ font_formula.install(confirmation: "yes")
29
29
  end
30
30
 
31
31
  def generate_styles(paths)