fontist 1.11.6 → 1.13.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,5 @@
1
1
  require "fontist/import"
2
2
  require_relative "recursive_extraction"
3
- require_relative "otf/font_file"
4
- require_relative "files/collection_file"
5
3
  require_relative "helpers/hash_helper"
6
4
  require_relative "formula_builder"
7
5
 
@@ -14,21 +12,29 @@ module Fontist
14
12
  end
15
13
 
16
14
  def call
17
- save(formula)
15
+ save(builder)
18
16
  end
19
17
 
20
18
  private
21
19
 
22
- def formula
20
+ def builder
23
21
  builder = FormulaBuilder.new
24
- builder.url = @url
22
+ setup_strings(builder, archive)
23
+ setup_files(builder)
24
+ builder
25
+ end
26
+
27
+ def setup_strings(builder, archive)
25
28
  builder.archive = archive
26
- builder.extractor = extractor
29
+ builder.url = @url
27
30
  builder.options = @options
31
+ end
32
+
33
+ def setup_files(builder)
34
+ builder.extractor = extractor
28
35
  builder.font_files = extractor.font_files
29
36
  builder.font_collection_files = extractor.font_collection_files
30
37
  builder.license_text = extractor.license_text
31
- builder.formula
32
38
  end
33
39
 
34
40
  def extractor
@@ -48,10 +54,10 @@ module Fontist
48
54
  Fontist::Utils::Downloader.download(url, progress_bar: true).path
49
55
  end
50
56
 
51
- def save(hash)
52
- filename = Import.name_to_filename(hash[:name])
57
+ def save(builder)
58
+ filename = Import.name_to_filename(builder.name)
53
59
  path = @options[:formula_dir] ? File.join(@options[:formula_dir], filename) : filename
54
- yaml = YAML.dump(Helpers::HashHelper.stringify_keys(hash))
60
+ yaml = YAML.dump(Helpers::HashHelper.stringify_keys(builder.formula))
55
61
  File.write(path, yaml)
56
62
  path
57
63
  end
@@ -9,11 +9,13 @@ module Fontist
9
9
  FONT_LABELS = ["OpenType font data",
10
10
  "TrueType Font data"].freeze
11
11
 
12
- COLLECTION_LABEL = "TrueType font collection data".freeze
12
+ COLLECTION_LABELS = ["OpenType font collection data",
13
+ "TrueType font collection data"].freeze
13
14
 
14
15
  FONT_EXTENSIONS = {
15
16
  "OpenType font data" => "otf",
16
17
  "TrueType Font data" => "ttf",
18
+ "OpenType font collection data" => "ttc",
17
19
  "TrueType font collection data" => "ttc",
18
20
  }.freeze
19
21
 
@@ -22,7 +24,7 @@ module Fontist
22
24
 
23
25
  if brief.start_with?(*FONT_LABELS)
24
26
  :font
25
- elsif brief.start_with?(COLLECTION_LABEL)
27
+ elsif brief.start_with?(*COLLECTION_LABELS)
26
28
  :collection
27
29
  else
28
30
  :other
@@ -4,36 +4,41 @@ require_relative "text_helper"
4
4
  module Fontist
5
5
  module Import
6
6
  class FormulaBuilder
