fontist 1.8.3 → 1.8.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,29 @@
1
+ require "fontist/indexes/filename_index"
2
+
3
+ module Fontist
4
+ class FontPath
5
+ def initialize(path)
6
+ @path = path
7
+ end
8
+
9
+ def to_s
10
+ [].tap do |s|
11
+ s << "-"
12
+ s << @path
13
+ s << "(from #{formulas.join(' or ')} formula)" if formulas.any?
14
+ end.join(" ")
15
+ end
16
+
17
+ def formulas
18
+ @formulas ||= if fontist_font?
19
+ Indexes::FilenameIndex.from_yaml.load_index_formulas(File.basename(@path)).map(&:name)
20
+ else
21
+ []
22
+ end
23
+ end
24
+
25
+ def fontist_font?
26
+ @path.start_with?(Fontist.fonts_path.to_s)
27
+ end
28
+ end
29
+ end
@@ -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,25 +1,22 @@
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
22
- File.extname(filename(@archive)).sub(/^\./, "")
19
+ fetch_extension(@archive)
23
20
  end
24
21
 
25
22
  def font_files
@@ -39,11 +36,22 @@ 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
+
51
+ def fetch_extension(file)
52
+ File.extname(filename(file)).sub(/^\./, "")
53
+ end
54
+
47
55
  def filename(file)
48
56
  if file.respond_to?(:original_filename)
49
57
  file.original_filename
@@ -53,58 +61,21 @@ module Fontist
53
61
  end
54
62
 
55
63
  def ensure_extracted
56
- extracted_path
57
- end
58
-
59
- def extracted_path
60
- @extracted_path ||= extract_recursively(@archive)
61
- end
64
+ return if @extracted
62
65
 
63
- def extract_recursively(archive)
64
- path = operate_on_archive(archive)
65
- match_files(path)
66
- if matched?
67
- save_operation_subdir
68
- return path
69
- end
70
-
71
- next_archive = find_archive(path)
72
- extract_recursively(next_archive)
73
- end
74
-
75
- def operate_on_archive(archive)
76
- extractor = choose_extractor(archive)
77
- Fontist.ui.say("Extracting #{archive} with #{extractor.class.name}")
78
-
79
- save_operation(extractor)
80
- extractor.extract
66
+ extract_data(@archive)
67
+ @extracted = true
81
68
  end
82
69
 
83
- # rubocop:disable Metrics/MethodLength
84
- def choose_extractor(archive)
85
- case filename(archive)
86
- when /\.msi$/i
87
- Extractors::OleExtractor.new(archive)
88
- when /\.cab$/i
89
- Extractors::CabExtractor.new(archive)
90
- when /\.exe$/i
91
- extractor = Extractors::SevenZipExtractor.new(archive)
92
- extractor.try ? extractor : Extractors::CabExtractor.new(archive)
93
- else
94
- Extractors::ZipExtractor.new(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)
95
74
  end
96
75
  end
97
- # rubocop:enable Metrics/MethodLength
98
76
 
99
- def save_operation(extractor)
100
- @operations << { format: extractor.format }
101
- end
102
-
103
- def match_files(dir_path)
104
- Find.find(dir_path) do |entry_path| # rubocop:disable Style/CollectionMethods
105
- match_license(entry_path)
106
- match_font(entry_path) if font_directory?(entry_path, dir_path)
107
- end
77
+ def path(file)
78
+ file.respond_to?(:path) ? file.path : file
108
79
  end
109
80
 
110
81
  def match_license(path)
@@ -115,18 +86,6 @@ module Fontist
115
86
  file.match?(LICENSE_PATTERN)
116
87
  end
117
88
 
118
- def font_directory?(path, base_path)
119
- return true unless @subdir
120
-
121
- # https://bugs.ruby-lang.org/issues/10011
122
- base_path = Pathname.new(base_path)
123
-
124
- relative_path = Pathname.new(path).relative_path_from(base_path).to_s
125
- dirname = File.dirname(relative_path)
126
- normalized_pattern = @subdir.chomp("/")
127
- File.fnmatch?(normalized_pattern, dirname)
128
- end
129
-
130
89
  def match_font(path)
131
90
  case Files::FontDetector.detect(path)
132
91
  when :font
@@ -136,53 +95,14 @@ module Fontist
136
95
  end
137
96
  end
138
97
 
139
- def matched?
140
- [@font_files, @collection_files].any? do |files|
141
- files.size.positive?
142
- end
143
- end
144
-
145
- def save_operation_subdir
146
- return unless @subdir
147
-
148
- @operations.last[:options] ||= {}
149
- @operations.last[:options][:fonts_sub_dir] = @subdir
150
- end
151
-
152
- def find_archive(path)
153
- children = Dir.entries(path) - [".", ".."] # ruby 2.4 compat
154
- paths = children.map { |file| File.join(path, file) }
155
- by_subarchive(paths) || by_size(paths)
156
- end
98
+ def font_directory?(path)
99
+ return true unless subdirectory_pattern
157
100
 
158
- def by_subarchive(paths)
159
- return unless @subarchive
160
-
161
- path_found = paths.detect do |path|
162
- @subarchive == File.basename(path)
163
- end
164
-
165
- return unless path_found
166
-
167
- save_operation_subarchive(path_found)
168
-
169
- path_found
170
- end
171
-
172
- def save_operation_subarchive(path)
173
- @operations.last[:options] ||= {}
174
- @operations.last[:options][:subarchive] = File.basename(path)
175
- end
176
-
177
- def by_size(paths)
178
- paths.max_by do |path|
179
- [file_type(path), File.size(path)]
180
- end
101
+ File.fnmatch?(subdirectory_pattern, File.dirname(path))
181
102
  end
182
103
 
183
- def file_type(file_path)
184
- extension = File.extname(file_path).delete(".")
185
- ARCHIVE_EXTENSIONS.include?(extension) ? 1 : 0
104
+ def subdirectory_pattern
105
+ @subdirectory_pattern ||= "*" + @subdir.chomp("/") if @subdir
186
106
  end
187
107
  end
188
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