fontist 1.9.3 → 1.11.2
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/.github/workflows/metanorma.yml +1 -1
- data/.github/workflows/rspec.yml +1 -1
- data/README.adoc +804 -0
- data/exe/fontist +24 -2
- data/fontist.gemspec +3 -2
- data/lib/fontist/cli.rb +23 -9
- data/lib/fontist/font.rb +8 -3
- data/lib/fontist/formula.rb +4 -0
- data/lib/fontist/google_cli.rb +29 -0
- data/lib/fontist/import/files/collection_file.rb +10 -1
- data/lib/fontist/import/formula_builder.rb +30 -5
- data/lib/fontist/import/google/new_fonts_fetcher.rb +44 -33
- data/lib/fontist/import/google.rb +18 -0
- data/lib/fontist/import/google_check.rb +0 -7
- data/lib/fontist/import/google_import.rb +26 -138
- data/lib/fontist/import/helpers/system_helper.rb +1 -1
- data/lib/fontist/import/otf/font_file.rb +17 -4
- data/lib/fontist/import/otf_parser.rb +2 -0
- data/lib/fontist/import/otf_style.rb +10 -2
- data/lib/fontist/import/otfinfo/template.erb +6 -0
- data/lib/fontist/import/recursive_extraction.rb +2 -1
- data/lib/fontist/index.rb +4 -28
- data/lib/fontist/indexes/default_family_font_index.rb +21 -0
- data/lib/fontist/indexes/font_index.rb +8 -13
- data/lib/fontist/indexes/preferred_family_font_index.rb +24 -0
- data/lib/fontist/system_font.rb +6 -16
- data/lib/fontist/system_index.rb +108 -29
- data/lib/fontist/update.rb +2 -2
- data/lib/fontist/utils/downloader.rb +14 -6
- data/lib/fontist/version.rb +1 -1
- data/lib/fontist.rb +43 -13
- metadata +26 -29
- data/.github/workflows/check_google.yml +0 -28
- data/README.md +0 -570
- data/lib/fontist/fontist_font.rb +0 -24
- data/lib/fontist/formula_paths.rb +0 -44
- data/lib/fontist/import/google/fonts_public.md +0 -10
- data/lib/fontist/import/google/fonts_public.pb.rb +0 -71
- data/lib/fontist/import/google/fonts_public.proto +0 -46
@@ -1,11 +1,29 @@
|
|
1
1
|
module Fontist
|
2
2
|
module Import
|
3
3
|
module Google
|
4
|
+
def self.metadata_name(path)
|
5
|
+
metadata_path = File.join(path, "METADATA.pb")
|
6
|
+
return unless File.exists?(metadata_path)
|
7
|
+
|
8
|
+
File.foreach(metadata_path) do |line|
|
9
|
+
name = line.match(/^name: "(.+)"/)
|
10
|
+
return name[1] if name
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
4
14
|
def self.formula_path(name)
|
5
15
|
filename = name.downcase.gsub(" ", "_") + ".yml"
|
6
16
|
Fontist.formulas_path.join("google", filename)
|
7
17
|
end
|
8
18
|
|
19
|
+
def self.digest(path)
|
20
|
+
checksums = Dir.glob(File.join(path, "*.{ttf,otf,ttc}"))
|
21
|
+
.sort
|
22
|
+
.map { |x| Digest::SHA256.file(x).to_s }
|
23
|
+
|
24
|
+
Digest::SHA256.hexdigest(checksums.to_s)
|
25
|
+
end
|
26
|
+
|
9
27
|
def self.style_version(text)
|
10
28
|
return unless text
|
11
29
|
|
@@ -4,17 +4,12 @@ module Fontist
|
|
4
4
|
module Import
|
5
5
|
class GoogleCheck
|
6
6
|
def call
|
7
|
-
fetch_formulas
|
8
7
|
fonts = new_fonts
|
9
8
|
indicate(fonts)
|
10
9
|
end
|
11
10
|
|
12
11
|
private
|
13
12
|
|
14
|
-
def fetch_formulas
|
15
|
-
Formula.update_formulas_repo
|
16
|
-
end
|
17
|
-
|
18
13
|
def new_fonts
|
19
14
|
Fontist::Import::Google::NewFontsFetcher.new(logging: true).call
|
20
15
|
end
|
@@ -26,8 +21,6 @@ module Fontist
|
|
26
21
|
new_paths.each do |path|
|
27
22
|
puts path
|
28
23
|
end
|
29
|
-
|
30
|
-
abort
|
31
24
|
end
|
32
25
|
end
|
33
26
|
end
|
@@ -1,11 +1,7 @@
|
|
1
1
|
require "erb"
|
2
2
|
require_relative "google"
|
3
3
|
require_relative "google/new_fonts_fetcher"
|
4
|
-
require_relative "
|
5
|
-
require_relative "template_helper"
|
6
|
-
require_relative "text_helper"
|
7
|
-
require_relative "otf_parser"
|
8
|
-
require_relative "otf_style"
|
4
|
+
require_relative "create_formula"
|
9
5
|
|
10
6
|
module Fontist
|
11
7
|
module Import
|
@@ -13,6 +9,7 @@ module Fontist
|
|
13
9
|
def call
|
14
10
|
fonts = new_fonts
|
15
11
|
create_formulas(fonts)
|
12
|
+
rebuild_index
|
16
13
|
end
|
17
14
|
|
18
15
|
private
|
@@ -22,157 +19,48 @@ module Fontist
|
|
22
19
|
end
|
23
20
|
|
24
21
|
def create_formulas(fonts)
|
22
|
+
return puts("Nothing to update") if fonts.empty?
|
23
|
+
|
25
24
|
puts "Creating formulas..."
|
26
25
|
fonts.each do |path|
|
27
26
|
create_formula(path)
|
28
27
|
end
|
29
28
|
end
|
30
29
|
|
31
|
-
def create_formula(
|
32
|
-
puts
|
33
|
-
metadata = fetch_metadata(path)
|
34
|
-
font = build_font(metadata, path)
|
35
|
-
save_formula(font)
|
36
|
-
end
|
30
|
+
def create_formula(font_path)
|
31
|
+
puts font_path
|
37
32
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
33
|
+
path = Fontist::Import::CreateFormula.new(
|
34
|
+
url(font_path),
|
35
|
+
name: Google.metadata_name(font_path),
|
36
|
+
formula_dir: formula_dir,
|
37
|
+
skip_sha: variable_style?(font_path),
|
38
|
+
digest: Google.digest(font_path),
|
39
|
+
).call
|
42
40
|
|
43
|
-
|
44
|
-
h = from_metadata(metadata)
|
45
|
-
.merge(from_otfinfo(path))
|
46
|
-
.merge(styles: styles_from_otfinfo(path, metadata.fonts))
|
47
|
-
.merge(from_license(path))
|
48
|
-
|
49
|
-
OpenStruct.new(h)
|
41
|
+
Fontist.ui.success("Formula has been successfully created: #{path}")
|
50
42
|
end
|
51
43
|
|
52
|
-
def
|
53
|
-
|
54
|
-
|
55
|
-
Hash.new.tap do |h|
|
56
|
-
h[:fullname] = metadata.name
|
57
|
-
h[:cleanname] = metadata.name.gsub(/ /, "")
|
58
|
-
h[:sha256] = sha256(metadata.name) unless variable_style?(metadata)
|
59
|
-
h[:copyright] = Fontist::Import::TextHelper.cleanup(copyright)
|
60
|
-
end
|
44
|
+
def url(path)
|
45
|
+
name = Google.metadata_name(path)
|
46
|
+
"https://fonts.google.com/download?family=#{ERB::Util.url_encode(name)}"
|
61
47
|
end
|
62
48
|
|
63
|
-
def
|
64
|
-
|
65
|
-
|
49
|
+
def formula_dir
|
50
|
+
@formula_dir ||= Fontist.formulas_path.join("google").tap do |path|
|
51
|
+
FileUtils.mkdir_p(path) unless File.exist?(path)
|
66
52
|
end
|
67
53
|
end
|
68
54
|
|
69
|
-
def
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
Digest::SHA256.file(file).to_s
|
75
|
-
end
|
76
|
-
|
77
|
-
def from_license(path)
|
78
|
-
file = Dir.glob(File.join(path, "{OFL.txt,UFL.txt,LICENSE.txt}")).first
|
79
|
-
print "warn, no license, " unless file
|
80
|
-
return { license: "" } unless file
|
81
|
-
|
82
|
-
{ license: cleanup_text(File.read(file)) }
|
83
|
-
end
|
84
|
-
|
85
|
-
def cleanup_text(text)
|
86
|
-
text.rstrip
|
87
|
-
.gsub("\r\n", "\n")
|
88
|
-
.lines
|
89
|
-
.map(&:rstrip)
|
90
|
-
.drop_while(&:empty?)
|
91
|
-
.join("\n")
|
92
|
-
end
|
93
|
-
|
94
|
-
def from_otfinfo(path)
|
95
|
-
font_file = Dir.glob(File.join(path, "*.ttf")).first
|
96
|
-
otf = OtfParser.new(font_file).call
|
97
|
-
|
98
|
-
{ homepage: otf["Vendor URL"],
|
99
|
-
license_url: otf["License URL"] }
|
100
|
-
end
|
101
|
-
|
102
|
-
def styles_from_otfinfo(path, fonts)
|
103
|
-
fonts.map do |f|
|
104
|
-
file_path = File.join(path, f.filename)
|
105
|
-
info = OtfParser.new(file_path).call
|
106
|
-
OtfStyle.new(info, file_path).call
|
55
|
+
def variable_style?(path)
|
56
|
+
fonts = Dir.glob(File.join(path, "*.{ttf,otf}"))
|
57
|
+
fonts.any? do |font|
|
58
|
+
File.basename(font).match?(/\[(.+,)?(wght|opsz)\]/)
|
107
59
|
end
|
108
60
|
end
|
109
61
|
|
110
|
-
def
|
111
|
-
|
112
|
-
path = formula_path(font.fullname)
|
113
|
-
save_to_path(hash, path)
|
114
|
-
end
|
115
|
-
|
116
|
-
def formula_hash(font)
|
117
|
-
stringify_keys(name: font.cleanname.sub(/\S/, &:upcase),
|
118
|
-
description: font.fullname,
|
119
|
-
homepage: font.homepage,
|
120
|
-
resources: formula_resource(font),
|
121
|
-
fonts: [yaml_font(font)],
|
122
|
-
extract: { format: :zip },
|
123
|
-
copyright: font.copyright,
|
124
|
-
license_url: font.license_url,
|
125
|
-
open_license: font.license)
|
126
|
-
end
|
127
|
-
|
128
|
-
def stringify_keys(hash)
|
129
|
-
JSON.parse(hash.to_json)
|
130
|
-
end
|
131
|
-
|
132
|
-
def formula_resource(font)
|
133
|
-
encoded_name = ERB::Util.url_encode(font.fullname)
|
134
|
-
url = "https://fonts.google.com/download?family=#{encoded_name}"
|
135
|
-
|
136
|
-
options = {}
|
137
|
-
options[:urls] = [url]
|
138
|
-
options[:sha256] = font.sha256 if font.sha256
|
139
|
-
|
140
|
-
{ "#{font.cleanname}.zip" => options }
|
141
|
-
end
|
142
|
-
|
143
|
-
def yaml_font(font)
|
144
|
-
{ name: font.fullname,
|
145
|
-
styles: yaml_styles(font.styles) }
|
146
|
-
end
|
147
|
-
|
148
|
-
def yaml_styles(styles)
|
149
|
-
styles.map do |s|
|
150
|
-
yaml_style(s)
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
def yaml_style(style)
|
155
|
-
Hash.new.tap do |h|
|
156
|
-
h.merge!(family_name: style.family_name,
|
157
|
-
type: style.style,
|
158
|
-
full_name: style.full_name)
|
159
|
-
h.merge!(style.to_h.select do |k, _|
|
160
|
-
%i(post_script_name version description copyright).include?(k)
|
161
|
-
end.compact)
|
162
|
-
h.merge!(font: fix_variable_filename(style.filename))
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
def fix_variable_filename(filename)
|
167
|
-
filename.sub("[wght]", "-VariableFont_wght")
|
168
|
-
end
|
169
|
-
|
170
|
-
def formula_path(name)
|
171
|
-
Fontist::Import::Google.formula_path(name)
|
172
|
-
end
|
173
|
-
|
174
|
-
def save_to_path(hash, path)
|
175
|
-
File.write(path, YAML.dump(hash))
|
62
|
+
def rebuild_index
|
63
|
+
Fontist::Index.rebuild
|
176
64
|
end
|
177
65
|
end
|
178
66
|
end
|
@@ -10,7 +10,8 @@ module Fontist
|
|
10
10
|
otfinfo: Otfinfo::OtfinfoRequirement.new,
|
11
11
|
}.freeze
|
12
12
|
|
13
|
-
STYLE_ATTRIBUTES = %i[family_name type
|
13
|
+
STYLE_ATTRIBUTES = %i[family_name type preferred_family_name
|
14
|
+
preferred_type full_name post_script_name
|
14
15
|
version description copyright font
|
15
16
|
source_font].freeze
|
16
17
|
|
@@ -35,11 +36,19 @@ module Fontist
|
|
35
36
|
end
|
36
37
|
|
37
38
|
def family_name
|
38
|
-
info["
|
39
|
+
info["Family"]
|
39
40
|
end
|
40
41
|
|
41
42
|
def type
|
42
|
-
info["
|
43
|
+
info["Subfamily"]
|
44
|
+
end
|
45
|
+
|
46
|
+
def preferred_family_name
|
47
|
+
info["Preferred family"]
|
48
|
+
end
|
49
|
+
|
50
|
+
def preferred_type
|
51
|
+
info["Preferred subfamily"]
|
43
52
|
end
|
44
53
|
|
45
54
|
def full_name
|
@@ -97,7 +106,11 @@ module Fontist
|
|
97
106
|
end
|
98
107
|
|
99
108
|
def detect_extension
|
100
|
-
Files::FontDetector.standard_extension(@path)
|
109
|
+
detected = Files::FontDetector.standard_extension(@path)
|
110
|
+
file_extension = File.extname(File.basename(@path)).sub(/^\./, "")
|
111
|
+
return file_extension if file_extension.casecmp?(detected)
|
112
|
+
|
113
|
+
detected
|
101
114
|
end
|
102
115
|
end
|
103
116
|
end
|
@@ -7,8 +7,8 @@ module Fontist
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def call
|
10
|
-
style = { family_name: @info["
|
11
|
-
style: @info["
|
10
|
+
style = { family_name: @info["Family"],
|
11
|
+
style: @info["Subfamily"],
|
12
12
|
full_name: @info["Full name"],
|
13
13
|
post_script_name: @info["PostScript name"],
|
14
14
|
version: version(@info["Version"]),
|
@@ -16,6 +16,14 @@ module Fontist
|
|
16
16
|
filename: File.basename(@path),
|
17
17
|
copyright: @info["Copyright"] }
|
18
18
|
|
19
|
+
if @info["Preferred family"]
|
20
|
+
style[:preferred_family_name] = @info["Preferred family"]
|
21
|
+
end
|
22
|
+
|
23
|
+
if @info["Preferred subfamily"]
|
24
|
+
style[:preferred_style] = @info["Preferred subfamily"]
|
25
|
+
end
|
26
|
+
|
19
27
|
OpenStruct.new(style)
|
20
28
|
end
|
21
29
|
|
@@ -2,6 +2,12 @@
|
|
2
2
|
{
|
3
3
|
family_name: "<%= s.family_name %>",
|
4
4
|
style: "<%= s.style %>",
|
5
|
+
<%- if s.preferred_family_name -%>
|
6
|
+
preferred_family_name: "<%= s.preferred_family_name %>",
|
7
|
+
<%- end -%>
|
8
|
+
<%- if s.preferred_style -%>
|
9
|
+
preferred_type: "<%= s.preferred_style %>",
|
10
|
+
<%- end -%>
|
5
11
|
full_name: "<%= s.full_name %>",
|
6
12
|
<%- if s.post_script_name -%>
|
7
13
|
post_script_name: "<%= s.post_script_name %>",
|
@@ -3,7 +3,8 @@ require_relative "files/font_detector"
|
|
3
3
|
module Fontist
|
4
4
|
module Import
|
5
5
|
class RecursiveExtraction
|
6
|
-
LICENSE_PATTERN =
|
6
|
+
LICENSE_PATTERN =
|
7
|
+
/(ofl\.txt|ufl\.txt|licenses?\.txt|license|copying)$/i.freeze
|
7
8
|
|
8
9
|
def initialize(archive, subarchive: nil, subdir: nil)
|
9
10
|
@archive = archive
|
data/lib/fontist/index.rb
CHANGED
@@ -3,41 +3,17 @@ require_relative "indexes/filename_index"
|
|
3
3
|
|
4
4
|
module Fontist
|
5
5
|
class Index
|
6
|
-
def self.rebuild_for_main_repo
|
7
|
-
unless Dir.exist?(Fontist.private_formulas_path)
|
8
|
-
return do_rebuild_for_main_repo_with
|
9
|
-
end
|
10
|
-
|
11
|
-
Dir.mktmpdir do |dir|
|
12
|
-
tmp_private_path = File.join(dir, "private")
|
13
|
-
FileUtils.mv(Fontist.private_formulas_path, tmp_private_path)
|
14
|
-
|
15
|
-
do_rebuild_for_main_repo_with
|
16
|
-
|
17
|
-
FileUtils.mv(tmp_private_path, Fontist.private_formulas_path)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.do_rebuild_for_main_repo_with
|
22
|
-
Fontist.formula_index_path = Fontist.formulas_repo_path.join("index.yml")
|
23
|
-
Fontist.formula_filename_index_path =
|
24
|
-
Fontist.formulas_repo_path.join("filename_index.yml")
|
25
|
-
|
26
|
-
rebuild
|
27
|
-
|
28
|
-
Fontist.formula_index_path = nil
|
29
|
-
Fontist.formula_filename_index_path = nil
|
30
|
-
end
|
31
|
-
|
32
6
|
def self.rebuild
|
33
|
-
Fontist::Indexes::
|
7
|
+
Fontist::Indexes::DefaultFamilyFontIndex.rebuild
|
8
|
+
Fontist::Indexes::PreferredFamilyFontIndex.rebuild
|
34
9
|
Fontist::Indexes::FilenameIndex.rebuild
|
35
10
|
|
36
11
|
reset_cache
|
37
12
|
end
|
38
13
|
|
39
14
|
def self.reset_cache
|
40
|
-
Fontist::Indexes::
|
15
|
+
Fontist::Indexes::DefaultFamilyFontIndex.reset_cache
|
16
|
+
Fontist::Indexes::PreferredFamilyFontIndex.reset_cache
|
41
17
|
Fontist::Indexes::FilenameIndex.reset_cache
|
42
18
|
end
|
43
19
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require_relative "base_index"
|
2
|
+
|
3
|
+
module Fontist
|
4
|
+
module Indexes
|
5
|
+
class DefaultFamilyFontIndex < BaseIndex
|
6
|
+
def self.path
|
7
|
+
Fontist.formula_index_path
|
8
|
+
end
|
9
|
+
|
10
|
+
def add_formula(formula)
|
11
|
+
formula.fonts.each do |font|
|
12
|
+
add_index_formula(font.name, formula.to_index_formula)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def normalize_key(key)
|
17
|
+
key.downcase
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -1,21 +1,16 @@
|
|
1
|
-
require_relative "
|
1
|
+
require_relative "default_family_font_index"
|
2
|
+
require_relative "preferred_family_font_index"
|
2
3
|
|
3
4
|
module Fontist
|
4
5
|
module Indexes
|
5
|
-
class FontIndex
|
6
|
-
def self.
|
7
|
-
Fontist.
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
formula.fonts.each do |font|
|
12
|
-
add_index_formula(font.name, formula.to_index_formula)
|
6
|
+
class FontIndex
|
7
|
+
def self.from_yaml
|
8
|
+
if Fontist.preferred_family?
|
9
|
+
PreferredFamilyFontIndex.from_yaml
|
10
|
+
else
|
11
|
+
DefaultFamilyFontIndex.from_yaml
|
13
12
|
end
|
14
13
|
end
|
15
|
-
|
16
|
-
def normalize_key(key)
|
17
|
-
key.downcase
|
18
|
-
end
|
19
14
|
end
|
20
15
|
end
|
21
16
|
end
|