fontist 0.4.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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