fontist 0.3.0 → 1.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/macosx.yml +1 -1
- data/.github/workflows/ubuntu.yml +1 -1
- data/.gitignore +4 -2
- data/README.md +91 -5
- data/lib/fontist.rb +26 -12
- data/lib/fontist/errors.rb +3 -1
- data/lib/fontist/font.rb +78 -0
- data/lib/fontist/font_formula.rb +123 -0
- data/lib/fontist/formula.rb +90 -0
- data/lib/fontist/formulas.rb +10 -3
- data/lib/fontist/formulas/andale_font.rb +80 -0
- data/lib/fontist/formulas/arial_black_font.rb +79 -0
- data/lib/fontist/formulas/cleartype_fonts.rb +227 -0
- data/lib/fontist/formulas/comic_font.rb +78 -0
- data/lib/fontist/formulas/courier_font.rb +81 -0
- data/lib/fontist/formulas/euphemia_font.rb +85 -0
- data/lib/fontist/formulas/georgia_font.rb +80 -0
- data/lib/fontist/formulas/impact_font.rb +78 -0
- data/lib/fontist/formulas/montserrat_font.rb +132 -0
- data/lib/fontist/formulas/ms_truetype_fonts.rb +125 -0
- data/lib/fontist/formulas/open_sans_fonts.rb +263 -0
- data/lib/fontist/formulas/overpass_font.rb +73 -0
- data/lib/fontist/formulas/source_fonts.rb +109 -0
- data/lib/fontist/formulas/stix_fonts.rb +108 -0
- data/lib/fontist/formulas/tahoma_font.rb +147 -0
- data/lib/fontist/formulas/webding_font.rb +78 -0
- data/lib/fontist/registry.rb +42 -0
- data/lib/fontist/{data/source.yml → system.yml} +5 -6
- data/lib/fontist/system_font.rb +27 -11
- data/lib/fontist/utils.rb +9 -0
- data/lib/fontist/utils/downloader.rb +75 -0
- data/lib/fontist/utils/dsl.rb +77 -0
- data/lib/fontist/utils/exe_extractor.rb +72 -0
- data/lib/fontist/utils/zip_extractor.rb +38 -0
- data/lib/fontist/version.rb +1 -1
- data/spec/fontist/font_formula_spec.rb +67 -0
- data/spec/fontist/font_spec.rb +87 -0
- data/spec/fontist/formula_spec.rb +67 -0
- data/spec/fontist/formulas/andale_font_spec.rb +29 -0
- data/spec/fontist/formulas/arial_black_font_spec.rb +29 -0
- data/spec/fontist/formulas/cleartype_fonts_spec.rb +38 -0
- data/spec/fontist/formulas/comic_font_spec.rb +29 -0
- data/spec/fontist/formulas/courier_font_spec.rb +29 -0
- data/spec/fontist/formulas/euphemia_font_spec.rb +29 -0
- data/spec/fontist/formulas/georgia_font_spec.rb +29 -0
- data/spec/fontist/formulas/impact_font_spec.rb +29 -0
- data/spec/fontist/formulas/montserrat_font_spec.rb +29 -0
- data/spec/fontist/formulas/ms_truetype_fonts_spec.rb +29 -0
- data/spec/fontist/formulas/open_sans_fonts_spec.rb +29 -0
- data/spec/fontist/formulas/overpass_font_spec.rb +29 -0
- data/spec/fontist/formulas/source_fonts_spec.rb +31 -0
- data/spec/fontist/formulas/stix_fonts_spec.rb +29 -0
- data/spec/fontist/formulas/tahoma_font_spec.rb +29 -0
- data/spec/fontist/formulas/webding_font_spec.rb +29 -0
- data/spec/fontist/registry_spec.rb +47 -0
- data/spec/fontist/system_font_spec.rb +17 -1
- data/spec/fontist/{downloader_spec.rb → utils/downloader_spec.rb} +6 -5
- data/spec/spec_helper.rb +4 -2
- data/spec/support/fontist_helper.rb +4 -2
- metadata +50 -20
- data/lib/fontist/data/formulas/ms_vista.yml +0 -39
- data/lib/fontist/data/formulas/source_font.yml +0 -51
- data/lib/fontist/downloader.rb +0 -70
- data/lib/fontist/finder.rb +0 -47
- data/lib/fontist/formulas/base.rb +0 -25
- data/lib/fontist/formulas/ms_vista.rb +0 -74
- data/lib/fontist/formulas/source_font.rb +0 -48
- data/lib/fontist/installer.rb +0 -47
- data/lib/fontist/source.rb +0 -58
- data/spec/fontist/finder_spec.rb +0 -41
- data/spec/fontist/formulas/ms_vista_spec.rb +0 -27
- data/spec/fontist/formulas/source_font_spec.rb +0 -18
- data/spec/fontist/installer_spec.rb +0 -48
- data/spec/fontist/source_spec.rb +0 -24
@@ -6,16 +6,15 @@ system:
|
|
6
6
|
windows:
|
7
7
|
paths:
|
8
8
|
- C:/Windows/Fonts/**/**.{ttc,ttf}
|
9
|
+
- C:/Users/{username}/AppData/Local/Microsoft/Windows/Fonts/**/**.{ttc,ttf}
|
9
10
|
|
10
|
-
|
11
|
+
macos:
|
11
12
|
paths:
|
13
|
+
- /Library/Fonts/**/**.{ttf,ttc}
|
12
14
|
- /System/Library/Fonts/**/**.{ttf,ttc}
|
15
|
+
- /Users/{username}/Library/Fonts/**.{ttf,ttc}
|
16
|
+
- /Applications/Microsoft**/Contents/Resources/**/**.{ttf,ttc}
|
13
17
|
|
14
18
|
unix:
|
15
19
|
paths:
|
16
20
|
- /usr/share/fonts/**/**.{ttf,ttc}
|
17
|
-
|
18
|
-
remote:
|
19
|
-
formulas:
|
20
|
-
- ./formulas/ms_vista.yml
|
21
|
-
- ./formulas/source_font.yml
|
data/lib/fontist/system_font.rb
CHANGED
@@ -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: [])
|
@@ -13,6 +11,8 @@ module Fontist
|
|
13
11
|
|
14
12
|
def find
|
15
13
|
paths = font_paths.grep(/#{font}/i)
|
14
|
+
paths = lookup_using_font_name || [] if paths.empty?
|
15
|
+
|
16
16
|
paths.empty? ? nil : paths
|
17
17
|
end
|
18
18
|
|
@@ -20,28 +20,32 @@ module Fontist
|
|
20
20
|
|
21
21
|
attr_reader :font, :user_sources
|
22
22
|
|
23
|
-
def
|
24
|
-
|
25
|
-
require "
|
26
|
-
|
23
|
+
def normalize_default_paths
|
24
|
+
@normalize_default_paths ||= default_sources["paths"].map do |path|
|
25
|
+
require "etc"
|
26
|
+
passwd = Etc.getpwuid
|
27
|
+
|
28
|
+
passwd ? path.gsub("{username}", passwd.name) : path
|
27
29
|
end
|
28
30
|
end
|
29
31
|
|
30
32
|
def font_paths
|
31
33
|
Dir.glob((
|
32
34
|
user_sources +
|
33
|
-
|
35
|
+
normalize_default_paths +
|
34
36
|
[fontist_fonts_path.join("**")]
|
35
37
|
).flatten.uniq)
|
36
38
|
end
|
37
39
|
|
40
|
+
def lookup_using_font_name
|
41
|
+
font_names = map_name_to_valid_font_names || []
|
42
|
+
font_paths.grep(/#{font_names.join("|")}/i) unless font_names.empty?
|
43
|
+
end
|
44
|
+
|
38
45
|
def fontist_fonts_path
|
39
46
|
@fontist_fonts_path ||= Fontist.fonts_path
|
40
47
|
end
|
41
48
|
|
42
|
-
def default_sources
|
43
|
-
@default_sources ||= Source.all.system[user_os.to_s]
|
44
|
-
end
|
45
49
|
|
46
50
|
def user_os
|
47
51
|
@user_os ||= (
|
@@ -50,7 +54,7 @@ module Fontist
|
|
50
54
|
when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
|
51
55
|
:windows
|
52
56
|
when /darwin|mac os/
|
53
|
-
:
|
57
|
+
:macos
|
54
58
|
when /linux/
|
55
59
|
:linux
|
56
60
|
when /solaris|bsd/
|
@@ -61,5 +65,17 @@ module Fontist
|
|
61
65
|
)
|
62
66
|
end
|
63
67
|
|
68
|
+
def map_name_to_valid_font_names
|
69
|
+
fonts = Formula.find_fonts(font)
|
70
|
+
fonts.map { |font| font.styles.map(&:font) }.flatten if fonts
|
71
|
+
end
|
72
|
+
|
73
|
+
def system_path_file
|
74
|
+
File.open(Fontist.lib_path.join("fontist", "system.yml"))
|
75
|
+
end
|
76
|
+
|
77
|
+
def default_sources
|
78
|
+
@default_sources ||= YAML.load(system_path_file)["system"][user_os.to_s]
|
79
|
+
end
|
64
80
|
end
|
65
81
|
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module Fontist
|
2
|
+
module Utils
|
3
|
+
class Downloader
|
4
|
+
def initialize(file, file_size: nil, sha: nil, progress_bar: nil)
|
5
|
+
# TODO: If the first mirror fails, try the second one
|
6
|
+
@file = file
|
7
|
+
@progress_bar = progress_bar
|
8
|
+
@sha = [sha].flatten.compact
|
9
|
+
@file_size = (file_size || default_file_size).to_i
|
10
|
+
end
|
11
|
+
|
12
|
+
def download
|
13
|
+
file = download_file
|
14
|
+
|
15
|
+
if !sha.empty? && !sha.include?(Digest::SHA256.file(file).to_s)
|
16
|
+
raise(Fontist::Errors::TamperedFileError.new(
|
17
|
+
"The downloaded file from #{@file} doesn't " \
|
18
|
+
"match with the expected sha256 checksum!"
|
19
|
+
))
|
20
|
+
end
|
21
|
+
|
22
|
+
file
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.download(file, options = {})
|
26
|
+
new(file, options).download
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
attr_reader :file, :sha, :file_size
|
32
|
+
|
33
|
+
def default_file_size
|
34
|
+
5 * byte_to_megabyte
|
35
|
+
end
|
36
|
+
|
37
|
+
def byte_to_megabyte
|
38
|
+
@byte_to_megabyte ||= 1024 * 1024
|
39
|
+
end
|
40
|
+
|
41
|
+
def download_path
|
42
|
+
options[:download_path] || Fontist.root_path.join("tmp")
|
43
|
+
end
|
44
|
+
|
45
|
+
def download_file
|
46
|
+
bar = ProgressBar.new(file_size / byte_to_megabyte)
|
47
|
+
|
48
|
+
Down.download(
|
49
|
+
@file,
|
50
|
+
open_timeout: 10,
|
51
|
+
read_timeout: 10,
|
52
|
+
progress_proc: -> (progress) {
|
53
|
+
bar.increment(progress / byte_to_megabyte) if @progress_bar === true
|
54
|
+
}
|
55
|
+
)
|
56
|
+
|
57
|
+
rescue Down::NotFound
|
58
|
+
raise(Fontist::Errors::InvalidResourceError.new("Invalid URL: #{@file}"))
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
class ProgressBar
|
63
|
+
def initialize(total)
|
64
|
+
@counter = 1
|
65
|
+
@total = total
|
66
|
+
end
|
67
|
+
|
68
|
+
def increment(progress)
|
69
|
+
complete = sprintf("%#.2f%%", ((@counter.to_f / @total.to_f) * 100))
|
70
|
+
print "\r\e[0KDownloads: #{@counter}MB/#{@total}MB (#{complete})"
|
71
|
+
@counter = progress
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,77 @@
|
|
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
|
+
|
72
|
+
def display_progress_bar(value )
|
73
|
+
instance.options = (instance.options || {}).merge(progress_bar: value )
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
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
|
data/lib/fontist/version.rb
CHANGED
@@ -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
|