fontist 1.7.3 → 1.8.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/release.yml +38 -0
  3. data/.github/workflows/rspec.yml +58 -0
  4. data/README.md +34 -4
  5. data/{bin → exe}/fontist +0 -0
  6. data/fontist.gemspec +3 -2
  7. data/lib/fontist.rb +5 -2
  8. data/lib/fontist/cli.rb +53 -38
  9. data/lib/fontist/errors.rb +14 -12
  10. data/lib/fontist/font.rb +25 -27
  11. data/lib/fontist/font_installer.rb +114 -0
  12. data/lib/fontist/fontist_font.rb +3 -49
  13. data/lib/fontist/formula.rb +101 -35
  14. data/lib/fontist/formula_paths.rb +43 -0
  15. data/lib/fontist/helpers.rb +7 -0
  16. data/lib/fontist/import/google_check.rb +1 -1
  17. data/lib/fontist/import/google_import.rb +3 -4
  18. data/lib/fontist/import/otfinfo_generate.rb +1 -1
  19. data/lib/fontist/import/recursive_extraction.rb +5 -1
  20. data/lib/fontist/index.rb +72 -0
  21. data/lib/fontist/index_formula.rb +30 -0
  22. data/lib/fontist/manifest/install.rb +4 -5
  23. data/lib/fontist/manifest/locations.rb +9 -1
  24. data/lib/fontist/system_font.rb +2 -29
  25. data/lib/fontist/system_index.rb +1 -1
  26. data/lib/fontist/utils/exe_extractor.rb +1 -1
  27. data/lib/fontist/utils/zip_extractor.rb +1 -1
  28. data/lib/fontist/version.rb +1 -1
  29. metadata +27 -19
  30. data/.github/workflows/macosx.yml +0 -33
  31. data/.github/workflows/ubuntu.yml +0 -30
  32. data/.github/workflows/windows.yml +0 -32
  33. data/bin/check_google +0 -8
  34. data/bin/console +0 -11
  35. data/bin/convert_formulas +0 -8
  36. data/bin/generate_otfinfo +0 -8
  37. data/bin/import_google +0 -8
  38. data/bin/rspec +0 -29
  39. data/bin/setup +0 -7
  40. data/lib/fontist/font_formula.rb +0 -169
  41. data/lib/fontist/formula_template.rb +0 -122
  42. data/lib/fontist/formulas.rb +0 -56
  43. data/lib/fontist/registry.rb +0 -43
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- require "bundler/setup"
5
- require "fontist"
6
- require "fontist/import/convert_formulas"
7
-
8
- Fontist::Import::ConvertFormulas.new.call
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- require "bundler/setup"
5
- require "fontist"
6
- require "fontist/import/otfinfo_generate"
7
-
8
- Fontist::Import::OtfinfoGenerate.new(ARGV[0]).call
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- require "bundler/setup"
5
- require "fontist"
6
- require "fontist/import/google_import"
7
-
8
- Fontist::Import::GoogleImport.new.call
data/bin/rspec DELETED
@@ -1,29 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- #
5
- # This file was generated by Bundler.
6
- #
7
- # The application 'rspec' is installed as part of a gem, and
8
- # this file is here to facilitate running it.
9
- #
10
-
11
- require "pathname"
12
- ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
- Pathname.new(__FILE__).realpath)
14
-
15
- bundle_binstub = File.expand_path("../bundle", __FILE__)
16
-
17
- if File.file?(bundle_binstub)
18
- if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
19
- load(bundle_binstub)
20
- else
21
- abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
- Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
- end
24
- end
25
-
26
- require "rubygems"
27
- require "bundler/setup"
28
-
29
- load Gem.bin_path("rspec-core", "rspec")
data/bin/setup DELETED
@@ -1,7 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- gem install bundler --conservative
7
- bundle check || bundle install
@@ -1,169 +0,0 @@
1
- module Fontist
2
- class FontFormula
3
- include Singleton
4
- extend Fontist::Utils::Dsl
5
- include Fontist::Utils::ZipExtractor
6
- include Fontist::Utils::ExeExtractor
7
- include Fontist::Utils::MsiExtractor
8
- include Fontist::Utils::SevenZipExtractor
9
-
10
- attr_accessor :license, :license_url, :license_required, :copyright
11
- attr_accessor :key, :homepage, :description, :options, :temp_resource
12
-
13
- def font_list
14
- @font_list ||= []
15
- end
16
-
17
- def resources
18
- @resources ||= {}
19
- end
20
-
21
- def fonts
22
- @fonts ||= font_list.uniq
23
- end
24
-
25
- def extract_font_styles(options)
26
- extract_from_file(options) ||
27
- extract_from_collection(options) || default_font
28
- end
29
-
30
- def reinitialize
31
- @downloaded = false
32
- @matched_fonts = []
33
- end
34
-
35
- def self.fetch_font(name, confirmation:)
36
- if instance.license_required && confirmation.downcase != "yes"
37
- raise(Fontist::Errors::LicensingError)
38
- end
39
-
40
- instance.reinitialize
41
- instance.install_font(name, confirmation)
42
- end
43
-
44
- def install_font(name, confirmation)
45
- run_in_temp_dir { extract }
46
- matched_fonts_uniq = matched_fonts.flatten.uniq
47
- matched_fonts_uniq.empty? ? nil : matched_fonts_uniq
48
- end
49
-
50
- private
51
-
52
- attr_reader :downloaded, :matched_fonts
53
-
54
- def resource(name, &block)
55
- source = resources[name]
56
- block_given? ? yield(source) : source
57
- end
58
-
59
- def fonts_path
60
- @fonts_path = Fontist.fonts_path
61
- end
62
-
63
- def default_font
64
- [{ type: "Regular", font: temp_resource[:filename] }]
65
- end
66
-
67
- def run_in_temp_dir(&block)
68
- Dir.mktmpdir(nil, Dir.tmpdir) do |dir|
69
- @temp_dir = Pathname.new(dir)
70
-
71
- yield
72
- @temp_dir = nil
73
- end
74
- end
75
-
76
- def extract_from_file(options)
77
- styles = options.fetch(:match_styles_from_file, [])
78
-
79
- unless styles.empty?
80
- styles.map do |attributes|
81
- Fontist::Utils::Dsl::Font.new(attributes).attributes
82
- end
83
- end
84
- end
85
-
86
- def match_fonts(fonts_paths, font_name)
87
- filenames = filenames_by_font_name(font_name)
88
- paths = search_for_filenames(fonts_paths, filenames)
89
- @matched_fonts.push(*paths)
90
-
91
- paths
92
- end
93
-
94
- def filenames_by_font_name(font_name)
95
- fonts.map do |f|
96
- if f[:name].casecmp?(font_name)
97
- f[:styles].map do |s|
98
- s[:font]
99
- end
100
- end
101
- end.flatten.compact
102
- end
103
-
104
- def search_for_filenames(paths, filenames)
105
- paths.select do |path|
106
- filenames.any? do |filename|
107
- File.basename(path) == filename
108
- end
109
- end
110
- end
111
-
112
- def extract_from_collection(options)
113
- styles = options.fetch(:extract_styles_from_collection, [])
114
-
115
- unless styles.empty?
116
- styles.map do |attributes|
117
- filenames = temp_resource.slice(:filename, :source_filename)
118
- Fontist::Utils::Dsl::CollectionFont.new(attributes.merge(filenames))
119
- .attributes
120
- end
121
- end
122
- end
123
-
124
- def download_file(source)
125
- url = source[:urls].first
126
- Fontist.ui.say(%(Downloading font "#{key}" from #{url}))
127
-
128
- downloaded_file = Fontist::Utils::Downloader.download(
129
- url,
130
- sha: source[:sha256],
131
- file_size: source[:file_size],
132
- progress_bar: is_progress_bar_enabled
133
- )
134
-
135
- @downloaded = true
136
- downloaded_file
137
- end
138
-
139
- def is_progress_bar_enabled
140
- options.nil? ? true : options.fetch(:progress_bar, true)
141
- end
142
-
143
- def font_file?(filename)
144
- source_files.include?(filename)
145
- end
146
-
147
- def source_files
148
- @source_files ||= fonts.flat_map do |font|
149
- font[:styles].map do |style|
150
- style[:source_font] || style[:font]
151
- end
152
- end
153
- end
154
-
155
- def target_filename(source_filename)
156
- target_filenames[source_filename]
157
- end
158
-
159
- def target_filenames
160
- @target_filenames ||= fonts.flat_map do |font|
161
- font[:styles].map do |style|
162
- source = style[:source_font] || style[:font]
163
- target = style[:font]
164
- [source, target]
165
- end
166
- end.to_h
167
- end
168
- end
169
- end
@@ -1,122 +0,0 @@
1
- module Fontist
2
- class FormulaTemplate
3
- def self.create_formula_class(formula)
4
- Class.new(FontFormula) do |klass|
5
- first_font = (formula.fonts || formula.font_collections.first.fonts).first
6
- cleanname = first_font.name.gsub(/ /, "")
7
- resource_name = formula.resources.to_h.keys.first
8
- font_filename = first_font.styles.first.font
9
-
10
- key formula.key&.to_sym || formula.name.gsub(/ /, "_").downcase.to_sym
11
- display_progress_bar formula.display_progress_bar if formula.display_progress_bar
12
- desc formula.description
13
- homepage formula.homepage
14
-
15
- formula.resources.to_h.each do |filename, options|
16
- resource filename do
17
- urls options.urls
18
- sha256 options.sha256
19
- end
20
- end
21
-
22
- if formula.font_collections
23
- formula.font_collections.each do |collection|
24
- provides_font_collection do
25
- filename collection.filename
26
- source_filename collection.source_filename
27
-
28
- collection.fonts.each do |font|
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
- )
43
- end
44
- end
45
- end
46
- end
47
-
48
- if formula.fonts
49
- formula.fonts.each do |font|
50
- provides_font(
51
- font.name,
52
- match_styles_from_file: font.styles.map do |style|
53
- {
54
- family_name: style.family_name,
55
- style: style.type,
56
- full_name: style.full_name,
57
- post_script_name: style.post_script_name,
58
- version: style.version,
59
- description: style.description,
60
- filename: style.font,
61
- source_filename: style.source_font,
62
- copyright: style.copyright,
63
- }
64
- end
65
- )
66
- end
67
- end
68
-
69
- klass.define_method :extract do
70
- resource = resource(resource_name)
71
-
72
- [formula.extract].flatten.each do |operation|
73
- method = "#{operation.format}_extract"
74
- resource = if operation.options
75
- send(method, resource, **operation.options.to_h)
76
- else
77
- send(method, resource)
78
- end
79
- end
80
-
81
- if formula.fonts
82
- formula.fonts.each do |font|
83
- match_fonts(resource, font.name)
84
- end
85
- end
86
-
87
- if formula.font_collections
88
- formula.font_collections.each do |collection|
89
- collection.fonts.each do |font|
90
- match_fonts(resource, font.name)
91
- end
92
- end
93
- end
94
- end
95
-
96
- klass.define_method :install do
97
- case platform
98
- when :macos
99
- install_matched_fonts "$HOME/Library/Fonts/#{cleanname}"
100
- when :linux
101
- install_matched_fonts "/usr/share/fonts/truetype/#{cleanname.downcase}"
102
- end
103
- end
104
-
105
- test do
106
- case platform
107
- when :macos
108
- assert_predicate "$HOME/Library/Fonts/#{cleanname}/#{font_filename}", :exist?
109
- when :linux
110
- assert_predicate "/usr/share/fonts/truetype/#{cleanname.downcase}/#{font_filename}", :exist?
111
- end
112
- end
113
-
114
- copyright formula.copyright
115
- license_url formula.license_url
116
-
117
- open_license formula.open_license if formula.open_license
118
- requires_license_agreement formula.requires_license_agreement if formula.requires_license_agreement
119
- end
120
- end
121
- end
122
- end
@@ -1,56 +0,0 @@
1
- require "git"
2
- require "fontist/utils"
3
- require "fontist/font_formula"
4
- require "fontist/formula_template"
5
-
6
- module Fontist
7
- module Formulas
8
- def self.register_formulas
9
- load_formulas
10
- update_registry
11
- end
12
-
13
- def self.fetch_formulas
14
- if Dir.exist?(Fontist.formulas_repo_path)
15
- Git.open(Fontist.formulas_repo_path).pull
16
- else
17
- Git.clone(Fontist.formulas_repo_url,
18
- Fontist.formulas_repo_path,
19
- depth: 1)
20
- end
21
- end
22
-
23
- def self.load_formulas
24
- Dir[Fontist.formulas_path.join("**/*.yml").to_s].sort.each do |file|
25
- create_formula_class(file)
26
- end
27
- end
28
-
29
- def self.create_formula_class(file)
30
- formula = parse_to_object(YAML.load_file(file))
31
- class_name = name_to_classname(formula.name)
32
- return if Formulas.const_defined?(class_name)
33
-
34
- klass = FormulaTemplate.create_formula_class(formula)
35
- Formulas.const_set(class_name, klass)
36
- end
37
-
38
- def self.parse_to_object(hash)
39
- JSON.parse(hash.to_json, object_class: OpenStruct)
40
- end
41
-
42
- def self.update_registry
43
- Formulas.constants.select do |constant|
44
- if Formulas.const_get(constant).is_a?(Class)
45
- klass = "Fontist::Formulas::#{constant}"
46
- Fontist::Registry.register(Object.const_get(klass))
47
- end
48
- end
49
- end
50
-
51
- def self.name_to_classname(name)
52
- cleanname = name.gsub(/ /, "").sub(/\S/, &:upcase)
53
- "#{cleanname}Font"
54
- end
55
- end
56
- end
@@ -1,43 +0,0 @@
1
- module Fontist
2
- class Registry
3
- include Singleton
4
-
5
- def initialize
6
- @formulas ||= {}
7
- end
8
-
9
- def formulas
10
- parse_to_object(@formulas)
11
- end
12
-
13
- def self.formulas
14
- instance.formulas
15
- end
16
-
17
- def self.register(formula, key = nil)
18
- key ||= formula.instance.key || formula.to_s
19
- instance.register(formula, key)
20
- end
21
-
22
- def register(formula, key)
23
- @formulas[key] = build_formula_data(formula)
24
- end
25
-
26
- private
27
-
28
- def build_formula_data(formula)
29
- {
30
- installer: formula,
31
- fonts: formula.instance.fonts,
32
- license: formula.instance.license,
33
- homepage: formula.instance.homepage ,
34
- description: formula.instance.description,
35
- license_required: formula.instance.license_required,
36
- }
37
- end
38
-
39
- def parse_to_object(data)
40
- JSON.parse(data.to_json, object_class: OpenStruct)
41
- end
42
- end
43
- end