fontist 1.13.2 → 1.14.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,141 +1,57 @@
1
1
  require "plist"
2
2
  require "nokogiri"
3
- require "fontist/import"
4
- require_relative "recursive_extraction"
5
- require_relative "helpers/hash_helper"
6
- require_relative "manual_formula_builder"
3
+ require "fontist/import/create_formula"
7
4
 
8
5
  module Fontist
9
6
  module Import
10
7
  class Macos
11
8
  FONT_XML = "/System/Library/AssetsV2/com_apple_MobileAsset_Font6/com_apple_MobileAsset_Font6.xml".freeze # rubocop:disable Layout/LineLength
12
- DESCRIPTION = "Fonts included with macOS %<name>s".freeze
13
-
14
- INSTRUCTIONS = <<~INSTRUCTIONS.freeze
15
- To download and enable any of these fonts:
16
-
17
- 1. Open Font Book, which is in your Applications folder.
18
- 2. Select All Fonts in the sidebar, or use the Search field to find the font that you want to download. Fonts that are not already downloaded appear dimmed in the list of fonts.
19
- 3. Select the dimmed font and choose Edit > Download, or Control-click it and choose Download from the pop-up menu.
20
- INSTRUCTIONS
21
-
22
- def initialize(options = {})
23
- @options = options
24
- end
9
+ HOMEPAGE = "https://support.apple.com/en-om/HT211240#document".freeze
25
10
 
26
11
  def call
27
- downloadable_fonts = fetch_fonts_list
28
- links = fetch_links(downloadable_fonts)
29
- archives = download(links)
30
- store_in_dir(archives) do |dir|
31
- create_formula(dir)
12
+ links.each do |link|
13
+ create_formula(link)
32
14
  end
33
- end
34
15
 
35
- private
36
-
37
- def fetch_fonts_list
38
- html = Net::HTTP.get(URI.parse(@options[:fonts_link]))
16
+ Fontist::Index.rebuild
39
17
 
40
- document = Nokogiri::HTML.parse(html)
41
- document.css("#sections div.grid2col:nth-of-type(3) div ul > li",
42
- "#sections div.grid2col:nth-of-type(4) div ul > li")
43
- .map(&:text)
18
+ Fontist.ui.success("Created #{links.size} formulas.")
44
19
  end
45
20
 
46
- def fetch_links(downloadable_fonts)
47
- data = Plist.parse_xml(FONT_XML)
48
- assets = downloadable_assets(data, downloadable_fonts)
49
- assets_links(assets)
50
- end
51
-
52
- def downloadable_assets(data, downloadable_fonts)
53
- data["Assets"].select do |x|
54
- x["FontInfo4"].any? do |i|
55
- downloadable_fonts.find do |d|
56
- d.start_with?(i["FontFamilyName"])
57
- end
58
- end
59
- end
60
- end
21
+ private
61
22
 
62
- def assets_links(assets)
63
- assets.map do |x|
23
+ def links
24
+ data = Plist.parse_xml(FONT_XML)
25
+ data["Assets"].map do |x|
64
26
  x.values_at("__BaseURL", "__RelativePath").join
65
27
  end
66
28
  end
67
29
 
68
- def download(links)
69
- links.map do |url|
70
- Fontist::Utils::Downloader.download(url, progress_bar: true).path
71
- end
72
- end
73
-
74
- def store_in_dir(archives)
75
- Dir.mktmpdir do |dir|
76
- archives.each do |archive|
77
- FileUtils.ln(archive, dir)
78
- end
79
-
80
- yield dir
81
- end
82
- end
83
-
84
- def create_formula(archives_dir)
85
- extractor = RecursiveExtraction.new(archives_dir)
86
- path = save(formula(archives_dir, extractor))
30
+ def create_formula(url)
31
+ path = Fontist::Import::CreateFormula.new(
32
+ url,
33
+ platforms: platforms,
34
+ homepage: homepage,
35
+ requires_license_agreement: license,
36
+ formula_dir: formula_dir,
37
+ keep_existing: true,
38
+ ).call
87
39
  Fontist.ui.success("Formula has been successfully created: #{path}")
