fontist 1.8.4 → 1.8.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rspec.yml +13 -13
  3. data/fontist.gemspec +3 -7
  4. data/lib/fontist.rb +4 -0
  5. data/lib/fontist/cli.rb +11 -22
  6. data/lib/fontist/font.rb +37 -42
  7. data/lib/fontist/font_installer.rb +37 -37
  8. data/lib/fontist/font_path.rb +29 -0
  9. data/lib/fontist/formula.rb +8 -4
  10. data/lib/fontist/import/recursive_extraction.rb +25 -119
  11. data/lib/fontist/index.rb +4 -65
  12. data/lib/fontist/indexes/base_index.rb +82 -0
  13. data/lib/fontist/indexes/filename_index.rb +19 -0
  14. data/lib/fontist/indexes/font_index.rb +21 -0
  15. data/lib/fontist/indexes/index_formula.rb +36 -0
  16. data/lib/fontist/manifest/install.rb +3 -2
  17. data/lib/fontist/utils.rb +0 -8
  18. data/lib/fontist/utils/downloader.rb +7 -4
  19. data/lib/fontist/version.rb +1 -1
  20. metadata +21 -92
  21. data/lib/fontist/import/extractors.rb +0 -9
  22. data/lib/fontist/import/extractors/cab_extractor.rb +0 -37
  23. data/lib/fontist/import/extractors/cpio_extractor.rb +0 -39
  24. data/lib/fontist/import/extractors/extractor.rb +0 -19
  25. data/lib/fontist/import/extractors/gzip_extractor.rb +0 -27
  26. data/lib/fontist/import/extractors/ole_extractor.rb +0 -41
  27. data/lib/fontist/import/extractors/rpm_extractor.rb +0 -45
  28. data/lib/fontist/import/extractors/seven_zip_extractor.rb +0 -44
  29. data/lib/fontist/import/extractors/tar_extractor.rb +0 -47
  30. data/lib/fontist/import/extractors/zip_extractor.rb +0 -31
  31. data/lib/fontist/index_formula.rb +0 -30
  32. data/lib/fontist/utils/cpio/cpio.rb +0 -199
  33. data/lib/fontist/utils/cpio_extractor.rb +0 -47
  34. data/lib/fontist/utils/exe_extractor.rb +0 -75
  35. data/lib/fontist/utils/gzip_extractor.rb +0 -24
  36. data/lib/fontist/utils/msi_extractor.rb +0 -31
  37. data/lib/fontist/utils/rpm_extractor.rb +0 -37
  38. data/lib/fontist/utils/seven_zip_extractor.rb +0 -41
  39. data/lib/fontist/utils/tar_extractor.rb +0 -61
  40. data/lib/fontist/utils/zip_extractor.rb +0 -52
@@ -21,11 +21,15 @@ module Fontist
21
21
  end
22
22
 
23
23
  def self.find(font_name)
24
- Index.from_yaml.load_formulas(font_name).first
24
+ Indexes::FontIndex.from_yaml.load_formulas(font_name).first
25
+ end
26
+
27
+ def self.find_many(font_name)
28
+ Indexes::FontIndex.from_yaml.load_formulas(font_name)
25
29
  end
26
30
 
27
31
  def self.find_fonts(font_name)
28
- formulas = Index.from_yaml.load_formulas(font_name)
32
+ formulas = Indexes::FontIndex.from_yaml.load_formulas(font_name)
29
33
 
30
34
  formulas.map do |formula|
31
35
  formula.fonts.select do |f|
@@ -35,7 +39,7 @@ module Fontist
35
39
  end
36
40
 
37
41
  def self.find_styles(font_name, style_name)
38
- formulas = Index.from_yaml.load_formulas(font_name)
42
+ formulas = Indexes::FontIndex.from_yaml.load_formulas(font_name)
39
43
 
40
44
  formulas.map do |formula|
41
45
  formula.fonts.map do |f|
@@ -57,7 +61,7 @@ module Fontist
57
61
  end
58
62
 
59
63
  def to_index_formula
60
- IndexFormula.new(path)
64
+ Indexes::IndexFormula.new(path)
61
65
  end
62
66
 
63
67
  def path
@@ -1,21 +1,18 @@
1
- require "find"
2
- require_relative "extractors"
3
1
  require_relative "files/font_detector"
