fontist 1.6.0 → 1.7.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2dc209840287f224caec09be365402ca43e3605debfed69d01f3f89f12d27093
4
- data.tar.gz: 2ba6e5c3359cfa30afe30ecf96b4f11311e33c12dcce5053b7e37ea9c1750ce9
3
+ metadata.gz: 4832b87f5d5535536b6f2f2e2761bf8ff8dbd82770703f93e201e2c7e81f496d
4
+ data.tar.gz: 32e720d4a33cb78a88bcdd8bf3b80bc24abec544d3dd755a459ae2a1a4a78d6b
5
5
  SHA512:
6
- metadata.gz: b3e2a83f4c56ca2092954e9602827dcc6fe74ba4ba40d52f5e8ce6b0ca532cec67558fcf5a2e24775b13d263843ff2fab045f66838468a9d5fe0f087c3c08e23
7
- data.tar.gz: 5d8968907e2955e7657044ad60c6c8c66ffc0f90d4e06f219b4bde01ad43f949b8dfc24a3477a6eebd269535d14dd26b7222c841c1f2b216f9e5a9111c9c931d
6
+ metadata.gz: 6567b976d958bc852244e5080753eb1fc2e44f8231fe08f3cded4076d510c553565160cf83c108e2e6c309cce042393acf7e19ab34e5a851f4c879a7f9c642ae
7
+ data.tar.gz: 2bab58316fdc830954b93daa716deaac90912ee4906510fad27efba2c0323af8cdb9bade71d5a5f257461063576863b44e1bfc0b72f7cdde1839689acb497f95
@@ -12,8 +12,13 @@ module Fontist
12
12
  desc "install FONT", "Install font by font or formula"
13
13
  option :force, type: :boolean, aliases: :f,
14
14
  desc: "Install even if it's already installed in system"
15
+ option :confirm_license, type: :boolean, desc: "Confirm license agreement"
15
16
  def install(font)
16
- Fontist::Font.install(font, force: options[:force])
17
+ Fontist::Font.install(
18
+ font,
19
+ force: options[:force],
20
+ confirmation: options[:confirm_license] ? "yes" : "no"
21
+ )
17
22
  STATUS_SUCCESS
18
23
  rescue Fontist::Errors::NonSupportedFontError
19
24
  could_not_find_font(font)
@@ -94,6 +99,7 @@ module Fontist
94
99
  option :name, desc: "Example: Times New Roman"
95
100
  option :mirror, repeatable: true
96
101
  option :subarchive, desc: "Subarchive to choose when there are several ones"
102
+ option :subdir, desc: "Subdirectory to take fonts from"
97
103
  def create_formula(url)
98
104
  require "fontist/import/create_formula"
99
105
  name = Fontist::Import::CreateFormula.new(url, options).call
@@ -7,6 +7,7 @@ module Fontist
7
7
  class InvalidResourceError < StandardError; end
8
8
  class TimeoutError < StandardError; end
9
9
  class MissingAttributeError < StandardError; end
10
+ class UnknownFontTypeError < StandardError; end
10
11
  class FontNotFoundError < StandardError; end
11
12
  class BinaryCallError < StandardError; end
12
13
  class ManifestCouldNotBeReadError < StandardError; end
@@ -95,8 +95,10 @@ module Fontist
95
95
  styles = options.fetch(:extract_styles_from_collection, [])
96
96
 
97
97
  unless styles.empty?
98
- styles.map do |type, file|
99
- { type: type, collection: file, font: temp_resource[:filename] }
98
+ styles.map do |attributes|
99
+ filenames = temp_resource.slice(:filename, :source_filename)
100
+ Fontist::Utils::Dsl::CollectionFont.new(attributes.merge(filenames))
101
+ .attributes
100
102
  end
101
103
  end
102
104
  end
@@ -126,5 +128,31 @@ module Fontist
126
128
  def is_progress_bar_enabled
127
129
  options.nil? ? true : options.fetch(:progress_bar, true)
128
130
  end
