fontist 0.1.0 → 1.1.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.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/macosx.yml +30 -0
  3. data/.github/workflows/ubuntu.yml +2 -2
  4. data/.github/workflows/windows.yml +32 -0
  5. data/.gitignore +4 -0
  6. data/README.md +97 -1
  7. data/bin/console +2 -5
  8. data/fontist.gemspec +5 -0
  9. data/lib/fontist.rb +44 -2
  10. data/lib/fontist/errors.rb +9 -0
  11. data/lib/fontist/font.rb +78 -0
  12. data/lib/fontist/font_formula.rb +123 -0
  13. data/lib/fontist/formula.rb +90 -0
  14. data/lib/fontist/formulas.rb +15 -0
  15. data/lib/fontist/formulas/andale_font.rb +79 -0
  16. data/lib/fontist/formulas/arial_black_font.rb +78 -0
  17. data/lib/fontist/formulas/cleartype_fonts.rb +226 -0
  18. data/lib/fontist/formulas/comic_font.rb +77 -0
  19. data/lib/fontist/formulas/courier_font.rb +80 -0
  20. data/lib/fontist/formulas/euphemia_font.rb +85 -0
  21. data/lib/fontist/formulas/georgia_font.rb +79 -0
  22. data/lib/fontist/formulas/impact_font.rb +77 -0
  23. data/lib/fontist/formulas/montserrat_font.rb +132 -0
  24. data/lib/fontist/formulas/ms_truetype_fonts.rb +124 -0
  25. data/lib/fontist/formulas/open_sans_fonts.rb +263 -0
  26. data/lib/fontist/formulas/overpass_font.rb +73 -0
  27. data/lib/fontist/formulas/source_fonts.rb +109 -0
  28. data/lib/fontist/formulas/stix_fonts.rb +108 -0
  29. data/lib/fontist/formulas/tahoma_font.rb +147 -0
  30. data/lib/fontist/formulas/webding_font.rb +77 -0
  31. data/lib/fontist/registry.rb +42 -0
  32. data/lib/fontist/system.yml +17 -0
  33. data/lib/fontist/system_font.rb +72 -0
  34. data/lib/fontist/utils.rb +9 -0
  35. data/lib/fontist/utils/downloader.rb +72 -0
  36. data/lib/fontist/utils/dsl.rb +77 -0
  37. data/lib/fontist/utils/exe_extractor.rb +72 -0
  38. data/lib/fontist/utils/zip_extractor.rb +38 -0
  39. data/lib/fontist/version.rb +1 -1
  40. data/spec/fontist/font_formula_spec.rb +67 -0
  41. data/spec/fontist/font_spec.rb +87 -0
  42. data/spec/fontist/formula_spec.rb +67 -0
  43. data/spec/fontist/formulas/andale_font_spec.rb +29 -0
  44. data/spec/fontist/formulas/arial_black_font_spec.rb +29 -0
  45. data/spec/fontist/formulas/cleartype_fonts_spec.rb +38 -0
  46. data/spec/fontist/formulas/comic_font_spec.rb +29 -0
  47. data/spec/fontist/formulas/courier_font_spec.rb +29 -0
  48. data/spec/fontist/formulas/euphemia_font_spec.rb +29 -0
  49. data/spec/fontist/formulas/georgia_font_spec.rb +29 -0
  50. data/spec/fontist/formulas/impact_font_spec.rb +29 -0
  51. data/spec/fontist/formulas/montserrat_font_spec.rb +29 -0
  52. data/spec/fontist/formulas/ms_truetype_fonts_spec.rb +29 -0
  53. data/spec/fontist/formulas/open_sans_fonts_spec.rb +29 -0
  54. data/spec/fontist/formulas/overpass_font_spec.rb +29 -0
  55. data/spec/fontist/formulas/source_fonts_spec.rb +31 -0
  56. data/spec/fontist/formulas/stix_fonts_spec.rb +29 -0
  57. data/spec/fontist/formulas/tahoma_font_spec.rb +29 -0
  58. data/spec/fontist/formulas/webding_font_spec.rb +29 -0
  59. data/spec/fontist/registry_spec.rb +47 -0
  60. data/spec/fontist/system_font_spec.rb +44 -0
  61. data/spec/fontist/utils/downloader_spec.rb +35 -0
  62. data/spec/spec_helper.rb +8 -0
  63. data/spec/support/fontist_helper.rb +10 -0
  64. metadata +113 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b6f803c9ce9bd7012252efe69be7ffe684c57c3213d5c995d87e311024b5adc2
