fontist 1.5.1 → 1.7.3
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.
- checksums.yaml +4 -4
- data/README.md +75 -28
- data/fontist.gemspec +1 -0
- data/lib/fontist.rb +5 -1
- data/lib/fontist/cli.rb +23 -12
- data/lib/fontist/errors.rb +1 -0
- data/lib/fontist/font.rb +17 -3
- data/lib/fontist/font_formula.rb +58 -16
- data/lib/fontist/formula.rb +13 -53
- data/lib/fontist/formula_template.rb +16 -2
- data/lib/fontist/import/create_formula.rb +15 -30
- data/lib/fontist/import/files/collection_file.rb +6 -1
- data/lib/fontist/import/files/file_requirement.rb +17 -0
- data/lib/fontist/import/files/font_detector.rb +48 -0
- data/lib/fontist/import/formula_builder.rb +7 -3
- data/lib/fontist/import/otf/font_file.rb +17 -3
- data/lib/fontist/import/recursive_extraction.rb +69 -12
- data/lib/fontist/manifest/install.rb +5 -13
- data/lib/fontist/manifest/locations.rb +51 -4
- data/lib/fontist/system_font.rb +44 -44
- data/lib/fontist/system_index.rb +92 -0
- data/lib/fontist/utils.rb +1 -0
- data/lib/fontist/utils/cache.rb +22 -6
- data/lib/fontist/utils/downloader.rb +54 -10
- data/lib/fontist/utils/dsl.rb +4 -0
- data/lib/fontist/utils/dsl/collection_font.rb +36 -0
- data/lib/fontist/utils/dsl/font.rb +2 -1
- data/lib/fontist/utils/exe_extractor.rb +7 -4
- data/lib/fontist/utils/ui.rb +4 -0
- data/lib/fontist/utils/zip_extractor.rb +20 -11
- data/lib/fontist/version.rb +1 -1
- metadata +20 -3
- data/lib/fontist/manifest/common.rb +0 -60
@@ -23,10 +23,23 @@ module Fontist
|
|
23
23
|
formula.font_collections.each do |collection|
|
24
24
|
provides_font_collection do
|
25
25
|
filename collection.filename
|
26
|
+
source_filename collection.source_filename
|
26
27
|
|
27
28
|
collection.fonts.each do |font|
|
28
|
-
|
29
|
-
|
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
|
+
)
|
30
43
|
end
|
31
44
|
end
|
32
45
|
end
|
@@ -45,6 +58,7 @@ module Fontist
|
|
45
58
|
version: style.version,
|
46
59
|
description: style.description,
|
47
60
|
filename: style.font,
|
61
|
+
source_filename: style.source_font,
|
48
62
|
copyright: style.copyright,
|
49
63
|
}
|
50
64
|
end
|
@@ -8,10 +8,6 @@ require_relative "formula_builder"
|
|
8
8
|
module Fontist
|
9
9
|
module Import
|
10
10
|
class CreateFormula
|
11
|
-
FONT_PATTERN = /(\.ttf|\.otf)/i.freeze
|
12
|
-
FONT_COLLECTION_PATTERN = /\.ttc/i.freeze
|
13
|
-
LICENSE_PATTERN = /(OFL\.txt|UFL\.txt|LICENSE\.txt|COPYING)$/i.freeze
|
14
|
-
|
15
11
|
def initialize(url, options = {})
|
16
12
|
@url = url
|
17
13
|
@options = options
|
@@ -26,41 +22,30 @@ module Fontist
|
|
26
22
|
def formula
|
27
23
|
builder = FormulaBuilder.new
|
28
24
|
builder.url = @url
|
29
|
-
builder.archive =
|
30
|
-
builder.extractor = extractor
|
25
|
+
builder.archive = archive
|
26
|
+
builder.extractor = extractor
|
31
27
|
builder.options = @options
|
32
|
-
builder.font_files = font_files
|
33
|
-
builder.font_collection_files = font_collection_files
|
34
|
-
builder.license_text =
|
28
|
+
builder.font_files = extractor.font_files
|
29
|
+
builder.font_collection_files = extractor.font_collection_files
|
30
|
+
builder.license_text = extractor.license_text
|
35
31
|
builder.formula
|
36
32
|
end
|
37
33
|
|
38
|
-
def
|
39
|
-
|
40
|
-
|
41
|
-
|
34
|
+
def extractor
|
35
|
+
@extractor ||=
|
36
|
+
RecursiveExtraction.new(archive,
|
37
|
+
subarchive: @options[:subarchive],
|
38
|
+
subdir: @options[:subdir])
|
42
39
|
end
|
43
40
|
|
44
|
-
def
|
45
|
-
|
41
|
+
def archive
|
42
|
+
@archive ||= download(@url)
|
46
43
|
end
|
47
44
|
|
48
|
-
def
|
49
|
-
|
50
|
-
Otf::FontFile.new(path)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def font_collection_files(extractor)
|
55
|
-
extractor.extract(FONT_COLLECTION_PATTERN) do |path|
|
56
|
-
Files::CollectionFile.new(path)
|
57
|
-
end
|
58
|
-
end
|
45
|
+
def download(url)
|
46
|
+
return url if File.exist?(url)
|
59
47
|
|
60
|
-
|
61
|
-
extractor.extract(LICENSE_PATTERN) do |path|
|
62
|
-
File.read(path)
|
63
|
-
end
|
48
|
+
Fontist::Utils::Downloader.download(url, progress_bar: true).path
|
64
49
|
end
|
65
50
|
|
66
51
|
def save(hash)
|
@@ -11,10 +11,15 @@ module Fontist
|
|
11
11
|
def initialize(path)
|
12
12
|
@path = path
|
13
13
|
@fonts = read
|
14
|
+
@extension = "ttc"
|
14
15
|
end
|
15
16
|
|
16
17
|
def filename
|
17
|
-
File.basename(@path)
|
18
|
+
File.basename(@path, ".*") + "." + @extension
|
19
|
+
end
|
20
|
+
|
21
|
+
def source_filename
|
22
|
+
File.basename(@path) unless filename == File.basename(@path)
|
18
23
|
end
|
19
24
|
|
20
25
|
private
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Fontist
|
2
|
+
module Import
|
3
|
+
module Files
|
4
|
+
class FileRequirement
|
5
|
+
def initialize
|
6
|
+
`file -v`
|
7
|
+
rescue Errno::ENOENT
|
8
|
+
abort "`file` is not available. (Or is PATH not setup properly?)"
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(path)
|
12
|
+
Helpers::SystemHelper.run("file --brief '#{path}'")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require_relative "file_requirement"
|
2
|
+
|
3
|
+
module Fontist
|
4
|
+
module Import
|
5
|
+
module Files
|
6
|
+
class FontDetector
|
7
|
+
REQUIREMENTS = { file: FileRequirement.new }.freeze
|
8
|
+
|
9
|
+
FONT_LABELS = ["OpenType font data",
|
10
|
+
"TrueType Font data"].freeze
|
11
|
+
|
12
|
+
COLLECTION_LABEL = "TrueType font collection data".freeze
|
13
|
+
|
14
|
+
FONT_EXTENSIONS = {
|
15
|
+
"OpenType font data" => "otf",
|
16
|
+
"TrueType Font data" => "ttf",
|
17
|
+
"TrueType font collection data" => "ttc",
|
18
|
+
}.freeze
|
19
|
+
|
20
|
+
def self.detect(path)
|
21
|
+
brief = file_brief(path)
|
22
|
+
|
23
|
+
if brief.start_with?(*FONT_LABELS)
|
24
|
+
:font
|
25
|
+
elsif brief.start_with?(COLLECTION_LABEL)
|
26
|
+
:collection
|
27
|
+
else
|
28
|
+
:other
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.standard_extension(path)
|
33
|
+
brief = file_brief(path)
|
34
|
+
|
35
|
+
FONT_EXTENSIONS.each do |label, extension|
|
36
|
+
return extension if brief.start_with?(label)
|
37
|
+
end
|
38
|
+
|
39
|
+
raise Errors::UnknownFontTypeError.new(path)
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.file_brief(path)
|
43
|
+
REQUIREMENTS[:file].call(path)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -107,7 +107,10 @@ module Fontist
|
|
107
107
|
|
108
108
|
collections = @font_collection_files.map do |file|
|
109
109
|
fonts = fonts_from_files(file.fonts, :to_collection_style)
|
110
|
-
|
110
|
+
|
111
|
+
{ filename: file.filename,
|
112
|
+
source_filename: file.source_filename,
|
113
|
+
fonts: fonts }.compact
|
111
114
|
end
|
112
115
|
|
113
116
|
collections.sort_by do |x|
|
@@ -152,8 +155,9 @@ module Fontist
|
|
152
155
|
return
|
153
156
|
end
|
154
157
|
|
155
|
-
Fontist.ui.error("WARN: ensure it's an open license, otherwise
|
156
|
-
|
158
|
+
Fontist.ui.error("WARN: ensure it's an open license, otherwise " \
|
159
|
+
"change the 'open_license' attribute to " \
|
160
|
+
"'requires_license_agreement'")
|
157
161
|
|
158
162
|
TextHelper.cleanup(@license_text)
|
159
163
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require_relative "../otfinfo/otfinfo_requirement"
|
2
2
|
require_relative "../text_helper"
|
3
|
+
require_relative "../files/font_detector"
|
3
4
|
|
4
5
|
module Fontist
|
5
6
|
module Import
|
@@ -10,14 +11,19 @@ module Fontist
|
|
10
11
|
}.freeze
|
11
12
|
|
12
13
|
STYLE_ATTRIBUTES = %i[family_name type full_name post_script_name
|
13
|
-
version description copyright font
|
14
|
-
|
14
|
+
version description copyright font
|
15
|
+
source_font].freeze
|
16
|
+
|
17
|
+
COLLECTION_ATTRIBUTES = STYLE_ATTRIBUTES.reject do |a|
|
18
|
+
%i[font source_font].include?(a)
|
19
|
+
end
|
15
20
|
|
16
21
|
attr_reader :path
|
17
22
|
|
18
23
|
def initialize(path)
|
19
24
|
@path = path
|
20
25
|
@info = read
|
26
|
+
@extension = detect_extension
|
21
27
|
end
|
22
28
|
|
23
29
|
def to_style
|
@@ -55,7 +61,11 @@ module Fontist
|
|
55
61
|
end
|
56
62
|
|
57
63
|
def font
|
58
|
-
File.basename(@path)
|
64
|
+
File.basename(@path, ".*") + "." + @extension
|
65
|
+
end
|
66
|
+
|
67
|
+
def source_font
|
68
|
+
File.basename(@path) unless font == File.basename(@path)
|
59
69
|
end
|
60
70
|
|
61
71
|
def copyright
|
@@ -85,6 +95,10 @@ module Fontist
|
|
85
95
|
.map { |x| x.map { |y| Fontist::Import::TextHelper.cleanup(y) } }
|
86
96
|
.to_h
|
87
97
|
end
|
98
|
+
|
99
|
+
def detect_extension
|
100
|
+
Files::FontDetector.standard_extension(@path)
|
101
|
+
end
|
88
102
|
end
|
89
103
|
end
|
90
104
|
end
|
@@ -1,28 +1,40 @@
|
|
1
1
|
require "find"
|
2
2
|
require_relative "extractors"
|
3
|
+
require_relative "files/font_detector"
|
3
4
|
|
4
5
|
module Fontist
|
5
6
|
module Import
|
6
7
|
class RecursiveExtraction
|
7
|
-
|
8
|
+
FONTS_PATTERN = "**/*.{ttf,otf,ttc}".freeze
|
8
9
|
ARCHIVE_EXTENSIONS = %w[zip msi exe cab].freeze
|
10
|
+
LICENSE_PATTERN = /(OFL\.txt|UFL\.txt|LICENSE\.txt|COPYING)$/i.freeze
|
9
11
|
|
10
|
-
def initialize(archive, subarchive: nil)
|
12
|
+
def initialize(archive, subarchive: nil, subdir: nil)
|
11
13
|
@archive = archive
|
12
14
|
@subarchive = subarchive
|
15
|
+
@subdir = subdir
|
13
16
|
@operations = []
|
17
|
+
@font_files = []
|
18
|
+
@collection_files = []
|
14
19
|
end
|
15
20
|
|
16
21
|
def extension
|
17
22
|
File.extname(filename(@archive)).sub(/^\./, "")
|
18
23
|
end
|
19
24
|
|
20
|
-
def
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
25
|
+
def font_files
|
26
|
+
ensure_extracted
|
27
|
+
@font_files
|
28
|
+
end
|
29
|
+
|
30
|
+
def font_collection_files
|
31
|
+
ensure_extracted
|
32
|
+
@collection_files
|
33
|
+
end
|
34
|
+
|
35
|
+
def license_text
|
36
|
+
ensure_extracted
|
37
|
+
@license_text
|
26
38
|
end
|
27
39
|
|
28
40
|
def operations
|
@@ -50,7 +62,11 @@ module Fontist
|
|
50
62
|
|
51
63
|
def extract_recursively(archive)
|
52
64
|
path = operate_on_archive(archive)
|
53
|
-
|
65
|
+
match_files(path)
|
66
|
+
if matched?
|
67
|
+
save_operation_subdir
|
68
|
+
return path
|
69
|
+
end
|
54
70
|
|
55
71
|
next_archive = find_archive(path)
|
56
72
|
extract_recursively(next_archive)
|
@@ -84,9 +100,50 @@ module Fontist
|
|
84
100
|
@operations << { format: extractor.format }
|
85
101
|
end
|
86
102
|
|
87
|
-
def
|
88
|
-
|
89
|
-
|
103
|
+
def match_files(dir_path)
|
104
|
+
Find.find(dir_path) do |entry_path| # rubocop:disable Style/CollectionMethods
|
105
|
+
match_license(entry_path)
|
106
|
+
match_font(entry_path) if font_directory?(entry_path, dir_path)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def match_license(path)
|
111
|
+
@license_text ||= File.read(path) if license?(path)
|
112
|
+
end
|
113
|
+
|
114
|
+
def license?(file)
|
115
|
+
file.match?(LICENSE_PATTERN)
|
116
|
+
end
|
117
|
+
|
118
|
+
def font_directory?(path, base_path)
|
119
|
+
return true unless @subdir
|
120
|
+
|
121
|
+
relative_path = Pathname.new(path).relative_path_from(base_path).to_s
|
122
|
+
dirname = File.dirname(relative_path)
|
123
|
+
normalized_pattern = @subdir.chomp("/")
|
124
|
+
File.fnmatch?(normalized_pattern, dirname)
|
125
|
+
end
|
126
|
+
|
127
|
+
def match_font(path)
|
128
|
+
case Files::FontDetector.detect(path)
|
129
|
+
when :font
|
130
|
+
@font_files << Otf::FontFile.new(path)
|
131
|
+
when :collection
|
132
|
+
@collection_files << Files::CollectionFile.new(path)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def matched?
|
137
|
+
[@font_files, @collection_files].any? do |files|
|
138
|
+
files.size.positive?
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def save_operation_subdir
|
143
|
+
return unless @subdir
|
144
|
+
|
145
|
+
@operations.last[:options] ||= {}
|
146
|
+
@operations.last[:options][:fonts_sub_dir] = @subdir
|
90
147
|
end
|
91
148
|
|
92
149
|
def find_archive(path)
|
@@ -1,29 +1,21 @@
|
|
1
|
-
require_relative "
|
1
|
+
require_relative "locations"
|
2
2
|
|
3
3
|
module Fontist
|
4
4
|
module Manifest
|
5
|
-
class Install <
|
5
|
+
class Install < Locations
|
6
6
|
def initialize(manifest, confirmation: "no")
|
7
7
|
@manifest = manifest
|
8
8
|
@confirmation = confirmation
|
9
9
|
end
|
10
10
|
|
11
|
-
def self.call(manifest, confirmation: "no")
|
12
|
-
new(manifest, confirmation: confirmation).call
|
13
|
-
end
|
14
|
-
|
15
11
|
private
|
16
12
|
|
17
13
|
def file_paths(font, style)
|
18
|
-
paths =
|
19
|
-
return paths unless paths.empty?
|
14
|
+
paths = super
|
15
|
+
return paths unless paths["paths"].empty?
|
20
16
|
|
21
17
|
install_font(font)
|
22
|
-
|
23
|
-
end
|
24
|
-
|
25
|
-
def find_installed_font(font, style)
|
26
|
-
Fontist::SystemFont.find_with_style(font, style)
|
18
|
+
super
|
27
19
|
end
|
28
20
|
|
29
21
|
def install_font(font)
|
@@ -1,12 +1,59 @@
|
|
1
|
-
require_relative "common"
|
2
|
-
|
3
1
|
module Fontist
|
4
2
|
module Manifest
|
5
|
-
class Locations
|
3
|
+
class Locations
|
4
|
+
def initialize(manifest)
|
5
|
+
@manifest = manifest
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.from_file(file, **keywords)
|
9
|
+
raise Fontist::Errors::ManifestCouldNotBeFoundError unless File.exist?(file)
|
10
|
+
|
11
|
+
manifest = YAML.load_file(file)
|
12
|
+
raise Fontist::Errors::ManifestCouldNotBeReadError unless manifest.is_a?(Hash)
|
13
|
+
|
14
|
+
from_hash(manifest, **keywords)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.from_hash(manifest, **keywords)
|
18
|
+
if keywords.empty?
|
19
|
+
new(manifest).call
|
20
|
+
else
|
21
|
+
new(manifest, **keywords).call
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def call
|
26
|
+
font_names.zip(font_paths).to_h
|
27
|
+
end
|
28
|
+
|
6
29
|
private
|
7
30
|
|
31
|
+
attr_reader :manifest
|
32
|
+
|
33
|
+
def font_names
|
34
|
+
manifest.keys
|
35
|
+
end
|
36
|
+
|
37
|
+
def font_paths
|
38
|
+
manifest.map do |font, styles|
|
39
|
+
styles_to_ary = [styles].flatten
|
40
|
+
style_paths_map(font, styles_to_ary)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def style_paths_map(font, names)
|
45
|
+
paths = style_paths(font, names)
|
46
|
+
names.zip(paths).to_h
|
47
|
+
end
|
48
|
+
|
49
|
+
def style_paths(font, names)
|
50
|
+
names.map do |style|
|
51
|
+
file_paths(font, style)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
8
55
|
def file_paths(font, style)
|
9
|
-
Fontist::SystemFont.
|
56
|
+
Fontist::SystemFont.find_with_name(font, style).transform_keys(&:to_s)
|
10
57
|
end
|
11
58
|
end
|
12
59
|
end
|