131
+
132
+ def font_file?(filename)
133
+ source_files.include?(filename)
134
+ end
135
+
136
+ def source_files
137
+ @source_files ||= fonts.flat_map do |font|
138
+ font[:styles].map do |style|
139
+ style[:source_font] || style[:font]
140
+ end
141
+ end
142
+ end
143
+
144
+ def target_filename(source_filename)
145
+ target_filenames[source_filename]
146
+ end
147
+
148
+ def target_filenames
149
+ @target_filenames ||= fonts.flat_map do |font|
150
+ font[:styles].map do |style|
151
+ source = style[:source_font] || style[:font]
152
+ target = style[:font]
153
+ [source, target]
154
+ end
155
+ end.to_h
156
+ end
129
157
  end
130
158
  end
@@ -19,8 +19,8 @@ module Fontist
19
19
  new(font_name: name).find_fonts
20
20
  end
21
21
 
22
- def self.find_styles(font, style)
23
- new(font_name: font, style_name: style).find_styles
22
+ def self.find_styles_with_fonts(font, style)
23
+ new(font_name: font, style_name: style).find_styles_with_fonts
24
24
  end
25
25
 
26
26
  def all
@@ -37,12 +37,16 @@ module Fontist
37
37
  fonts.empty? ? nil : fonts
38
38
  end
39
39
 
40
- def find_styles
40
+ def find_styles_with_fonts
41
41
  formulas.values.flat_map do |formula|
42
42
  formula.fonts.flat_map do |f|
43
- f.styles.select do |s|
43
+ selected = f.styles.select do |s|
44
44
  f.name.casecmp?(font_name) && s.type.casecmp?(style_name)
45
45
  end
46
+
47
+ selected.map do |s|
48
+ { font: f, style: s }
49
+ end
46
50
  end
47
51
  end
48
52
  end
@@ -23,10 +23,23 @@ module Fontist
23
23
  formula.font_collections.each do |collection|
24
24
  provides_font_collection do
25
25
  filename collection.filename
26
+ source_filename collection.source_filename
26
27
 
27
28
  collection.fonts.each do |font|
28
- styles = font.styles.map { |s| [s.type, s.full_name] }.to_h
29
- provides_font font.name, extract_styles_from_collection: styles
29
+ provides_font(
30
+ font.name,
31
+ extract_styles_from_collection: font.styles.map do |style|
32
+ {
33
+ family_name: style.family_name,
34
+ style: style.type,
35
+ full_name: style.full_name,
36
+ post_script_name: style.post_script_name,
37
+ version: style.version,
38
+ description: style.description,
39
+ copyright: style.copyright,
40
+ }
41
+ end
42
+ )
30
43
  end
31
44
  end
32
45
  end
@@ -45,6 +58,7 @@ module Fontist
45
58
  version: style.version,
46
59
  description: style.description,
47
60
  filename: style.font,
61
+ source_filename: style.source_font,
48
62
  copyright: style.copyright,
49
63
  }
50
64
  end
@@ -8,10 +8,6 @@ require_relative "formula_builder"
8
8
  module Fontist
9
9
  module Import
10
10
  class CreateFormula
11
- FONT_PATTERN = /(\.ttf|\.otf)/i.freeze
12
- FONT_COLLECTION_PATTERN = /\.ttc/i.freeze
13
- LICENSE_PATTERN = /(OFL\.txt|UFL\.txt|LICENSE\.txt|COPYING)$/i.freeze
14
-
15
11
  def initialize(url, options = {})
16
12
  @url = url
17
13
  @options = options
@@ -26,41 +22,30 @@ module Fontist
26
22
  def formula
27
23
  builder = FormulaBuilder.new
28
24
  builder.url = @url
29
- builder.archive = download(@url)
30
- builder.extractor = extractor(builder.archive)
25
+ builder.archive = archive
26
+ builder.extractor = extractor
31
27
  builder.options = @options
32
- builder.font_files = font_files(builder.extractor)
33
- builder.font_collection_files = font_collection_files(builder.extractor)
34
- builder.license_text = license_texts(builder.extractor).first
28
+ builder.font_files = extractor.font_files
29
+ builder.font_collection_files = extractor.font_collection_files
30
+ builder.license_text = extractor.license_text
35
31
  builder.formula