4
- data.tar.gz: c15139f58b45512e4a07cd3f62a6b51cee37e46f79d0418ee17a027d4851ff34
3
+ metadata.gz: ec6fb2284e060c8f43ac62c16a9777d25d20886ef2ff687eecdfb963980bb350
4
+ data.tar.gz: ddcba3ee0f0a7c75f23532d7809c7c40492583ba032b4ebbc204d0730f6af9a4
5
5
  SHA512:
6
- metadata.gz: 98a1812e2f840eae8f74bce309af758da25e751532ee1184054437bc5f91a3cedf58f5268c522a3eef149364b130250b9c4881ee405ba3666a5cc4f399f1a7fe
7
- data.tar.gz: 0357ecd0887b2f7d112ac5082724edff9ada86fafa2f013c8fff00dcd23516b9fc5212c193a4a59280e01c384e904da6400c83780c8c29797177c40c13ea269a
6
+ metadata.gz: 7bfc0b3cb5597ceca0474c95d47a26e993ccf91773b4a17b10f08c84ac2ec4dfed40d3a271b309c6b2f7c77cd14dca5978b88a274c7aba3ba3ee95b25afcea30
7
+ data.tar.gz: af007b2fda60f2f53bf2be5c107bf27ec423b9759f62c6827bdecc50ed62bf56a4f4f0969ec9d74f91631f92cad75c0564182424ef2b5754ead6c9335ae87ac1
@@ -0,0 +1,30 @@
1
+ name: macos
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - master
7
+
8
+ pull_request:
9
+ branches:
10
+ - master
11
+
12
+ jobs:
13
+ build:
14
+ runs-on: macos-latest
15
+
16
+ steps:
17
+ - uses: actions/checkout@v2
18
+
19
+ - uses: actions/setup-ruby@v1
20
+ with:
21
+ ruby-version: 2.6
22
+
23
+ - name: Install bundler
24
+ run: gem install bundler
25
+
26
+ - name: Setup
27
+ run: bin/setup
28
+
29
+ - name: Run tests
30
+ run: TEST_ENV=CI bin/rspec
@@ -18,7 +18,7 @@ jobs:
18
18
 
19
19
  - uses: actions/setup-ruby@v1
20
20
  with:
21
- ruby-version: 2.6.5
21
+ ruby-version: 2.6
22
22
 
23
23
  - name: Install bundler
24
24
  run: gem install bundler
@@ -27,4 +27,4 @@ jobs:
27
27
  run: bin/setup
28
28
 
29
29
  - name: Run tests
30
- run: bin/rspec
30
+ run: TEST_ENV=CI bin/rspec
@@ -0,0 +1,32 @@
1
+ name: windows
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - master
7
+
8
+ pull_request:
9
+ branches:
10
+ - master
11
+
12
+ jobs:
13
+ build:
14
+ runs-on: windows-latest
15
+
16
+ steps:
17
+ - uses: actions/checkout@v2
18
+
19
+ - uses: actions/setup-ruby@v1
20
+ with:
21
+ ruby-version: 2.6
22
+ architecture: "x64"
23
+
24
+ - name: Setup
25
+ shell: pwsh
26
+ run: |
27
+ gem install bundler
28
+ bundle config --local path vendor/bundle
29
+ bundle install --jobs 4 --retry 3
30
+
31
+ - name: Run tests
32
+ run: bundle exec rspec --tag ~skip_in_windows
data/.gitignore CHANGED
@@ -8,5 +8,9 @@
8
8
  /tmp/
9
9
  Gemfile.lock
10
10
 
