fontist 0.4.0 → 1.0.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 (82) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/macosx.yml +1 -1
  3. data/.github/workflows/ubuntu.yml +1 -1
  4. data/.gitignore +4 -2
  5. data/README.md +87 -25
  6. data/lib/fontist.rb +28 -13
  7. data/lib/fontist/downloader.rb +11 -11
  8. data/lib/fontist/errors.rb +1 -0
  9. data/lib/fontist/font.rb +78 -0
  10. data/lib/fontist/font_formula.rb +116 -0
  11. data/lib/fontist/formula.rb +90 -0
  12. data/lib/fontist/formulas.rb +10 -5
  13. data/lib/fontist/formulas/andale_font.rb +79 -0
  14. data/lib/fontist/formulas/arial_black_font.rb +78 -0
  15. data/lib/fontist/formulas/cleartype_fonts.rb +225 -0
  16. data/lib/fontist/formulas/comic_font.rb +77 -0
  17. data/lib/fontist/formulas/courier_font.rb +67 -12
  18. data/lib/fontist/formulas/euphemia_font.rb +85 -0
  19. data/lib/fontist/formulas/georgia_font.rb +79 -0
  20. data/lib/fontist/formulas/impact_font.rb +77 -0
  21. data/lib/fontist/formulas/montserrat_font.rb +132 -0
  22. data/lib/fontist/formulas/ms_truetype_fonts.rb +124 -0
  23. data/lib/fontist/formulas/open_sans_fonts.rb +263 -0
  24. data/lib/fontist/formulas/overpass_font.rb +73 -0
  25. data/lib/fontist/formulas/source_fonts.rb +109 -0
  26. data/lib/fontist/formulas/stix_fonts.rb +108 -0
  27. data/lib/fontist/formulas/tahoma_font.rb +147 -0
  28. data/lib/fontist/formulas/webding_font.rb +77 -0
  29. data/lib/fontist/registry.rb +42 -0
  30. data/lib/fontist/{data/source.yml → system.yml} +0 -7
  31. data/lib/fontist/system_font.rb +9 -13
  32. data/lib/fontist/utils.rb +8 -0
  33. data/lib/fontist/utils/dsl.rb +73 -0
  34. data/lib/fontist/utils/exe_extractor.rb +72 -0
  35. data/lib/fontist/utils/zip_extractor.rb +38 -0
  36. data/lib/fontist/version.rb +1 -1
  37. data/spec/fontist/downloader_spec.rb +2 -1
  38. data/spec/fontist/font_formula_spec.rb +67 -0
  39. data/spec/fontist/font_spec.rb +87 -0
  40. data/spec/fontist/formula_spec.rb +67 -0
  41. data/spec/fontist/formulas/andale_font_spec.rb +29 -0
  42. data/spec/fontist/formulas/arial_black_font_spec.rb +29 -0
  43. data/spec/fontist/formulas/cleartype_fonts_spec.rb +38 -0
  44. data/spec/fontist/formulas/comic_font_spec.rb +29 -0
  45. data/spec/fontist/formulas/courier_font_spec.rb +18 -19
  46. data/spec/fontist/formulas/euphemia_font_spec.rb +29 -0
  47. data/spec/fontist/formulas/georgia_font_spec.rb +29 -0
  48. data/spec/fontist/formulas/impact_font_spec.rb +29 -0
  49. data/spec/fontist/formulas/montserrat_font_spec.rb +29 -0
  50. data/spec/fontist/formulas/ms_truetype_fonts_spec.rb +29 -0
  51. data/spec/fontist/formulas/open_sans_fonts_spec.rb +29 -0
  52. data/spec/fontist/formulas/overpass_font_spec.rb +29 -0
  53. data/spec/fontist/formulas/source_fonts_spec.rb +31 -0
  54. data/spec/fontist/formulas/stix_fonts_spec.rb +29 -0
  55. data/spec/fontist/formulas/tahoma_font_spec.rb +29 -0
  56. data/spec/fontist/formulas/webding_font_spec.rb +29 -0
  57. data/spec/fontist/registry_spec.rb +47 -0
  58. data/spec/fontist/system_font_spec.rb +6 -6
  59. data/spec/spec_helper.rb +4 -2
  60. data/spec/support/fontist_helper.rb +4 -2
  61. metadata +45 -25
  62. data/lib/fontist/data/formulas/courier.yml +0 -26
  63. data/lib/fontist/data/formulas/ms_system.yml +0 -68
  64. data/lib/fontist/data/formulas/ms_vista.yml +0 -118
  65. data/lib/fontist/data/formulas/source_font.yml +0 -163
  66. data/lib/fontist/finder.rb +0 -45
  67. data/lib/fontist/formula_finder.rb +0 -94
  68. data/lib/fontist/formulas/base.rb +0 -72
  69. data/lib/fontist/formulas/helpers/exe_extractor.rb +0 -45
  70. data/lib/fontist/formulas/helpers/zip_extractor.rb +0 -36
  71. data/lib/fontist/formulas/ms_system.rb +0 -29
  72. data/lib/fontist/formulas/ms_vista.rb +0 -42
  73. data/lib/fontist/formulas/source_font.rb +0 -25
  74. data/lib/fontist/installer.rb +0 -42
  75. data/lib/fontist/source.rb +0 -58
  76. data/spec/fontist/finder_spec.rb +0 -41
  77. data/spec/fontist/formula_finder_spec.rb +0 -54
  78. data/spec/fontist/formulas/ms_system_spec.rb +0 -31
  79. data/spec/fontist/formulas/ms_vista_spec.rb +0 -27
  80. data/spec/fontist/formulas/source_font_spec.rb +0 -18
  81. data/spec/fontist/installer_spec.rb +0 -48
  82. data/spec/fontist/source_spec.rb +0 -24