7
- FORMULA_ATTRIBUTES = %i[name description homepage resources
7
+ FORMULA_ATTRIBUTES = %i[description homepage resources
8
8
  font_collections fonts extract copyright
9
9
  license_url open_license digest command].freeze
10
10
 
11
- attr_accessor :archive,
12
- :url,
13
- :extractor,
14
- :options,
15
- :font_files,
16
- :font_collection_files,
17
- :license_text
11
+ attr_writer :archive,
12
+ :url,
13
+ :extractor,
14
+ :options,
15
+ :font_files,
16
+ :font_collection_files,
17
+ :license_text,
18
+ :homepage
18
19
 
19
20
  def initialize
20
21
  @options = {}
21
22
  end
22
23
 
23
24
  def formula
24
- FORMULA_ATTRIBUTES.map { |name| [name, send(name)] }.to_h.compact
25
+ formula_attributes.map { |name| [name, send(name)] }.to_h.compact
25
26
  end
26
27
 
27
- private
28
-
29
28
  def name
30
- return options[:name] if options[:name]
29
+ return @options[:name] if @options[:name]
31
30
 
32
31
  unique_names = both_fonts.map(&:family_name).uniq
33
32
  TextHelper.longest_common_prefix(unique_names) ||
34
33
  both_fonts.first.family_name
35
34
  end
36
35
 
36
+ private
37
+
38
+ def formula_attributes
39
+ FORMULA_ATTRIBUTES
40
+ end
41
+
37
42
  def both_fonts
38
43
  @both_fonts ||= group_fonts
39
44
  end
@@ -50,7 +55,7 @@ module Fontist
50
55
  end
51
56
 
52
57
  def homepage
53
- both_fonts.map(&:homepage).compact.first
58
+ @options[:homepage] || both_fonts.map(&:homepage).compact.first
54
59
  end
55
60
 
56
61
  def resources
@@ -68,7 +73,7 @@ module Fontist
68
73
  end
69
74
 
70
75
  def resource_options_without_sha
71
- { urls: [@url] + mirrors }
76
+ { urls: [@url] + mirrors, file_size: file_size }
72
77
  end
73
78
 
74
79
  def resource_options_with_sha
@@ -81,7 +86,7 @@ module Fontist
81
86
 
82
87
  sha = prepare_sha256(sha)
83
88
 
84
- { urls: urls, sha256: sha }
89
+ { urls: urls, sha256: sha, file_size: file_size }
85
90
  end
86
91
 
87
92
  def downloads
@@ -115,6 +120,10 @@ module Fontist
115
120
  output
116
121
  end
117
122
 
123
+ def file_size
124
+ File.size(@archive)
125
+ end
126
+
118
127
  def font_collections
119
128
  return if @font_collection_files.empty?
120
129
 
@@ -9,3 +9,4 @@
9
9
  - Andika
10
10
  - Harmattan
11
11
  - Padauk
12
+ - STIX Two Math
@@ -0,0 +1,148 @@
1
+ require "plist"
2
+ require "nokogiri"
3
+ require "fontist/import"
4
+ require_relative "recursive_extraction"
5
+ require_relative "helpers/hash_helper"
6
+ require_relative "manual_formula_builder"
7
+
8
+ module Fontist
9
+ module Import
10
+ class Macos
11
+ 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
25
+
26
+ 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)
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def fetch_fonts_list
38
+ html = Net::HTTP.get(URI.parse(@options[:fonts_link]))
39
+
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)
44
+ end
45
+
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
61
+
62
+ def assets_links(assets)
63
+ assets.map do |x|
64
+ x.values_at("__BaseURL", "__RelativePath").join
65
+ end
66
+ end
67
+
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))
87
+ Fontist.ui.success("Formula has been successfully created: #{path}")
88
+
89
+ path
90
+ end
91
+
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
+ 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])
124
+ end
125
+
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
131
+ end
132
+
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
139
+ end
140
+
141
+ def formula_dir
142
+ @formula_dir ||= Fontist.formulas_path.join("macos").tap do |path|
143
+ FileUtils.mkdir_p(path) unless File.exist?(path)
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,24 @@
1
+ require_relative "formula_builder"
2
+
3
+ module Fontist
4
+ module Import
5
+ class ManualFormulaBuilder < FormulaBuilder
6
+ attr_accessor :description,
7
+ :platforms,
8
+ :instructions
9
+
10
+ private
11
+
12
+ def formula_attributes
13
+ @formula_attributes ||= super.dup.tap do |attrs|
14
+ attrs.delete(:resources)
15
+ attrs.delete(:open_license)
16
+ attrs.delete(:license_url)
17
+ attrs.delete(:copyright)
18
+
19
+ attrs.insert(attrs.index(:homepage) + 1, :platforms, :instructions)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -1,3 +1,5 @@
1
+ require_relative "otf/font_file"
2
+ require_relative "files/collection_file"
1
3
  require_relative "files/font_detector"
2
4
 
3
5
  module Fontist
@@ -0,0 +1,19 @@
1
+ module Fontist
2
+ class ImportCLI < Thor
3
+ desc "macos", "Create formula for on-demand macOS fonts"
4
+ option :name, desc: "Example: Big Sur", required: true
5
+ option :fonts_link,
6
+ desc: "A link to a list of available fonts in a current OS",
7
+ required: true
8
+ option :formulas_path, type: :string, desc: "Path to formulas"
9
+ def macos
10
+ if options[:formulas_path]
11
+ Fontist.formulas_path = Pathname.new(options[:formulas_path])
12
+ end
13
+
14
+ require_relative "import/macos"
15
+ Import::Macos.new(options).call
16
+ CLI::STATUS_SUCCESS
17
+ end
18
+ end
19
+ end
@@ -9,7 +9,10 @@ module Fontist
9
9
 