36
32
  end
37
33
 
38
- def download(url)
39
- return url if File.exist?(url)
40
-
41
- Fontist::Utils::Downloader.download(url, progress_bar: true).path
34
+ def extractor
35
+ @extractor ||=
36
+ RecursiveExtraction.new(archive,
37
+ subarchive: @options[:subarchive],
38
+ subdir: @options[:subdir])
42
39
  end
43
40
 
44
- def extractor(archive)
45
- RecursiveExtraction.new(archive, subarchive: @options[:subarchive])
41
+ def archive
42
+ @archive ||= download(@url)
46
43
  end
47
44
 
48
- def font_files(extractor)
49
- extractor.extract(FONT_PATTERN) do |path|
50
- Otf::FontFile.new(path)
51
- end
52
- end
53
-
54
- def font_collection_files(extractor)
55
- extractor.extract(FONT_COLLECTION_PATTERN) do |path|
56
- Files::CollectionFile.new(path)
57
- end
58
- end
45
+ def download(url)
46
+ return url if File.exist?(url)
59
47
 
60
- def license_texts(extractor)
61
- extractor.extract(LICENSE_PATTERN) do |path|
62
- File.read(path)
63
- end
48
+ Fontist::Utils::Downloader.download(url, progress_bar: true).path
64
49
  end
65
50
 
66
51
  def save(hash)
@@ -11,10 +11,15 @@ module Fontist
11
11
  def initialize(path)
12
12
  @path = path
13
13
  @fonts = read
14
+ @extension = "ttc"
14
15
  end
15
16
 
16
17
  def filename
17
- File.basename(@path)
18
+ File.basename(@path, ".*") + "." + @extension
19
+ end
20
+
21
+ def source_filename
22
+ File.basename(@path) unless filename == File.basename(@path)
18
23
  end
19
24
 
20
25
  private
@@ -0,0 +1,17 @@
1
+ module Fontist
2
+ module Import
3
+ module Files
4
+ class FileRequirement
5
+ def initialize
6
+ `file -v`
7
+ rescue Errno::ENOENT
8
+ abort "`file` is not available. (Or is PATH not setup properly?)"
9
+ end
10
+
11
+ def call(path)
12
+ Helpers::SystemHelper.run("file --brief '#{path}'")
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,48 @@
1
+ require_relative "file_requirement"
2
+
3
+ module Fontist
4
+ module Import
5
+ module Files
6
+ class FontDetector
7
+ REQUIREMENTS = { file: FileRequirement.new }.freeze
8
+
9
+ FONT_LABELS = ["OpenType font data",
10
+ "TrueType Font data"].freeze
11
+
12
+ COLLECTION_LABEL = "TrueType font collection data".freeze
13
+
14
+ FONT_EXTENSIONS = {
15
+ "OpenType font data" => "otf",
16
+ "TrueType Font data" => "ttf",
17
+ "TrueType font collection data" => "ttc",
18
+ }.freeze
19
+
20
+ def self.detect(path)
21
+ brief = file_brief(path)
22
+
23
+ if brief.start_with?(*FONT_LABELS)
24
+ :font
25
+ elsif brief.start_with?(COLLECTION_LABEL)
26
+ :collection
27
+ else
28
+ :other
29
+ end
30
+ end
31
+
32
+ def self.standard_extension(path)
33
+ brief = file_brief(path)
34
+
35
+ FONT_EXTENSIONS.each do |label, extension|
36
+ return extension if brief.start_with?(label)
37
+ end
38
+
39
+ raise Errors::UnknownFontTypeError.new(path)
40
+ end
41
+
42
+ def self.file_brief(path)
43
+ REQUIREMENTS[:file].call(path)
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -107,7 +107,10 @@ module Fontist
107
107
 
108
108
  collections = @font_collection_files.map do |file|
109
109
  fonts = fonts_from_files(file.fonts, :to_collection_style)