11
+ # fonts
12
+ /spec/fixtures/fonts/*
13
+ /spec/fixtures/fonts/DejaVuSerif.ttf
14
+
11
15
  # rspec failure tracking
12
16
  .rspec_status
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Fontist
2
2
 
3
+ ![windows](https://github.com/fontist/fontist/workflows/windows/badge.svg)
4
+ ![macos](https://github.com/fontist/fontist/workflows/macos/badge.svg)
3
5
  ![ubuntu](https://github.com/fontist/fontist/workflows/ubuntu/badge.svg)
4
6
 
5
7
  A simple library to find and download fonts for Windows, Linux and Mac.
@@ -26,7 +28,101 @@ gem install fontist
26
28
 
27
29
  ## Usage
28
30
 
29
- TODO: Coming soon
31
+ ### Font
32
+
33
+ The `Fontist::Font` is your go to place to deal with any font using fontist. This
34
+ interface will allow you to find a font or install a font. Lets start with how
35
+ can we find a font in your system.
36
+
37
+ #### Finding a font
38
+
39
+ The `Fontist::Fontist.find` interface can be used a find a font in your system.
40
+ It will look into the operating system specific font directories, and also the
41
+ fontist specific `~/.fontist` directory.
42
+
43
+ ```ruby
44
+ Fontist::Font.find(name)
45
+ ```
46
+
47
+ If fontist find a font then it will return the paths, but if not found then it
48
+ will could raise an unsupported font error or maybe an installation instruction
49
+ for that specific font.
50
+
51
+ #### Install a font
52
+
53
+ The `Fontist::Font.install` interface can be used to install any supported font.
54
+ This interface first checks if you already have that font installed or not and
55
+ if you do then it will return the paths.
56
+
57
+ If you don't but supported by fontist, then it will download the font and copy
58
+ it to `~/.fontist` directory and also return the paths.
59
+
60
+ ```ruby
61
+ Fontist::Font.install(name, confirmation: "no")
62
+ ```
63
+
64
+ If there are some issue with the provided font, like not supported or some other
65
+ issue then it will raise those errors.
66
+
67
+ #### List all fonts
68
+
69
+ The `Fontist::Font` interface exposes an interface to list all supported fonts,
70
+ this might be useful if want to know the name of the font or the available
71
+ styles. You can do that by using:
72
+
73
+ ```ruby
74
+ Fontist::Font.all
75
+ ```
76
+
77
+ The return values are ` OpenStruct` object, so you can easily do any other
78
+ operation you would do in any ruby object.
79
+
80
+ ### Formula
81
+
82
+ The `fontist` gem internally usages the `Fontist::Formula` interface to find a
83
+ registered formula or fonts supported by any formula. Unless, you need to do
84
+ anything with that you shouldn't need to work with this interface directly. But
85
+ if you do then these are the public interface it offers.
86
+
87
+ #### Find a formula
88
+
89
+ The `Fontist::Formula.find` interface allows you to find any of the registered
90
+ formula. This interface takes a font name as an argument and it looks through
91
+ each of the registered formula that offers this font installation. Usages:
92
+
93
+ ```ruby
94
+ Fontist::Formula.find("Calibri")
95
+ ```
96
+
97
+ The above method will find which formula offers this font and then it will
98
+ return a installable formula that can be used to check licences or install that
99
+ fonts in your system.
100
+
101
+ #### Find formula fonts
102
+
103
+ Normally, each font name can be associated with multiple styles or collection, for
104
+ example the `Calibri` font might contains a `regular`, `bola` or `italic` styles
105
+ fonts and if you want a interface that can return the complete list then this is
106
+ your friend. You can use it as following:
107
+
108
+ ```ruby
109
+ Fontist::Formula.find_fonts("Calibri")
110
+ ```
111
+
112
+
113
+ #### List all formulas
114
+
115
+ The `Fontist::Formula` interface exposes an interface to list all registered
116
+ font formula. This might be useful if want to know the name of the formula or
117
+ what type fonts can be installed using that formula. Usages:
118
+
119
+ ```ruby
120
+ Fontist::Formula.all
121
+ ```
122
+
123
+ The return values are ` OpenStruct` object, so you can easily do any other
124
+ operation you would do in any ruby object.
125
+
30
126
 
31
127
  ## Development
32
128
 
@@ -7,8 +7,5 @@ require "fontist"
7
7
  # with your gem easier. You can also use a different console, if you like.
8
8
 
9
9
  # (If you use this, don't forget to add pry to your Gemfile!)
10
- # require "pry"
11
- # Pry.start
12
-
13
- require "irb"
14
- IRB.start(__FILE__)
10
+ require "pry"
11
+ Pry.start
@@ -21,6 +21,11 @@ Gem::Specification.new do |spec|
21
21
  spec.files = `git ls-files`.split("\n")
22
22
  spec.test_files = `git ls-files -- {spec}/*`.split("\n")
23
23
 
24
+ spec.add_runtime_dependency "down", "~> 5.0"
25
+ spec.add_runtime_dependency "libmspack", "~> 0.1.0"
26
+ spec.add_runtime_dependency "rubyzip", "~> 2.3.0"
27
+
28
+ spec.add_development_dependency "pry"
24
29
  spec.add_development_dependency "bundler", "~> 2.0"
25
30
  spec.add_development_dependency "rake", "~> 12.3.3"
26
31
  spec.add_development_dependency "rspec", "~> 3.0"
@@ -1,6 +1,48 @@
1
+ require "down"
2
+ require "digest"
3
+ require "json"
4
+ require "yaml"
5
+ require "singleton"
6
+
7
+ require "fontist/errors"
1
8
  require "fontist/version"
2
9
 
10
+ require "fontist/font"
11
+ require "fontist/registry"
12
+ require "fontist/formulas"
13
+ require "fontist/formula"
14
+ require "fontist/system_font"
15
+
3
16
  module Fontist
4
- class Error < StandardError; end
5
- # Your code goes here...
17
+ def self.lib_path
18
+ Fontist.root_path.join("lib")
19
+ end
20
+
21
+ def self.root_path
22
+ Pathname.new(File.dirname(__dir__))
23
+ end
24
+
25
+ def self.fontist_path
26
+ Pathname.new(Dir.home).join(".fontist")
27
+ end
28
+
29
+ def self.fonts_path
30
+ Fontist.fontist_path.join("fonts")
31
+ end
32
+
33
+ def self.formulas_path
34
+ Fontist.lib_path.join("fontist", "formulas")
35
+ end
6
36
  end
37
+
38
+ # Loading formulas
39
+ #
40
+ # The formula loading behavior is dynamic, so what we are actualy
41
+ # doing here is looking for formulas in the `./fontist/formulas` directory
42
+ # then require thos as we go.
43
+ #
44
+ # There is a caviat, since the `Dir` method depends on absoulate path
45
+ # so moving this loading up or somewhere else might not always ensure
46
+ # the fontist related path helpers.
47
+ #
48
+ Dir[Fontist.formulas_path.join("**.rb").to_s].sort.each { |file| require file }
@@ -0,0 +1,9 @@
1
+ module Fontist
2
+ module Errors
3
+ class LicensingError < StandardError; end
4
+ class MissingFontError < StandardError; end
5
+ class NonSupportedFontError < StandardError; end
6
+ class TemparedFileError < StandardError; end
7
+ class InvalidResourceError < StandardError; end
8
+ end
9
+ end
@@ -0,0 +1,78 @@
1
+ module Fontist
2
+ class Font
3
+ def initialize(options = {})
4
+ @name = options.fetch(:name, nil)
5
+ @confirmation = options.fetch(:confirmation, "no")
6
+
7
+ check_or_create_fontist_path!
8
+ end
9
+
10
+ def self.all
11
+ new.all
12
+ end
13
+
14
+ def self.find(name)
15
+ new(name: name).find
16
+ end
17
+
18
+ def self.install(name, confirmation: "no")
19
+ new(name: name, confirmation: confirmation).install
20
+ end
21
+
22
+ def find
23
+ find_system_font || downloadable_font || raise(
24
+ Fontist::Errors::NonSupportedFontError
25
+ )
26
+ end
27
+
28
+ def install
29
+ find_system_font || download_font || raise(
30
+ Fontist::Errors::NonSupportedFontError
31
+ )
32
+ end
33
+
34
+ def all
35
+ Fontist::Formula.all.to_h.map { |_name, formula| formula.fonts }.flatten
36
+ end
37
+
38
+ private
39
+
40
+ attr_reader :name, :confirmation
41
+
42
+ def find_system_font
43
+ Fontist::SystemFont.find(name)
44
+ end
45
+
46
+ def check_or_create_fontist_path!
47
+ unless Fontist.fonts_path.exist?
48
+ require "fileutils"
49
+ FileUtils.mkdir_p(Fontist.fonts_path)
50
+ end
51
+ end
52
+
53
+ def font_installer(formula)
54
+ Object.const_get(formula.installer)
55
+ end
56
+
57
+ def formula
58
+ @formula ||= Fontist::Formula.find(name)
59
+ end
60
+
61
+ def downloadable_font
62
+ if formula
63
+ raise(
64
+ Fontist::Errors::MissingFontError,
65
+ "Fonts are missing, please run " \
66
+ "Fontist::Font.install('#{name}', confirmation: 'yes') to " \
67
+ "download the font"
68
+ )
69
+ end
70
+ end
71
+
72
+ def download_font
73
+ if formula
74
+ font_installer(formula).fetch_font(name, confirmation: confirmation)
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,123 @@
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
+
8
+ attr_accessor :license, :license_url, :license_required
9
+ attr_accessor :key, :homepage, :description, :options, :temp_resource
10
+
11
+ def font_list
12
+ @font_list ||= []
13
+ end
14
+
15
+ def resources
16
+ @resources ||= {}
17
+ end
18
+
19
+ def fonts
20
+ @fonts ||= font_list.uniq
21
+ end
22
+
23
+ def extract_font_styles(options)
24
+ extract_from_file(options) ||
25
+ extract_from_collection(options) || default_font
26
+ end
27
+
28
+ def reinitialize
29
+ @downloaded = false
30
+ @matched_fonts = []
31
+ end
32
+
33
+ def self.fetch_font(name, confirmation:)
34
+ if instance.license_required && confirmation.downcase != "yes"
35
+ raise(Fontist::Errors::LicensingError)
36
+ end
37
+
38
+ instance.reinitialize
39
+ instance.install_font(name, confirmation)
40
+ end
41
+
42
+ def install_font(name, confirmation)
43
+ run_in_temp_dir { extract }
44
+ matched_fonts_uniq = matched_fonts.flatten.uniq
45
+ matched_fonts_uniq.empty? ? nil : matched_fonts_uniq
46
+ end
47
+
48
+ private
49
+
50
+ attr_reader :downloaded, :matched_fonts
51
+
52
+ def resource(name, &block)
53
+ source = resources[name]
54
+ block_given? ? yield(source) : source
55
+ end
56
+
57
+ def fonts_path
58
+ @fonts_path ||= Fontist.fonts_path
59
+ end
60
+
61
+ def default_font
62
+ [{ type: "Regular", font: temp_resource[:filename] }]
63
+ end
64
+
65
+ def run_in_temp_dir(&block)
66
+ Dir.mktmpdir(nil, Dir.tmpdir) do |dir|
67
+ @temp_dir = Pathname.new(dir)
68
+
69
+ yield
70
+ @temp_dir = nil
71
+ end
72
+ end
73
+
74
+ def extract_from_file(options)
75
+ styles = options.fetch(:match_styles_from_file, [])
76
+
77
+ unless styles.empty?
78
+ styles.map { |type, file | { type: type, font: file } }
79
+ end
80
+ end
81
+
82
+ def match_fonts(fonts_dir, font_name)
83
+ fonts = map_names_to_fonts(font_name).join("|")
84
+ font = fonts_dir.grep(/#{fonts}/i)
85
+ @matched_fonts.push(font) if font
86
+
87
+ font
88
+ end
89
+
90
+ def extract_from_collection(options)
91
+ styles = options.fetch(:extract_styles_from_collection, [])
92
+
93
+ unless styles.empty?
94
+ styles.map do |type, file|
95
+ { type: type, collection: file, font: temp_resource[:filename] }
96
+ end
97
+ end
98
+ end
99
+
100
+ def map_names_to_fonts(font_name)
101
+ fonts = Fontist::Formula.find_fonts(font_name)
102
+ fonts = fonts.map { |font| font.styles.map(&:font) }.flatten if fonts
103
+
104
+ fonts || []
105
+ end
106
+
107
+ def download_file(source)
108
+ downloaded_file = Fontist::Utils::Downloader.download(
109
+ source[:urls].sample,
110
+ sha: source[:sha256],
111
+ file_size: source[:file_size],
112
+ progress_bar: is_progress_bar_enabled
113
+ )
114
+
115
+ @downloaded = true
116
+ downloaded_file
117
+ end
118
+
119
+ def is_progress_bar_enabled
120
+ options.nil? ? false : options.fetch(:progress_bar, false)
121
+ end
122
+ end
123
+ end