@@ -14,10 +14,3 @@ system:
14
14
  unix:
15
15
  paths:
16
16
  - /usr/share/fonts/**/**.{ttf,ttc}
17
-
18
- remote:
19
- formulas:
20
- - ./formulas/ms_vista.yml
21
- - ./formulas/ms_system.yml
22
- - ./formulas/source_font.yml
23
- - ./formulas/courier.yml
@@ -3,8 +3,6 @@ module Fontist
3
3
  def initialize(font:, sources: nil)
4
4
  @font = font
5
5
  @user_sources = sources || []
6
-
7
- check_or_create_fontist_path
8
6
  end
9
7
 
10
8
  def self.find(font, sources: [])
@@ -22,13 +20,6 @@ module Fontist
22
20
 
23
21
  attr_reader :font, :user_sources
24
22
 
25
- def check_or_create_fontist_path
26
- unless fontist_fonts_path.exist?
27
- require "fileutils"
28
- FileUtils.mkdir_p(fontist_fonts_path)
29
- end
30
- end
31
-
32
23
  def font_paths
33
24
  Dir.glob((
34
25
  user_sources +
@@ -46,9 +37,6 @@ module Fontist
46
37
  @fontist_fonts_path ||= Fontist.fonts_path
47
38
  end
48
39
 
49
- def default_sources
50
- @default_sources ||= Source.all.system[user_os.to_s]
51
- end
52
40
 
53
41
  def user_os
54
42
  @user_os ||= (
@@ -69,8 +57,16 @@ module Fontist
69
57
  end
70
58
 
71
59
  def map_name_to_valid_font_names
72
- fonts = FormulaFinder.find_fonts(font)
60
+ fonts = Formula.find_fonts(font)
73
61
  fonts.map { |font| font.styles.map(&:font) }.flatten if fonts
74
62
  end
63
+
64
+ def system_path_file
65
+ File.open(Fontist.lib_path.join("fontist", "system.yml"))
66
+ end
67
+
68
+ def default_sources
69
+ @default_sources ||= YAML.load(system_path_file)["system"][user_os.to_s]
70
+ end
75
71
  end
76
72
  end
@@ -0,0 +1,8 @@
1
+ require "fontist/utils/dsl"
2
+ require "fontist/utils/zip_extractor"
3
+ require "fontist/utils/exe_extractor"
4
+
5
+ module Fontist
6
+ module Utils
7
+ end
8
+ end
@@ -0,0 +1,73 @@
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 provides_font(font, options = {})
51
+ font_styles = instance.extract_font_styles(options)
52
+ instance.font_list.push(name: font, styles: font_styles)
53
+ end
54
+
55
+ def test
56
+ end
57
+
58
+ def requires_license_agreement(license)
59
+ instance.license = license
60
+ instance.license_required = true
61
+ end
62
+
63
+ def open_license(license)
64
+ instance.license = license
65
+ instance.license_required = false
66
+ end
67
+
68
+ def license_url(url)
69
+ instance.license_url = url
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,72 @@
1
+ module Fontist
2
+ module Utils
3
+ module ExeExtractor
4
+ def cab_extract(exe_file, download: true, font_ext: /.tt|.ttc/i)
5
+ download = @downloaded === true ? false : download
6
+
7
+ exe_file = download_file(exe_file).path if download
8
+ cab_file = decompressor.search(exe_file)
9
+ cabbed_fonts = grep_fonts(cab_file.files, font_ext) || []
10
+ fonts_paths = extract_cabbed_fonts_to_assets(cabbed_fonts)
11
+
12
+ yield(fonts_paths) if block_given?
13
+ end
14
+
15
+ def exe_extract(source)
16
+ cab_file = decompressor.search(download_file(source).path)
17
+ yield(build_cab_file_hash(cab_file.files)) if block_given?
18
+ end
19
+
20
+ private
21
+
22
+ def decompressor
23
+ @decompressor ||= (
24
+ require "libmspack"
25
+ LibMsPack::CabDecompressor.new
26
+ )
27
+ end
28
+
29
+ def grep_fonts(file, font_ext)
30
+ Array.new.tap do |fonts|
31
+ while file
32
+ fonts.push(file) if file.filename.match(font_ext)
33
+ file = file.next
34
+ end
35
+ end
36
+ end
37
+
38
+ def extract_cabbed_fonts_to_assets(cabbed_fonts)
39
+ Array.new.tap do |fonts|
40
+ cabbed_fonts.each do |font|
41
+ font_path = fonts_path.join(font.filename).to_s
42
+ decompressor.extract(font, font_path)
43
+
44
+ fonts.push(font_path)
45
+ end
46
+ end
47
+ end
48
+
49
+ def build_cab_file_hash(file)
50
+ Hash.new.tap do |cab_files|
51
+ while file
52
+ filename = file.filename
53
+ if filename.include?("cab")
54
+ file_path = temp_dir.join(filename).to_s
55
+
56
+ decompressor.extract(file, file_path)
57
+ cab_files[filename.to_s] = file_path
58
+ end
59
+
60
+ file = file.next
61
+ end
62
+ end
63
+ end
64
+
65
+ def temp_dir
66
+ @temp_dir ||= raise(
67
+ NotImplementedError.new("You must implement this method"),
68
+ )
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,38 @@
1
+ require "zip"
2
+ require "pathname"
3
+
4
+ module Fontist
5
+ module Utils
6
+ module ZipExtractor
7
+ def zip_extract(resource, download: true, fonts_sub_dir: "")
8
+ zip_file = download_file(resource) if download
9
+ zip_file ||= resource.urls.first
10
+
11
+ fonts_paths = unzip_fonts(zip_file, fonts_sub_dir)
12
+ block_given? ? yield(fonts_paths) : fonts_paths
13
+ end
14
+
15
+ alias_method :unzip, :zip_extract
16
+
17
+ private
18
+
19
+ def unzip_fonts(file, fonts_sub_dir = "")
20
+ Zip.on_exists_proc = true
21
+ Array.new.tap do |fonts|
22
+
23
+ Zip::File.open(file) do |zip_file|
24
+ zip_file.glob("#{fonts_sub_dir}*.{ttf,ttc,otf}").each do |entry|
25
+ if entry.name
26
+ filename = Pathname.new(entry.name).basename
27
+ font_path = fonts_path.join(filename.to_s)
28
+ fonts.push(font_path.to_s)
29
+
30
+ entry.extract(font_path)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -1,3 +1,3 @@
1
1
  module Fontist
2
- VERSION = "0.4.0".freeze
2
+ VERSION = "1.0.0".freeze
3
3
  end
@@ -1,6 +1,7 @@
1
1
  require "spec_helper"
2
+
2
3
  RSpec.describe Fontist::Downloader do
3
- describe ".download", file_download: true do
4
+ describe ".download" do
4
5
  it "return the valid downloaded file" do
5
6
  tempfile = Fontist::Downloader.download(
6
7
  sample_file[:file],
@@ -0,0 +1,67 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "Fontist::Formulas::DemoFormula" do
4
+ describe "initialization" do
5
+ it "registers formula resources through the DSL" do
6
+ formula = Fontist::Formulas::DemoFormula.instance
7
+ resource = formula.resources["demo-formula"]
8
+ demo_font = formula.font_list.first
9
+
10
+ expect(formula.key).to eq(:demo_formula)
11
+ expect(formula.license_required).to be_truthy
12
+ expect(formula.description).to eq("Demo font formula")
13
+ expect(formula.license).to eq("Vendor specific font licences")
14
+ expect(formula.homepage).to eq("https://github.com/fontist/fontist")
15
+
16
+ expect(resource[:file_size]).to eq("1234567890")
17
+ expect(resource[:urls].first).to eq("https://github.com/fontist/fontist")
18
+ expect(resource[:sha256]).to eq("594e0f42e6581add4dead70c1dfb9")
19
+
20
+ expect(demo_font[:styles].count).to eq(2)
21
+ expect(demo_font[:name]).to eq("Demo font")
22
+ expect(demo_font[:styles].first[:font]).to eq("demo-font.ttf")
23
+ end
24
+ end
25
+
26
+ describe "method invokation" do
27
+ it "invokes the correct method for installation" do
28
+ expect {
29
+ Fontist::Formulas::DemoFormula.fetch_font("Demo font", confirmation: "yes")
30
+ }.not_to raise_error
31
+ end
32
+ end
33
+
34
+ module Fontist
35
+ module Formulas
36
+ class DemoFormula < FontFormula
37
+ key :demo_formula
38
+ desc "Demo font formula"
39
+ homepage "https://github.com/fontist/fontist"
40
+ requires_license_agreement "Vendor specific font licences"
41
+
42
+ resource "demo-formula" do
43
+ urls [ "https://github.com/fontist/fontist" ]
44
+ sha256 "594e0f42e6581add4dead70c1dfb9"
45
+ file_size "1234567890"
46
+ end
47
+
48
+ provides_font "Demo font", match_styles_from_file: {
49
+ "Regular" => "demo-font.ttf",
50
+ "Italic" => "demo-fonti.ttf"
51
+ }
52
+
53
+ provides_font_collection("Meiryo Bold") do |coll|
54
+ filename "demo-font.ttc"
55
+ provides_font "Demo collection", extract_styles_from_collection: {
56
+ "Regular" => "demo-col-font.ttf",
57
+ "Italic" => "demo-col-fonti.ttf"
58
+ }
59
+ end
60
+
61
+ def extract
62
+ []
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,87 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe Fontist::Font do
4
+ describe ".all" do
5
+ it "list all supported fonts" do
6
+ fonts = Fontist::Font.all
7
+
8
+ expect(fonts.count).to be > 10
9
+ expect(fonts.first.name).not_to be_nil
10
+ expect(fonts.first.styles).not_to be_nil
11
+ end
12
+ end
13
+
14
+ describe ".find" do
15
+ context "with valid font name" do
16
+ it "returns the fonts path" do
17
+ name = "DejaVuSerif.ttf"
18
+ stub_system_font_finder_to_fixture(name)
19
+ dejavu_ttf = Fontist::Font.find(name)
20
+
21
+ expect(dejavu_ttf.first).to include(name)
22
+ end
23
+ end
24
+
25
+ context "with downloadable font name" do
26
+ it "raises font missing error" do
27
+ name = "Courier"
28
+
29
+ allow(Fontist::SystemFont).to receive(:find).and_return(nil)
30
+ expect {
31
+ Fontist::Font.find(name)
32
+ }.to raise_error(Fontist::Errors::MissingFontError)
33
+ end
34
+ end
35
+
36
+ context "with invalid font name" do
37
+ it "raises font unsupported error" do
38
+ font_name = "InvalidFont.ttf"
39
+
40
+ expect {
41
+ Fontist::Font.find(font_name)
42
+ }.to raise_error(Fontist::Errors::NonSupportedFontError)
43
+ end
44
+ end
45
+ end
46
+
47
+ describe ".install" do
48
+ context "with valid font name" do
49
+ it "installs the font and return the paths" do
50
+ name = "Calibri"
51
+
52
+ stub_fontist_path_to_temp_path
53
+ font_paths = Fontist::Font.install(name, confirmation: "yes")
54
+
55
+ expect(font_paths.join("|").downcase).to include("#{name.downcase}.ttf")
56
+ end
57
+ end
58
+
59
+ context "with existing font name" do
60
+ it "returns the existing font paths" do
61
+ name = "Courier"
62
+ stub_fontist_path_to_temp_path
63
+ Fontist::Font.install(name, confirmation: "yes")
64
+
65
+ font_paths = Fontist::Font.install(name, confirmation: "yes")
66
+
67
+ expect(font_paths.count).to be > 3
68
+ expect(Fontist::Formulas::CourierFont).not_to receive(:fetch_font)
69
+ end
70
+ end
71
+
72
+ context "with unsupported fonts" do
73
+ it "raises an unsupported error" do
74
+ name = "Invalid font name"
75
+
76
+ expect {
77
+ Fontist::Font.install(name, confirmation: "yes")
78
+ }.to raise_error(Fontist::Errors::NonSupportedFontError)
79
+ end
80
+ end
81
+ end
82
+
83
+ def stub_system_font_finder_to_fixture(name)
84
+ allow(Fontist::SystemFont).to receive(:find).
85
+ and_return(["spec/fixtures/fonts/#{name}"])
86
+ end
87
+ end
@@ -0,0 +1,67 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe Fontist::Formula do
4
+ describe ".find" do
5
+ context "by font name" do
6
+ it "returns the font formulas" do
7
+ name = "Calibri"
8
+
9
+ clear_type = Fontist::Formula.find(name)
10
+
11
+ expect(clear_type.fonts.map(&:name)).to include(name)
12
+ expect(clear_type.installer).to eq("Fontist::Formulas::ClearTypeFonts")
13
+ expect(clear_type.description).to include("Microsoft ClearType Fonts")
14
+ end
15
+ end
16
+
17
+ context "by exact font" do
18
+ it "returns the font formulas" do
19
+ name = "CAMBRIAI.TTF"
20
+
21
+ clear_type = Fontist::Formula.find(name)
22
+ font_files = clear_type.fonts.map { |font| font.styles.map(&:font) }
23
+
24
+ expect(font_files.flatten).to include(name)
25
+ expect(clear_type.installer).to eq("Fontist::Formulas::ClearTypeFonts")
26
+ expect(clear_type.description).to include("Microsoft ClearType Fonts")
27
+ end
28
+ end
29
+
30
+ context "for invalid font" do
31
+ it "returns nil to the caller" do
32
+ name = "Calibri Made Up Name"
33
+ formulas = Fontist::Formula.find(name)
34
+
35
+ expect(formulas).to be_nil
36
+ end
37
+ end
38
+ end
39
+
40
+ describe ".find_fonts" do
41
+ it "returns the exact font font names" do
42
+ name = "Calibri"
43
+ font = Fontist::Formula.find_fonts(name).last
44
+
45
+ expect(font.styles.map(&:font)).to include("CALIBRI.TTF")
46
+ expect(font.styles.map(&:font)).to include("CALIBRIB.TTF")
47
+ expect(font.styles.map(&:font)).to include("CALIBRII.TTF")
48
+ end
49
+
50
+ it "returns nil if invalid name provided" do
51
+ name = "Calibri Invlaid"
52
+ fonts = Fontist::Formula.find_fonts(name)
53
+
54
+ expect(fonts).to be_nil
55
+ end
56
+ end
57
+
58
+ describe ".all" do
59
+ it "returns all registered formulas" do
60
+ formulas = Fontist::Formula.all
61
+
62
+ expect(formulas.cleartype.fonts.count).to be > 10
63
+ expect(formulas.cleartype.homepage).to eq("https://www.microsoft.com")
64
+ expect(formulas.cleartype.description).to eq("Microsoft ClearType Fonts")
65
+ end
66
+ end
67
+ end