88
40
 
89
41
  path
90
42
  end
91
43
 
92
- def formula(archive, extractor)
93
- builder = ManualFormulaBuilder.new
94
- setup_strings(builder, archive)
95
- setup_files(builder, extractor)
96
- builder.formula
97
- end
98
-
99
- def setup_strings(builder, archive)
100
- builder.url = archive
101
- builder.archive = archive
102
- builder.platforms = platforms
103
- builder.instructions = instructions
104
- builder.description = description
105
- builder.options = builder_options
106
- end
107
-
108
44
  def platforms
109
- major_version = Sys::Uname.release.split(".").first
110
-
111
- ["macos-#{major_version}"]
112
- end
113
-
114
- def instructions
115
- INSTRUCTIONS.strip
116
- end
117
-
118
- def description
119
- format(DESCRIPTION, name: @options[:name])
120
- end
121
-
122
- def builder_options
123
- @options.merge(homepage: @options[:fonts_link])
45
+ ["macos"]
124
46
  end
125
47
 
126
- def setup_files(builder, extractor)
127
- builder.extractor = extractor
128
- builder.font_files = extractor.font_files
129
- builder.font_collection_files = extractor.font_collection_files
130
- builder.license_text = extractor.license_text
48
+ def homepage
49
+ HOMEPAGE
131
50
  end
132
51
 
133
- def save(hash)
134
- filename = Import.name_to_filename(@options[:name])
135
- path = File.join(formula_dir, filename)
136
- yaml = YAML.dump(Helpers::HashHelper.stringify_keys(hash))
137
- File.write(path, yaml)
138
- path
52
+ def license
53
+ @license ||= File.read(File.expand_path("macos/macos_license.txt",
54
+ __dir__))
139
55
  end
140
56
 
141
57
  def formula_dir
@@ -94,12 +94,22 @@ module Fontist
94
94
  def match_font(path)
95
95
  case Files::FontDetector.detect(path)
96
96
  when :font
97
- @font_files << Otf::FontFile.new(path)
97
+ file = Otf::FontFile.new(path)
98
+ @font_files << file unless already_exist?(file)
98
99
  when :collection
99
100
  @collection_files << Files::CollectionFile.new(path)
100
101
  end
101
102
  end
102
103
 
104
+ def already_exist?(candidate)
105
+ @font_files.any? do |file|
106
+ file.family_name == candidate.family_name &&
107
+ file.type == candidate.type &&
108
+ file.version == candidate.version &&
109
+ file.font == candidate.font
110
+ end
111
+ end
112
+
103
113
  def font_directory?(path)
104
114
  return true unless subdirectory_pattern
105
115
 
@@ -20,7 +20,7 @@ module Fontist
20
20
  min, max = strs.minmax
21
21
  idx = min.size.times { |i| break i if min[i] != max[i] }
22
22
  prefix = min[0...idx].strip
23
- return if prefix.empty?
23
+ return if prefix.size < 2
24
24
 
25
25
  prefix
26
26
  end
@@ -2,15 +2,27 @@ module Fontist
2
2
  class ImportCLI < Thor
3
3
  include CLI::ClassOptions
4
4
 
5
+ desc "google", "Import Google fonts"
6
+ def google
7
+ handle_class_options(options)
8
+ require "fontist/import/google_import"
9
+ Fontist::Import::GoogleImport.new.call
10
+ CLI::STATUS_SUCCESS
11
+ end
12
+
5
13
  desc "macos", "Create formula for on-demand macOS fonts"
6
- option :name, desc: "Example: Big Sur", required: true
7
- option :fonts_link,
8
- desc: "A link to a list of available fonts in a current OS",
9
- required: true
10
14
  def macos
11
15
  handle_class_options(options)
12
16
  require_relative "import/macos"