110
- { filename: file.filename, fonts: fonts }
110
+
111
+ { filename: file.filename,
112
+ source_filename: file.source_filename,
113
+ fonts: fonts }.compact
111
114
  end
112
115
 
113
116
  collections.sort_by do |x|
@@ -152,8 +155,9 @@ module Fontist
152
155
  return
153
156
  end
154
157
 
155
- Fontist.ui.error("WARN: ensure it's an open license, otherwise change \
156
- to 'requires_license_agreement'")
158
+ Fontist.ui.error("WARN: ensure it's an open license, otherwise " \
159
+ "change the 'open_license' attribute to " \
160
+ "'requires_license_agreement'")
157
161
 
158
162
  TextHelper.cleanup(@license_text)
159
163
  end
@@ -1,5 +1,6 @@
1
1
  require_relative "../otfinfo/otfinfo_requirement"
2
2
  require_relative "../text_helper"
3
+ require_relative "../files/font_detector"
3
4
 
4
5
  module Fontist
5
6
  module Import
@@ -10,14 +11,19 @@ module Fontist
10
11
  }.freeze
11
12
 
12
13
  STYLE_ATTRIBUTES = %i[family_name type full_name post_script_name
13
- version description copyright font].freeze
14
- COLLECTION_ATTRIBUTES = STYLE_ATTRIBUTES.reject { |a| a == :font }
14
+ version description copyright font
15
+ source_font].freeze
16
+
17
+ COLLECTION_ATTRIBUTES = STYLE_ATTRIBUTES.reject do |a|
18
+ %i[font source_font].include?(a)
19
+ end
15
20
 
16
21
  attr_reader :path
17
22
 
18
23
  def initialize(path)
19
24
  @path = path
20
25
  @info = read
26
+ @extension = detect_extension
21
27
  end
22
28
 
23
29
  def to_style
@@ -55,7 +61,11 @@ module Fontist
55
61
  end
56
62
 
57
63
  def font
58
- File.basename(@path)
64
+ File.basename(@path, ".*") + "." + @extension
65
+ end
66
+
67
+ def source_font
68
+ File.basename(@path) unless font == File.basename(@path)
59
69
  end
60
70
 
61
71
  def copyright
@@ -85,6 +95,10 @@ module Fontist
85
95
  .map { |x| x.map { |y| Fontist::Import::TextHelper.cleanup(y) } }
86
96
  .to_h
87
97
  end
98
+
99
+ def detect_extension
100
+ Files::FontDetector.standard_extension(@path)
101
+ end
88
102
  end
89
103
  end
90
104
  end
@@ -1,28 +1,40 @@
1
1
  require "find"
2
2
  require_relative "extractors"
3
+ require_relative "files/font_detector"
3
4
 
4
5
  module Fontist
5
6
  module Import
6
7
  class RecursiveExtraction
7
- BOTH_FONTS_PATTERN = "**/*.{ttf,otf,ttc}*".freeze
8
+ FONTS_PATTERN = "**/*.{ttf,otf,ttc}".freeze
8
9
  ARCHIVE_EXTENSIONS = %w[zip msi exe cab].freeze
10
+ LICENSE_PATTERN = /(OFL\.txt|UFL\.txt|LICENSE\.txt|COPYING)$/i.freeze
9
11
 
10
- def initialize(archive, subarchive: nil)
12
+ def initialize(archive, subarchive: nil, subdir: nil)
11
13
  @archive = archive
12
14
  @subarchive = subarchive
15
+ @subdir = subdir
13
16
  @operations = []
17
+ @font_files = []
18
+ @collection_files = []
14
19
  end
15
20
 
16
21
  def extension
17
22
  File.extname(filename(@archive)).sub(/^\./, "")
18
23
  end
19
24
 
20
- def extract(pattern)
21
- Array.new.tap do |results|
22
- Find.find(extracted_path) do |path| # rubocop:disable Style/CollectionMethods, Metrics/LineLength
23
- results << yield(path) if path.match(pattern)
24
- end
25
- end
25
+ def font_files
26
+ ensure_extracted
27
+ @font_files
28
+ end
29
+
30
+ def font_collection_files
31
+ ensure_extracted
32
+ @collection_files
33
+ end
34
+
35
+ def license_text
36
+ ensure_extracted
37
+ @license_text
26
38
  end