4
2
 
5
3
  module Fontist
6
4
  module Import
7
5
  class RecursiveExtraction
8
- FONTS_PATTERN = "**/*.{ttf,otf,ttc}".freeze
9
- ARCHIVE_EXTENSIONS = %w[zip msi exe cab].freeze
10
6
  LICENSE_PATTERN = /(ofl\.txt|ufl\.txt|licenses?\.txt|copying)$/i.freeze
11
7
 
12
8
  def initialize(archive, subarchive: nil, subdir: nil)
13
9
  @archive = archive
14
- @subarchive = subarchive
15
10
  @subdir = subdir
16
- @operations = []
11
+ @operations = {}
17
12
  @font_files = []
18
13
  @collection_files = []
14
+
15
+ save_operation_subdir
19
16
  end
20
17
 
21
18
  def extension
@@ -39,11 +36,18 @@ module Fontist
39
36
 
40
37
  def operations
41
38
  ensure_extracted
42
- @operations.size == 1 ? @operations.first : @operations
39
+ @operations
43
40
  end
44
41
 
45
42
  private
46
43
 
44
+ def save_operation_subdir
45
+ return unless @subdir
46
+
47
+ @operations[:options] ||= {}
48
+ @operations[:options][:fonts_sub_dir] = @subdir
49
+ end
50
+
47
51
  def fetch_extension(file)
48
52
  File.extname(filename(file)).sub(/^\./, "")
49
53
  end
@@ -57,68 +61,21 @@ module Fontist
57
61
  end
58
62
 
59
63
  def ensure_extracted
60
- extracted_path
61
- end
64
+ return if @extracted
62
65
 
63
- def extracted_path
64
- @extracted_path ||= extract_recursively(@archive)
66
+ extract_data(@archive)
67
+ @extracted = true
65
68
  end
66
69
 
67
- def extract_recursively(archive)
68
- path = operate_on_archive(archive)
69
- match_files(path)
70
- if matched?
71
- save_operation_subdir
72
- return path
73
- end
74
-
75
- next_archive = find_archive(path)
76
- extract_recursively(next_archive)
77
- end
78
-
79
- def operate_on_archive(archive)
80
- extractor = choose_extractor(archive)
81
- Fontist.ui.say("Extracting #{archive} with #{extractor.class.name}")
82
-
83
- save_operation(extractor)
84
- extractor.extract
85
- end
86
-
87
- # rubocop:disable Metrics/MethodLength
88
- def choose_extractor(archive)
89
- case fetch_extension(archive).downcase
90
- when "msi"
91
- Extractors::OleExtractor.new(archive)
92
- when "cab"
93
- Extractors::CabExtractor.new(archive)
94
- when "exe"
95
- extractor = Extractors::SevenZipExtractor.new(archive)
96
- extractor.try ? extractor : Extractors::CabExtractor.new(archive)
97
- when "zip"
98
- Extractors::ZipExtractor.new(archive)
99
- when "rpm"
100
- Extractors::RpmExtractor.new(archive)
101
- when "gz"
102
- Extractors::GzipExtractor.new(archive)
103
- when "cpio"
104
- Extractors::CpioExtractor.new(archive)
105
- when "tar"
106
- Extractors::TarExtractor.new(archive)
107
- else
108
- raise Errors::UnknownArchiveError, "Could not unarchive `#{filename(archive)}`."
70
+ def extract_data(archive)
71
+ Excavate::Archive.new(path(archive)).files(recursive_packages: true) do |path|
72
+ match_license(path)
73
+ match_font(path) if font_directory?(path)
109
74
  end
110
75
  end
111
- # rubocop:enable Metrics/MethodLength
112
76
 
113
- def save_operation(extractor)
114
- @operations << { format: extractor.format }
115
- end
116
-
117
- def match_files(dir_path)
118
- Find.find(dir_path) do |entry_path| # rubocop:disable Style/CollectionMethods
119
- match_license(entry_path)
120
- match_font(entry_path) if font_directory?(entry_path, dir_path)
121
- end
77
+ def path(file)
78
+ file.respond_to?(:path) ? file.path : file
122
79
  end
123
80
 
124
81
  def match_license(path)
@@ -129,18 +86,6 @@ module Fontist
129
86
  file.match?(LICENSE_PATTERN)
