fontico 0.1.1 → 1.2.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.
- checksums.yaml +4 -4
- data/README.md +182 -31
- data/lib/fontico/builder.rb +81 -8
- data/lib/fontico/emitters/font.rb +10 -3
- data/lib/fontico/emitters/gfx_font.rb +190 -0
- data/lib/fontico/emitters/header.rb +165 -0
- data/lib/fontico/emitters/stylesheet.rb +5 -0
- data/lib/fontico/helper.rb +45 -23
- data/lib/fontico/lockfile.rb +44 -5
- data/lib/fontico/manifest.rb +75 -4
- data/lib/fontico/node/rasterize.mjs +192 -0
- data/lib/fontico/railtie.rb +7 -1
- data/lib/fontico/version.rb +1 -1
- data/lib/fontico.rb +54 -3
- data/lib/tasks/fontico.rake +42 -30
- metadata +5 -2
data/lib/fontico/version.rb
CHANGED
data/lib/fontico.rb
CHANGED
|
@@ -23,6 +23,8 @@ module Fontico
|
|
|
23
23
|
autoload :Sprite, "fontico/emitters/sprite"
|
|
24
24
|
autoload :Font, "fontico/emitters/font"
|
|
25
25
|
autoload :Stylesheet, "fontico/emitters/stylesheet"
|
|
26
|
+
autoload :Header, "fontico/emitters/header"
|
|
27
|
+
autoload :GfxFont, "fontico/emitters/gfx_font"
|
|
26
28
|
end
|
|
27
29
|
|
|
28
30
|
class << self
|
|
@@ -34,9 +36,53 @@ module Fontico
|
|
|
34
36
|
def root = @root ||= Dir.pwd
|
|
35
37
|
def output_dir = @output_dir ||= "app/assets/builds"
|
|
36
38
|
def manifest_path = @manifest_path ||= File.join(root, "icons.yml")
|
|
37
|
-
|
|
39
|
+
# Same shape as I18n.load_path: engines first, the app last, later wins
|
|
40
|
+
# a name. Unset, it is just the app's icons.yml (non-Rails, tests).
|
|
41
|
+
def load_path = @load_path || [manifest_path].select { File.file?(_1) }
|
|
42
|
+
|
|
43
|
+
def load_path=(paths)
|
|
44
|
+
@load_path = paths.nil? ? nil : Array(paths)
|
|
45
|
+
reset!
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def manifest = @manifest ||= Manifest.load(*load_path)
|
|
38
49
|
def sprite_file = File.join(root, output_dir, "icons.svg")
|
|
39
50
|
|
|
51
|
+
# Rendered markup for bare icon() calls, minus the sprite path. Keyed by
|
|
52
|
+
# name and bounded by the manifest, so it cannot grow with traffic.
|
|
53
|
+
def icon_cache = @icon_cache ||= {}
|
|
54
|
+
|
|
55
|
+
# Inline mode embeds the sprite in every response, and it used to be
|
|
56
|
+
# re-read off disk on every call: 13us and a fresh 10KB string per
|
|
57
|
+
# request, more than a whole page of icon() calls costs. Held instead,
|
|
58
|
+
# behind a stat, which is cheap next to the read and means a rebuild from
|
|
59
|
+
# anywhere — the dev watcher, or `rake fontico:build` in another terminal
|
|
60
|
+
# — is picked up without waiting for a reset!.
|
|
61
|
+
def sprite_markup
|
|
62
|
+
stamp = File.stat(sprite_file).then { [_1.mtime, _1.size] }
|
|
63
|
+
return @sprite_markup if @sprite_stamp == stamp
|
|
64
|
+
|
|
65
|
+
@sprite_stamp = stamp
|
|
66
|
+
@sprite_markup = File.read(sprite_file).freeze
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Rails engines that ship config/icons.yml (or icons.yml at the gem
|
|
70
|
+
# root), then the app's file. The app is last on purpose.
|
|
71
|
+
def discover(app)
|
|
72
|
+
files = []
|
|
73
|
+
app.railties.each do |rt|
|
|
74
|
+
next unless rt.is_a?(Rails::Engine)
|
|
75
|
+
next if rt.is_a?(Rails::Application)
|
|
76
|
+
|
|
77
|
+
root = rt.root
|
|
78
|
+
found = %w[config/icons.yml icons.yml].map { root.join(_1) }.find { File.file?(_1.to_s) }
|
|
79
|
+
files << found.to_s if found
|
|
80
|
+
end
|
|
81
|
+
# manifest_path goes in even when absent: the dev watcher has to notice
|
|
82
|
+
# an icons.yml created after boot. Manifest.load skips what isn't there.
|
|
83
|
+
(files.select { File.file?(_1) } << manifest_path).uniq
|
|
84
|
+
end
|
|
85
|
+
|
|
40
86
|
# Inline mode embeds <symbol> definitions in the layout instead of
|
|
41
87
|
# referencing an external file — required when assets are served from a
|
|
42
88
|
# CDN, where cross-origin <use href> silently renders nothing.
|
|
@@ -85,13 +131,18 @@ module Fontico
|
|
|
85
131
|
# a reference in Ruby source never goes stale.
|
|
86
132
|
def codepoint(name)
|
|
87
133
|
cp = lockfile.codepoint_for(name.to_s)
|
|
88
|
-
raise Error, "no icon named #{name.inspect}
|
|
134
|
+
raise Error, "no icon named #{name.inspect} in icons.lock" if cp.nil?
|
|
89
135
|
|
|
90
136
|
cp
|
|
91
137
|
end
|
|
92
138
|
|
|
93
139
|
def glyph(name) = [codepoint(name)].pack("U")
|
|
94
|
-
|
|
140
|
+
# Drops everything derived from a build. The dev watcher calls this after
|
|
141
|
+
# every rebuild, which is what keeps the caches above honest.
|
|
142
|
+
def reset!
|
|
143
|
+
@manifest = @build_error = @missing_icons = nil
|
|
144
|
+
@icon_cache = @sprite_markup = @sprite_stamp = nil
|
|
145
|
+
end
|
|
95
146
|
|
|
96
147
|
def configure = yield(self)
|
|
97
148
|
end
|
data/lib/tasks/fontico.rake
CHANGED
|
@@ -4,43 +4,52 @@
|
|
|
4
4
|
# is noise, and the message reads fine without it.
|
|
5
5
|
def fontico_red(text) = $stdout.tty? ? "\e[31m#{text}\e[0m" : text
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
report = Fontico.build
|
|
7
|
+
def fontico_print_report(report)
|
|
8
|
+
puts "fontico: #{report.written.size} artifact(s)"
|
|
9
|
+
report.written.each { puts " #{_1}" }
|
|
10
|
+
puts " fetched #{report.fetched.size}, cached #{report.cached.size}"
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
# Loud, but not fatal: one bad name should not stop the other 199 icons
|
|
13
|
+
# from building. The artifacts simply come out without it.
|
|
14
|
+
if report.missing&.any?
|
|
15
|
+
puts
|
|
16
|
+
puts fontico_red("fontico: #{report.missing.size} icon(s) could not be resolved and were left out:")
|
|
17
|
+
report.missing.each { |name, reason| puts fontico_red(" #{name}: #{reason}") }
|
|
18
|
+
puts fontico_red(" fix the entry in icons.yml, then run rake fontico:build again")
|
|
19
|
+
puts
|
|
20
|
+
end
|
|
16
21
|
|
|
17
|
-
|
|
18
|
-
#
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
puts fontico_red("fontico: #{report.missing.size} icon(s) could not be resolved and were left out:")
|
|
22
|
-
report.missing.each { |name, reason| puts fontico_red(" #{name}: #{reason}") }
|
|
23
|
-
puts fontico_red(" fix the entry in icons.yml, then run rake fontico:build again")
|
|
24
|
-
puts
|
|
25
|
-
end
|
|
22
|
+
report.skipped.each do |target, names|
|
|
23
|
+
puts " #{target}: skipped #{names.size} multicolor icon(s): #{names.join(", ")}" if names.any?
|
|
24
|
+
end
|
|
25
|
+
puts " pending target(s): #{report.pending.join(", ")}" if report.pending.any?
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
puts "
|
|
27
|
+
if report.warnings.any?
|
|
28
|
+
puts "\nfontico: #{report.warnings.size} icon(s) need fixing at the source:"
|
|
29
|
+
report.warnings.each { |name, list| puts " #{name}: #{list.join("; ")}" }
|
|
30
|
+
puts " see docs/icon-authoring.html"
|
|
31
|
+
end
|
|
32
|
+
end
|
|
31
33
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
def fontico_rails_load_path!
|
|
35
|
+
return unless defined?(Rails) && Rails.respond_to?(:application) && Rails.application
|
|
36
|
+
|
|
37
|
+
Fontico.load_path = Fontico.discover(Rails.application)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
namespace :fontico do
|
|
41
|
+
desc "Build icon artifacts from icons.yml"
|
|
42
|
+
task :build do
|
|
43
|
+
require "fontico"
|
|
44
|
+
fontico_rails_load_path!
|
|
45
|
+
fontico_print_report(Fontico.build)
|
|
37
46
|
end
|
|
38
47
|
|
|
39
|
-
desc "Re-fetch every icon
|
|
48
|
+
desc "Re-fetch every icon from its provider. Codepoints stay pinned."
|
|
40
49
|
task :update do
|
|
41
50
|
require "fontico"
|
|
42
|
-
|
|
43
|
-
|
|
51
|
+
fontico_rails_load_path!
|
|
52
|
+
fontico_print_report(Fontico.build(force: true))
|
|
44
53
|
end
|
|
45
54
|
end
|
|
46
55
|
|
|
@@ -58,10 +67,13 @@ if Rake::Task.task_defined?("assets:clobber")
|
|
|
58
67
|
end
|
|
59
68
|
|
|
60
69
|
namespace :fontico do
|
|
70
|
+
# Only what lands in output_dir. A target given an explicit path in the
|
|
71
|
+
# manifest is pointing somewhere the app owns — a firmware include/ that is
|
|
72
|
+
# very likely committed — and deleting that is not precompile's business.
|
|
61
73
|
desc "Remove generated icon artifacts (icons.lock is kept: it is source)"
|
|
62
74
|
task :clobber do
|
|
63
75
|
require "fontico"
|
|
64
|
-
%w[icons.svg icons.css icons.ttf].each do |name|
|
|
76
|
+
%w[icons.svg icons.css icons.ttf icons.h icons_font.h].each do |name|
|
|
65
77
|
path = File.join(Fontico.root, Fontico.output_dir, name)
|
|
66
78
|
File.delete(path) if File.exist?(path)
|
|
67
79
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: fontico
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 1.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- nofxx
|
|
@@ -86,6 +86,8 @@ files:
|
|
|
86
86
|
- lib/fontico.rb
|
|
87
87
|
- lib/fontico/builder.rb
|
|
88
88
|
- lib/fontico/emitters/font.rb
|
|
89
|
+
- lib/fontico/emitters/gfx_font.rb
|
|
90
|
+
- lib/fontico/emitters/header.rb
|
|
89
91
|
- lib/fontico/emitters/sprite.rb
|
|
90
92
|
- lib/fontico/emitters/stylesheet.rb
|
|
91
93
|
- lib/fontico/helper.rb
|
|
@@ -95,6 +97,7 @@ files:
|
|
|
95
97
|
- lib/fontico/node/build_font.mjs
|
|
96
98
|
- lib/fontico/node/extract_glyphs.mjs
|
|
97
99
|
- lib/fontico/node/package.json
|
|
100
|
+
- lib/fontico/node/rasterize.mjs
|
|
98
101
|
- lib/fontico/node_runner.rb
|
|
99
102
|
- lib/fontico/outliner.rb
|
|
100
103
|
- lib/fontico/prawn.rb
|
|
@@ -126,7 +129,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
126
129
|
- !ruby/object:Gem::Version
|
|
127
130
|
version: '0'
|
|
128
131
|
requirements: []
|
|
129
|
-
rubygems_version: 3.6.
|
|
132
|
+
rubygems_version: 3.6.9
|
|
130
133
|
specification_version: 4
|
|
131
134
|
summary: Name icons by intent. Source them from anywhere. Ship one artifact.
|
|
132
135
|
test_files: []
|