27
39
 
28
40
  def operations
@@ -50,7 +62,11 @@ module Fontist
50
62
 
51
63
  def extract_recursively(archive)
52
64
  path = operate_on_archive(archive)
53
- return path if fonts_exist?(path)
65
+ match_files(path)
66
+ if matched?
67
+ save_operation_subdir
68
+ return path
69
+ end
54
70
 
55
71
  next_archive = find_archive(path)
56
72
  extract_recursively(next_archive)
@@ -84,9 +100,50 @@ module Fontist
84
100
  @operations << { format: extractor.format }
85
101
  end
86
102
 
87
- def fonts_exist?(path)
88
- fonts = Dir.glob(File.join(path, BOTH_FONTS_PATTERN))
89
- !fonts.empty?
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
108
+ end
109
+
110
+ def match_license(path)
111
+ @license_text ||= File.read(path) if license?(path)
112
+ end
113
+
114
+ def license?(file)
115
+ file.match?(LICENSE_PATTERN)
116
+ end
117
+
118
+ def font_directory?(path, base_path)
119
+ return true unless @subdir
120
+
121
+ relative_path = Pathname.new(path).relative_path_from(base_path).to_s
122
+ dirname = File.dirname(relative_path)
123
+ normalized_pattern = @subdir.chomp("/")
124
+ File.fnmatch?(normalized_pattern, dirname)
125
+ end
126
+
127
+ def match_font(path)
128
+ case Files::FontDetector.detect(path)
129
+ when :font
130
+ @font_files << Otf::FontFile.new(path)
131
+ when :collection
132
+ @collection_files << Files::CollectionFile.new(path)
133
+ end
134
+ end
135
+
136
+ def matched?
137
+ [@font_files, @collection_files].any? do |files|
138
+ files.size.positive?
139
+ end
140
+ end
141
+
142
+ def save_operation_subdir
143
+ return unless @subdir
144
+
145
+ @operations.last[:options] ||= {}
146
+ @operations.last[:options][:fonts_sub_dir] = @subdir
90
147
  end
91
148
 
92
149
  def find_archive(path)
@@ -1,8 +1,8 @@
1
- require_relative "common"
1
+ require_relative "locations"
2
2
 
3
3
  module Fontist
4
4
  module Manifest
5
- class Install < Common
5
+ class Install < Locations
6
6
  def initialize(manifest, confirmation: "no")
7
7
  @manifest = manifest
8
8
  @confirmation = confirmation
@@ -15,15 +15,11 @@ module Fontist
15
15
  private
16
16
 
17
17
  def file_paths(font, style)
18
- paths = find_installed_font(font, style)
19
- return paths unless paths.empty?
18
+ paths = super
19
+ return paths unless paths["paths"].empty?
20
20
 
21
21
  install_font(font)
22
- find_installed_font(font, style)
23
- end
24
-
25
- def find_installed_font(font, style)
26
- Fontist::SystemFont.find_with_style(font, style)
22
+ super
27
23
  end
28
24
 
29
25
  def install_font(font)
@@ -1,12 +1,59 @@
1
- require_relative "common"
2
-
3
1
  module Fontist
4
2
  module Manifest
5
- class Locations < Common
3
+ class Locations
4
+ def initialize(manifest)
5
+ @manifest = manifest
6
+ end
7
+
8
+ def self.call(manifest)
9
+ new(manifest).call
10
+ end
11
+
12
+ def call
13
+ font_names.zip(font_paths).to_h
14
+ end
15
+
6
16
  private
7
17
 