130
87
  end
131
88
 
132
- def font_directory?(path, base_path)
133
- return true unless @subdir
134
-
135
- # https://bugs.ruby-lang.org/issues/10011
136
- base_path = Pathname.new(base_path)
137
-
138
- relative_path = Pathname.new(path).relative_path_from(base_path).to_s
139
- dirname = File.dirname(relative_path)
140
- normalized_pattern = @subdir.chomp("/")
141
- File.fnmatch?(normalized_pattern, dirname)
142
- end
143
-
144
89
  def match_font(path)
145
90
  case Files::FontDetector.detect(path)
146
91
  when :font
@@ -150,53 +95,14 @@ module Fontist
150
95
  end
151
96
  end
152
97
 
153
- def matched?
154
- [@font_files, @collection_files].any? do |files|
155
- files.size.positive?
156
- end
157
- end
158
-
159
- def save_operation_subdir
160
- return unless @subdir
161
-
162
- @operations.last[:options] ||= {}
163
- @operations.last[:options][:fonts_sub_dir] = @subdir
164
- end
165
-
166
- def find_archive(path)
167
- children = Dir.entries(path) - [".", ".."] # ruby 2.4 compat
168
- paths = children.map { |file| File.join(path, file) }
169
- by_subarchive(paths) || by_size(paths)
170
- end
171
-
172
- def by_subarchive(paths)
173
- return unless @subarchive
174
-
175
- path_found = paths.detect do |path|
176
- @subarchive == File.basename(path)
177
- end
178
-
179
- return unless path_found
180
-
181
- save_operation_subarchive(path_found)
182
-
183
- path_found
184
- end
185
-
186
- def save_operation_subarchive(path)
187
- @operations.last[:options] ||= {}
188
- @operations.last[:options][:subarchive] = File.basename(path)
189
- end
98
+ def font_directory?(path)
99
+ return true unless subdirectory_pattern
190
100
 
191
- def by_size(paths)
192
- paths.max_by do |path|
193
- [file_type(path), File.size(path)]
194
- end
101
+ File.fnmatch?(subdirectory_pattern, File.dirname(path))
195
102
  end
196
103
 
197
- def file_type(file_path)
198
- extension = File.extname(file_path).delete(".")
199
- ARCHIVE_EXTENSIONS.include?(extension) ? 1 : 0
104
+ def subdirectory_pattern
105
+ @subdirectory_pattern ||= "*" + @subdir.chomp("/") if @subdir
200
106
  end
201
107
  end
202
108
  end
data/lib/fontist/index.rb CHANGED
@@ -1,72 +1,11 @@
1
- require_relative "index_formula"
1
+ require_relative "indexes/font_index"
2
+ require_relative "indexes/filename_index"
2
3
 
3
4
  module Fontist
4
5
  class Index
5
- def self.from_yaml
6
- unless File.exist?(Fontist.formula_index_path)
7
- raise Errors::FormulaIndexNotFoundError.new("Please fetch index with `fontist update`.")
8
- end
9
-
10
- data = YAML.load_file(Fontist.formula_index_path)
11
- new(data)
12
- end
13
-
14
6
  def self.rebuild
15
- index = new
16
- index.build
17
- index.to_yaml
18
- end
19
-
20
- def initialize(data = {})
21
- @index = {}
22
-
23
- data.each_pair do |font, paths|
24
- paths.each do |path|
25
- add_index_formula(font, IndexFormula.new(path))
26
- end
27
- end
28
- end
29
-
30
- def build
31
- Formula.all.each do |formula|
32
- add_formula(formula)
33
- end
34
- end
35
-
36
- def add_formula(formula)
37
- formula.fonts.each do |font|
38
- add_index_formula(font.name, formula.to_index_formula)
39
- end
40
- end
41
-
42
- def add_index_formula(font_raw, index_formula)
43
- font = normalize_font(font_raw)
44
- @index[font] ||= []
45
- @index[font] << index_formula unless @index[font].include?(index_formula)
46
- end
47
-
48
- def load_formulas(font)
49
- index_formulas(font).map(&:to_full)
50
- end
51
-
52
- def to_yaml
53
- File.write(Fontist.formula_index_path, YAML.dump(to_h))
54
- end
55
-
56
- def to_h
57
- @index.map do |font, index_formulas|
58
- [font, index_formulas.map(&:to_s)]
59
- end.to_h
60
- end
61
-
62
- private
63
-
64
- def index_formulas(font)
65
- @index[normalize_font(font)] || []
66
- end
67
-
68
- def normalize_font(font)
69
- font.downcase
7
+ Fontist::Indexes::FontIndex.rebuild
8
+ Fontist::Indexes::FilenameIndex.rebuild
70
9
  end