13
- Import::Macos.new(options).call
17
+ Import::Macos.new.call
18
+ CLI::STATUS_SUCCESS
19
+ end
20
+
21
+ desc "sil", "Import formulas from SIL"
22
+ def sil
23
+ handle_class_options(options)
24
+ require "fontist/import/sil_import"
25
+ Fontist::Import::SilImport.new.call
14
26
  CLI::STATUS_SUCCESS
15
27
  end
16
28
  end
@@ -97,8 +97,17 @@ module Fontist
97
97
 
98
98
  def generate_file_path(source)
99
99
  dir = Dir.mktmpdir(nil, Fontist.downloads_path)
100
- filename = source.original_filename
101
- File.join(dir, filename)
100
+ File.join(dir, filename(source))
101
+ end
102
+
103
+ def filename(source)
104
+ if File.extname(source.original_filename).empty? && source.content_type
105
+ require "mime/types"
106
+ ext = MIME::Types[source.content_type].first&.preferred_extension
107
+ return "#{source.original_filename}.#{ext}" if ext
108
+ end
109
+
110
+ source.original_filename
102
111
  end
103
112
 
104
113
  def move(source_file, target_path)
@@ -28,6 +28,14 @@ module Fontist
28
28
  def self.match?(platform)
29
29
  user_os_with_version.start_with?(platform)
30
30
  end
31
+
32
+ def self.fontconfig_installed?
33
+ Helpers.silence_stream($stderr) do
34
+ !!Helpers.run("fc-cache -V")
35
+ end
36
+ rescue Errno::ENOENT
37
+ false
38
+ end
31
39
  end
32
40
  end
33
41
  end
data/lib/fontist/utils.rb CHANGED
@@ -1,9 +1,6 @@
1
1
  require "fontist/utils/ui"
2
2
  require "fontist/utils/locking"
3
3
  require "fontist/utils/system"
4
- require "fontist/utils/dsl"
5
- require "fontist/utils/dsl/font"
6
- require "fontist/utils/dsl/collection_font"
7
4
  require "fontist/utils/downloader"
8
5
 
9
6
  module Fontist
@@ -1,3 +1,3 @@
1
1
  module Fontist
2
- VERSION = "1.13.2".freeze
2
+ VERSION = "1.14.2".freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fontist
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.13.2
4
+ version: 1.14.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-01-29 00:00:00.000000000 Z
11
+ date: 2022-04-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: down
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '1.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: mime-types
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: sys-uname
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -304,9 +318,10 @@ files:
304
318
  - lib/fontist/font.rb
305
319
  - lib/fontist/font_installer.rb
306
320
  - lib/fontist/font_path.rb
321
+ - lib/fontist/fontconfig.rb
322
+ - lib/fontist/fontconfig_cli.rb
307
323
  - lib/fontist/formula.rb
308
324
  - lib/fontist/formula_picker.rb
309
- - lib/fontist/google_cli.rb
310
325
  - lib/fontist/helpers.rb
311
326
  - lib/fontist/import.rb
312
327
  - lib/fontist/import/convert_formulas.rb
@@ -324,6 +339,7 @@ files:
324
339
  - lib/fontist/import/helpers/hash_helper.rb
325
340
  - lib/fontist/import/helpers/system_helper.rb
326
341
  - lib/fontist/import/macos.rb
342
+ - lib/fontist/import/macos/macos_license.txt
327
343
  - lib/fontist/import/manual_formula_builder.rb
328
344
  - lib/fontist/import/otf/font_file.rb
329
345
  - lib/fontist/import/otf_parser.rb
@@ -356,9 +372,6 @@ files:
356
372
  - lib/fontist/utils.rb
357
373
  - lib/fontist/utils/cache.rb
358
374
  - lib/fontist/utils/downloader.rb
359
- - lib/fontist/utils/dsl.rb
360
- - lib/fontist/utils/dsl/collection_font.rb
361
- - lib/fontist/utils/dsl/font.rb
362
375
  - lib/fontist/utils/locking.rb
363
376
  - lib/fontist/utils/system.rb
364
377
  - lib/fontist/utils/ui.rb