18
+ def font_names
19
+ fonts.keys
20
+ end
21
+
22
+ def fonts
23
+ @fonts ||= begin
24
+ unless File.exist?(@manifest)
25
+ raise Fontist::Errors::ManifestCouldNotBeFoundError
26
+ end
27
+
28
+ fonts = YAML.load_file(@manifest)
29
+ unless fonts.is_a?(Hash)
30
+ raise Fontist::Errors::ManifestCouldNotBeReadError
31
+ end
32
+
33
+ fonts
34
+ end
35
+ end
36
+
37
+ def font_paths
38
+ fonts.map do |font, styles|
39
+ styles_to_ary = [styles].flatten
40
+ style_paths_map(font, styles_to_ary)
41
+ end
42
+ end
43
+
44
+ def style_paths_map(font, names)
45
+ paths = style_paths(font, names)
46
+ names.zip(paths).to_h
47
+ end
48
+
49
+ def style_paths(font, names)
50
+ names.map do |style|
51
+ file_paths(font, style)
52
+ end
53
+ end
54
+
8
55
  def file_paths(font, style)
9
- Fontist::SystemFont.find_with_style(font, style)
56
+ Fontist::SystemFont.find_with_style(font, style).transform_keys(&:to_s)
10
57
  end
11
58
  end
12
59
  end
@@ -22,10 +22,10 @@ module Fontist
22
22
  end
23
23
 
24
24
  def find_with_style
25
- paths = lookup_using_font_and_style
26
- return paths unless paths.empty?
25
+ styles = Formula.find_styles_with_fonts(font, style)
27
26
 
28
- grep_font_paths(font, style)
27
+ { full_name: style_full_name(styles),
28
+ paths: style_paths(styles) }
29
29
  end
30
30
 
31
31
  private
@@ -95,9 +95,22 @@ module Fontist
95
95
  @default_sources ||= YAML.load(system_path_file)["system"][user_os.to_s]
96
96
  end
97
97
 
98
- def lookup_using_font_and_style
99
- styles = Formula.find_styles(font, style)
100
- filenames = styles.map(&:font)
98
+ def style_full_name(styles)
99
+ return if styles.empty?
100
+
101
+ s = styles.first
102
+ s[:style]["full_name"] || s[:font]["name"]
103
+ end
104
+
105
+ def style_paths(styles)
106
+ filenames = styles.map { |x| x[:style]["font"] }
107
+ paths = lookup_using_filenames(filenames)
108
+ return paths unless paths.empty?
109
+
110
+ grep_font_paths(font, style)
111
+ end
112
+
113
+ def lookup_using_filenames(filenames)
101
114
  filenames.flat_map do |filename|
102
115
  search_font_paths(filename)
103
116
  end
@@ -2,6 +2,7 @@ require "fontist/utils/ui"
2
2
  require "fontist/utils/system"
3
3
  require "fontist/utils/dsl"
4
4
  require "fontist/utils/dsl/font"
5
+ require "fontist/utils/dsl/collection_font"
5
6
  require "fontist/utils/downloader"
6
7
  require "fontist/utils/zip_extractor"
7
8
  require "fontist/utils/exe_extractor"
@@ -47,6 +47,10 @@ module Fontist
47
47
  instance.temp_resource.merge!(filename: name)
48
48
  end
49
49
 
50
+ def source_filename(name)
51
+ instance.temp_resource.merge!(source_filename: name)
52
+ end
53
+
50
54
  def provides_font(font, options = {})
51
55
  font_styles = instance.extract_font_styles(options)
52
56
  instance.font_list.push(name: font, styles: font_styles)
@@ -0,0 +1,36 @@
1
+ module Fontist
2
+ module Utils
3
+ module Dsl
4
+ class CollectionFont
5
+ REQUIRED_ATTRIBUTES = %i[style].freeze
6
+
7
+ attr_reader :attributes
8
+
9
+ def initialize(attributes)
10
+ REQUIRED_ATTRIBUTES.each do |required_attribute|
11
+ unless attributes[required_attribute]
12
+ raise(Fontist::Errors::MissingAttributeError.new(
13
+ "Missing attribute: #{required_attribute}"
14
+ ))
15
+ end
16
+ end
17
+
18
+ self.attributes = attributes
19
+ end
20
+
21
+ def attributes=(attrs)
22
+ @attributes = { family_name: attrs[:family_name],
23
+ type: attrs[:style],
24
+ collection: attrs[:full_name],
25
+ full_name: attrs[:full_name],
26
+ post_script_name: attrs[:post_script_name],
27
+ version: attrs[:version],
28
+ description: attrs[:description],
29
+ copyright: attrs[:copyright],
30
+ font: attrs[:filename],
31
+ source_font: attrs[:source_filename] }
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -29,7 +29,8 @@ module Fontist
29
29
  version: attrs[:version],
