fontist 1.7.3 → 1.8.1

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.
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