@@ -1,21 +0,0 @@
1
- module Fontist
2
- class GoogleCLI < Thor
3
- include CLI::ClassOptions
4
-
5
- desc "check", "Check Google fonts for updates"
6
- def check
7
- handle_class_options(options)
8
- require "fontist/import/google_check"
9
- Fontist::Import::GoogleCheck.new.call
10
- CLI::STATUS_SUCCESS
11
- end
12
-
13
- desc "import", "Import Google fonts"
14
- def import
15
- handle_class_options(options)
16
- require "fontist/import/google_import"
17
- Fontist::Import::GoogleImport.new.call
18
- CLI::STATUS_SUCCESS
19
- end
20
- end
21
- end
@@ -1,36 +0,0 @@
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
@@ -1,38 +0,0 @@
1
- module Fontist
2
- module Utils
3
- module Dsl
4
- class Font
5
- REQUIRED_ATTRIBUTES = %i[family_name
6
- style
7
- full_name
8
- filename].freeze
9
-
10
- attr_reader :attributes
11
-
12
- def initialize(attributes)
13
- REQUIRED_ATTRIBUTES.each do |required_attribute|
14
- unless attributes[required_attribute]
15
- raise(Fontist::Errors::MissingAttributeError.new(
16
- "Missing attribute: #{required_attribute}"
17
- ))
18
- end
19
- end
20
-
21
- self.attributes = attributes
22
- end
23
-
24
- def attributes=(attrs)
25
- @attributes = { family_name: attrs[:family_name],
26
- type: attrs[:style],
27
- full_name: attrs[:full_name],
28
- post_script_name: attrs[:post_script_name],
29
- version: attrs[:version],
30
- description: attrs[:description],
31
- copyright: attrs[:copyright],
32
- font: attrs[:filename],
33
- source_font: attrs[:source_filename] }
34
- end
35
- end
36
- end
37
- end
38
- end
@@ -1,85 +0,0 @@
1
- module Fontist
2
- module Utils
3
- module Dsl
4
- def key(key)
5
- instance.key = key
6
- end
7
-
8
- def desc(description)
9
- instance.description = description
10
- end
11
-
12
- def homepage(homepage)
13
- instance.homepage = homepage
14
- end
15
-
16
- def resource(resource_name, &block)
17
- instance.resources[resource_name] ||= {}
18
- instance.temp_resource = instance.resources[resource_name]
19
-
20
- yield(block) if block_given?
21
- instance.temp_resource = {}
22
- end
23
-
24
- def url(url)
25
- instance.temp_resource.merge!(urls: [url])
26
- end
27
-
28
- def urls(urls = [])
29
- instance.temp_resource.merge!(urls: urls)
30
- end
31
-
32
- def sha256(sha256)
33
- instance.temp_resource.merge!(sha256: sha256)
34
- end
35
-
36
- def file_size(file_size)
37
- instance.temp_resource.merge!(file_size: file_size )
38
- end
39
-
40
- def provides_font_collection(name = nil, &block)
41
- instance.temp_resource = {}
42
- yield(block) if block_given?
43
- instance.temp_resource = {}
44
- end
45
-
46
- def filename(name)
47
- instance.temp_resource.merge!(filename: name)
48
- end
49
-
50
- def source_filename(name)
51
- instance.temp_resource.merge!(source_filename: name)
52
- end
53
-
54
- def provides_font(font, options = {})
55
- font_styles = instance.extract_font_styles(options)
56
- instance.font_list.push(name: font, styles: font_styles)
57
- end
58
-
59
- def test
60
- end
61
-
62
- def requires_license_agreement(license)
63
- instance.license = license
64
- instance.license_required = true
65
- end
66
-
67
- def open_license(license)
68
- instance.license = license
69
- instance.license_required = false
70
- end
71
-
72
- def copyright(copyright)
73
- instance.copyright = copyright
74
- end
75
-
76
- def license_url(url)
77
- instance.license_url = url
78
- end
79
-
80
- def display_progress_bar(value )
81
- instance.options = (instance.options || {}).merge(progress_bar: value )
82
- end
83
- end
84
- end
85
- end