10
10
  def add_formula(formula)
11
11
  formula.fonts.each do |font|
12
- add_index_formula(font.name, formula.to_index_formula)
12
+ font.styles.each do |style|
13
+ font_name = style.default_family_name || font.name
14
+ add_index_formula(font_name, formula.to_index_formula)
15
+ end
13
16
  end
14
17
  end
15
18
 
@@ -0,0 +1,39 @@
1
+ module Fontist
2
+ class StyleVersion
3
+ def initialize(text)
4
+ @text = text
5
+ end
6
+
7
+ def value
8
+ @value ||= numbers || default_value
9
+ end
10
+
11
+ def numbers
12
+ string_version&.split(".")&.map(&:strip)
13
+ end
14
+
15
+ def string_version
16
+ @text&.split(";")&.first
17
+ end
18
+
19
+ def default_value
20
+ ["0"]
21
+ end
22
+
23
+ def <=>(other)
24
+ value <=> other.value
25
+ end
26
+
27
+ def ==(other)
28
+ value == other.value
29
+ end
30
+
31
+ def eql?(other)
32
+ value.eql?(other.value)
33
+ end
34
+
35
+ def hash
36
+ value.hash
37
+ end
38
+ end
39
+ end
@@ -14,6 +14,7 @@ system:
14
14
  - /System/Library/Fonts/**/**.{ttf,ttc}
15
15
  - /Users/{username}/Library/Fonts/**.{ttf,ttc}
16
16
  - /Applications/Microsoft**/Contents/Resources/**/**.{ttf,ttc}
17
+ - /System/Library/AssetsV2/com_apple_MobileAsset_Font6/**/**.{ttf,ttc}
17
18
 
18
19
  unix:
19
20
  paths:
@@ -1,9 +1,7 @@
1
1
  module Fontist
2
2
  class Update
3
- VERSION = "v2".freeze
4
-
5
3
  def self.call
6
- new(VERSION).call
4
+ new(Fontist.formulas_version).call
7
5
  end
8
6
 
9
7
  def initialize(branch = "main")
@@ -30,7 +28,14 @@ module Fontist
30
28
  depth: 1)
31
29
  end
32
30
 
33
- git = Git.open(Fontist.formulas_repo_path)
31
+ git = if Dir.exist?(Fontist.formulas_repo_path.join(".git"))
32
+ Git.open(Fontist.formulas_repo_path)
33
+ else
34
+ Git.init(Fontist.formulas_repo_path.to_s).tap do |g|
35
+ g.add_remote("origin", Fontist.formulas_repo_url)
36
+ end
37
+ end
38
+
34
39
  return git.pull("origin", @branch) if git.current_branch == @branch
35
40
 