30
30
  description: attrs[:description],
31
31
  copyright: attrs[:copyright],
32
- font: attrs[:filename] }
32
+ font: attrs[:filename],
33
+ source_font: attrs[:source_filename] }
33
34
  end
34
35
  end
35
36
  end
@@ -8,7 +8,7 @@ module Fontist
8
8
 
9
9
  Fontist.ui.say(%(Installing font "#{key}".))
10
10
  cab_file = decompressor.search(exe_file)
11
- cabbed_fonts = grep_fonts(cab_file.files, font_ext) || []
11
+ cabbed_fonts = grep_fonts(cab_file.files) || []
12
12
  fonts_paths = extract_cabbed_fonts_to_assets(cabbed_fonts)
13
13
 
14
14
  block_given? ? yield(fonts_paths) : fonts_paths
@@ -29,10 +29,10 @@ module Fontist
29
29
  )
30
30
  end
31
31
 
32
- def grep_fonts(file, font_ext)
32
+ def grep_fonts(file)
33
33
  Array.new.tap do |fonts|
34
34
  while file
35
- fonts.push(file) if file.filename.match(font_ext)
35
+ fonts.push(file) if font_file?(file.filename)
36
36
  file = file.next
37
37
  end
38
38
  end
@@ -41,7 +41,8 @@ module Fontist
41
41
  def extract_cabbed_fonts_to_assets(cabbed_fonts)
42
42
  Array.new.tap do |fonts|
43
43
  cabbed_fonts.each do |font|
44
- font_path = fonts_path.join(font.filename).to_s
44
+ target_filename = target_filename(font.filename)
45
+ font_path = fonts_path.join(target_filename).to_s
45
46
  decompressor.extract(font, font_path)
46
47
 
47
48
  fonts.push(font_path)
@@ -4,41 +4,49 @@ require "pathname"
4
4
  module Fontist
5
5
  module Utils
6
6
  module ZipExtractor
7
- # fonts_sub_dir is unused now, but formulas have this option
8
- # rubocop:disable Lint/UnusedMethodArgument
9
- def zip_extract(resource, download: true, fonts_sub_dir: "")
7
+ def zip_extract(resource, download: true, fonts_sub_dir: nil)
10
8
  zip_file = download_file(resource) if download
11
9
  zip_file ||= resource.urls.first
12
10
 
13
11
  Fontist.ui.say(%(Installing font "#{key}".))
14
- fonts_paths = unzip_fonts(zip_file)
12
+ fonts_paths = unzip_fonts(zip_file, fonts_sub_dir)
15
13
  block_given? ? yield(fonts_paths) : fonts_paths
16
14
  end
17
- # rubocop:enable Lint/UnusedMethodArgument
18
15
 
19
16
  alias_method :unzip, :zip_extract
20
17
 
21
18
  private
22
19
 
23
20
  # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
24
- def unzip_fonts(file)
21
+ def unzip_fonts(file, subdir)
25
22
  Zip.on_exists_proc = true
26
23
 
27
24
  Array.new.tap do |fonts|
28
25
  Zip::File.open(file) do |zip_file|
29
- zip_file.glob("**/*.{ttf,ttc,otf}").each do |entry|
26
+ zip_file.each do |entry|
30
27
  if entry.name
31
- filename = Pathname.new(entry.name).basename
32
- font_path = fonts_path.join(filename.to_s)
33
- fonts.push(font_path.to_s)
28
+ filename = Pathname.new(entry.name).basename.to_s
29
+ if font_directory?(entry.name, subdir) && font_file?(filename)
30
+ target_filename = target_filename(filename)
31
+ font_path = fonts_path.join(target_filename)
32
+ fonts.push(font_path.to_s)
34
33
 