71
10
  end
72
11
  end
@@ -0,0 +1,82 @@
1
+ require_relative "index_formula"
2
+
3
+ module Fontist
4
+ module Indexes
5
+ class BaseIndex
6
+ def self.from_yaml
7
+ @from_yaml ||= begin
8
+ unless File.exist?(path)
9
+ raise Errors::FormulaIndexNotFoundError.new("Please fetch `#{path}` index with `fontist update`.")
10
+ end
11
+
12
+ data = YAML.load_file(path)
13
+ new(data)
14
+ end
15
+ end
16
+
17
+ def self.path
18
+ raise NotImplementedError, "Please define path of an index"
19
+ end
20
+
21
+ def self.rebuild
22
+ index = new
23
+ index.build
24
+ index.to_yaml
25
+ end
26
+
27
+ def initialize(data = {})
28
+ @index = {}
29
+
30
+ data.each_pair do |key, paths|
31
+ paths.each do |path|
32
+ add_index_formula(key, IndexFormula.new(path))
33
+ end
34
+ end
35
+ end
36
+
37
+ def build
38
+ Formula.all.each do |formula|
39
+ add_formula(formula)
40
+ end
41
+ end
42
+
43
+ def add_formula(_formula)
44
+ raise NotImplementedError, "Please define how to add formula to an index, use #add_index_formula"
45
+ end
46
+
47
+ def add_index_formula(key_raw, index_formula)
48
+ key = normalize_key(key_raw)
49
+ @index[key] ||= []
50
+ @index[key] << index_formula unless @index[key].include?(index_formula)
51
+ end
52
+
53
+ def load_formulas(key)
54
+ index_formulas(key).map(&:to_full)
55
+ end
56
+
57
+ def load_index_formulas(key)
58
+ index_formulas(key)
59
+ end
60
+
61
+ def to_yaml
62
+ File.write(self.class.path, YAML.dump(to_h))
63
+ end
64
+
65
+ def to_h
66
+ @index.map do |key, index_formulas|
67
+ [key, index_formulas.map(&:to_s)]
68
+ end.to_h
69
+ end
70
+
71
+ private
72
+
73
+ def index_formulas(key)
74
+ @index[normalize_key(key)] || []
75
+ end
76
+
77
+ def normalize_key(key)
78
+ key
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,19 @@
1
+ require_relative "base_index"
2
+
3
+ module Fontist
4
+ module Indexes
5
+ class FilenameIndex < BaseIndex
6
+ def self.path
7
+ Fontist.formula_filename_index_path
8
+ end
9
+
10
+ def add_formula(formula)
11
+ formula.fonts.each do |font|
12
+ font.styles.each do |style|
13
+ add_index_formula(style.font, formula.to_index_formula)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,21 @@
1
+ require_relative "base_index"
2
+
3
+ module Fontist
4
+ 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)
13
+ end
14
+ end
15
+
16
+ def normalize_key(key)
17
+ key.downcase
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,36 @@
1
+ module Fontist
2
+ module Indexes
3
+ class IndexFormula
4
+ def initialize(path)
5
+ @path = path
6
+ end
7
+
8
+ def name
9
+ normalized.sub(/\.yml$/, "")
10
+ end
11
+
12
+ def to_s
13
+ normalized
14
+ end
15
+
16
+ def to_full
17
+ Formula.new_from_file(full_path)
18
+ end
19
+
20
+ def ==(other)
21
+ to_s == other.to_s
22
+ end
23
+
24
+ private
25
+
26
+ def normalized
27
+ escaped = Regexp.escape(Fontist.formulas_path.to_s + "/")
28
+ @path.sub(Regexp.new("^" + escaped), "")
29
+ end
30
+
31
+ def full_path
32
+ Fontist.formulas_path.join(normalized).to_s
33
+ end
34
+ end
35
+ end
36
+ end