36
41
  git.config("remote.origin.fetch",
@@ -24,7 +24,7 @@ module Fontist
24
24
  download_file
25
25
  end
26
26
 
27
- raise_if_tampered(file)
27
+ check_tampered(file)
28
28
 
29
29
  file
30
30
  end
@@ -33,15 +33,12 @@ module Fontist
33
33
 
34
34
  attr_reader :file, :sha, :file_size
35
35
 
36
- def raise_if_tampered(file)
36
+ def check_tampered(file)
37
37
  file_checksum = Digest::SHA256.file(file).to_s
38
38
  if !sha.empty? && !sha.include?(file_checksum)
39
- raise(
40
- Fontist::Errors::TamperedFileError.new(
41
- "The downloaded file from #{@file} doesn't " \
42
- "match with the expected sha256 checksum (#{file_checksum})!\n" \
43
- "Beginning of content: #{File.read(file, 3000)}",
44
- ),
39
+ Fontist.ui.error(
40
+ "SHA256 checksum mismatch for #{url}: #{file_checksum}, " \
41
+ "should be #{sha.join(', or ')}.",
45
42
  )
46
43
  end
47
44
  end
@@ -1,3 +1,5 @@
1
+ require "sys/uname"
2
+
1
3
  module Fontist
2
4
  module Utils
3
5
  module System
@@ -18,6 +20,14 @@ module Fontist
18
20
  end
19
21
  end
20
22
  end
23
+
24
+ def self.user_os_with_version
25
+ "#{user_os}-#{Sys::Uname.release}"
26
+ end
27
+
28
+ def self.match?(platform)
29
+ user_os_with_version.start_with?(platform)
30
+ end
21
31
  end
22
32
  end
23
33
  end
@@ -1,3 +1,3 @@
1
1
  module Fontist
2
- VERSION = "1.11.6".freeze
2
+ VERSION = "1.13.1".freeze
3
3
  end
data/lib/fontist.rb CHANGED
@@ -44,7 +44,11 @@ module Fontist
44
44
  end
45
45
 
46
46
  def self.fontist_version_path
47
- Fontist.fontist_path.join("versions", Update::VERSION)
47
+ Fontist.fontist_path.join("versions", formulas_version)
48
+ end
49
+
50
+ def self.formulas_version
51
+ "v3"
48
52
  end
49
53
 
50
54
  def self.formulas_repo_url
@@ -103,6 +107,10 @@ module Fontist
103
107
  Fontist.fontist_version_path
104
108
  end
105
109
 
110
+ def self.formula_size_limit_in_megabytes
111
+ 300
112
+ end
113
+
106
114
  def self.preferred_family?
107
115
  !!@preferred_family
108
116
  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.11.6
4
+ version: 1.13.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-09-28 00:00:00.000000000 Z
11
+ date: 2022-01-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: down
@@ -38,6 +38,34 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0.1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: nokogiri
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: sys-uname
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.2'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.2'
41
69
  - !ruby/object:Gem::Dependency
42
70
  name: thor
43
71
  requirement: !ruby/object:Gem::Requirement
@@ -80,6 +108,20 @@ dependencies:
80
108
  - - "~>"
81
109
  - !ruby/object:Gem::Version
82
110
  version: '1.6'
111
+ - !ruby/object:Gem::Dependency
112
+ name: plist
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '3.0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '3.0'
83
125
  - !ruby/object:Gem::Dependency
84
126
  name: excavate
85
127
  requirement: !ruby/object:Gem::Requirement
@@ -136,20 +178,6 @@ dependencies:
136
178
  - - ">="
137
179
  - !ruby/object:Gem::Version
138
180
  version: '0'
139
- - !ruby/object:Gem::Dependency
140
- name: nokogiri
141
- requirement: !ruby/object:Gem::Requirement
142
- requirements:
143
- - - "~>"
144
- - !ruby/object:Gem::Version
145
- version: '1.0'
146
- type: :development
147
- prerelease: false
148
- version_requirements: !ruby/object:Gem::Requirement
149
- requirements:
150
- - - "~>"
151
- - !ruby/object:Gem::Version
152
- version: '1.0'
153
181
  - !ruby/object:Gem::Dependency
154
182
  name: rake
155
183
  requirement: !ruby/object:Gem::Requirement
@@ -276,6 +304,7 @@ files:
276
304
  - lib/fontist/font_installer.rb
277
305
  - lib/fontist/font_path.rb
278
306
  - lib/fontist/formula.rb
307
+ - lib/fontist/formula_picker.rb
279
308
  - lib/fontist/google_cli.rb
280
309
  - lib/fontist/helpers.rb
281
310
  - lib/fontist/import.rb
@@ -293,6 +322,8 @@ files:
293
322
  - lib/fontist/import/google_import.rb
294
323
  - lib/fontist/import/helpers/hash_helper.rb
295
324
  - lib/fontist/import/helpers/system_helper.rb
325
+ - lib/fontist/import/macos.rb
326
+ - lib/fontist/import/manual_formula_builder.rb
296
327
  - lib/fontist/import/otf/font_file.rb
297
328
  - lib/fontist/import/otf_parser.rb
298
329
  - lib/fontist/import/otf_style.rb
@@ -303,6 +334,7 @@ files:
303
334
  - lib/fontist/import/sil_import.rb
304
335
  - lib/fontist/import/template_helper.rb
305
336
  - lib/fontist/import/text_helper.rb
337
+ - lib/fontist/import_cli.rb
306
338
  - lib/fontist/index.rb
307
339
  - lib/fontist/indexes/base_index.rb
308
340
  - lib/fontist/indexes/default_family_font_index.rb
@@ -315,6 +347,7 @@ files:
315
347
  - lib/fontist/manifest/locations.rb
316
348
  - lib/fontist/repo.rb
317
349
  - lib/fontist/repo_cli.rb
350
+ - lib/fontist/style_version.rb
318
351
  - lib/fontist/system.yml
319
352
  - lib/fontist/system_font.rb
320
353
  - lib/fontist/system_index.rb