35
- entry.extract(font_path)
34
+ entry.extract(font_path)
35
+ end
36
36
  end
37
37
  end
38
38
  end
39
39
  end
40
40
  end
41
41
  # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
42
+
43
+ def font_directory?(path, subdir)
44
+ return true unless subdir
45
+
46
+ dirname = File.dirname(path)
47
+ normalized_pattern = subdir.chomp("/")
48
+ File.fnmatch?(normalized_pattern, dirname)
49
+ end
42
50
  end
43
51
  end
44
52
  end
@@ -1,3 +1,3 @@
1
1
  module Fontist
2
- VERSION = "1.6.0".freeze
2
+ VERSION = "1.7.0".freeze
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fontist
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.0
4
+ version: 1.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2020-11-20 00:00:00.000000000 Z
12
+ date: 2020-11-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: down
@@ -284,6 +284,8 @@ files:
284
284
  - lib/fontist/import/extractors/seven_zip_extractor.rb
285
285
  - lib/fontist/import/extractors/zip_extractor.rb
286
286
  - lib/fontist/import/files/collection_file.rb
287
+ - lib/fontist/import/files/file_requirement.rb
288
+ - lib/fontist/import/files/font_detector.rb
287
289
  - lib/fontist/import/formula_builder.rb
288
290
  - lib/fontist/import/formula_serializer.rb
289
291
  - lib/fontist/import/google.rb
@@ -306,7 +308,6 @@ files:
306
308
  - lib/fontist/import/template_helper.rb
307
309
  - lib/fontist/import/text_helper.rb
308
310
  - lib/fontist/manifest.rb
309
- - lib/fontist/manifest/common.rb
310
311
  - lib/fontist/manifest/install.rb
311
312
  - lib/fontist/manifest/locations.rb
312
313
  - lib/fontist/registry.rb
@@ -316,6 +317,7 @@ files:
316
317
  - lib/fontist/utils/cache.rb
317
318
  - lib/fontist/utils/downloader.rb
318
319
  - lib/fontist/utils/dsl.rb
320
+ - lib/fontist/utils/dsl/collection_font.rb
319
321
  - lib/fontist/utils/dsl/font.rb
320
322
  - lib/fontist/utils/exe_extractor.rb
321
323
  - lib/fontist/utils/msi_extractor.rb
@@ -1,60 +0,0 @@
1
- module Fontist
2
- module Manifest
3
- class Common
4
- def initialize(manifest)
5
- @manifest = manifest
6
- end
7
-
8
- def self.call(manifest)
9
- new(manifest).call
10
- end
11
-
12
- def call
13
- font_names.zip(font_paths).to_h
14
- end
15
-
16
- private
17
-
18
- def font_names
19
- fonts.keys
20
- end
21
-
22
- def fonts
23
- @fonts ||= begin
24
- unless File.exist?(@manifest)
25
- raise Fontist::Errors::ManifestCouldNotBeFoundError
26
- end
27
-
28
- fonts = YAML.load_file(@manifest)
29
- unless fonts.is_a?(Hash)
30
- raise Fontist::Errors::ManifestCouldNotBeReadError
31
- end
32
-
33
- fonts
34
- end
35
- end
36
-
37
- def font_paths
38
- fonts.map do |font, styles|
39
- styles_to_ary = [styles].flatten
40
- style_paths_map(font, styles_to_ary)
41
- end
42
- end
43
-
44
- def style_paths_map(font, names)
45
- paths = style_paths(font, names)
46
- names.zip(paths).to_h
47
- end
48
-
49
- def style_paths(font, names)
50
- names.map do |style|
51
- file_paths(font, style)
52
- end
53
- end
54
-
55
- def file_paths(_font, _style)
56
- raise NotImplementedError.new("Implement #file_paths in child class")
57
- end
58
- end
59
- end
60
- end