fontico 0.1.1 → 0.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 +74 -20
- data/lib/fontico/builder.rb +25 -4
- data/lib/fontico/emitters/font.rb +10 -3
- data/lib/fontico/lockfile.rb +8 -2
- data/lib/fontico/manifest.rb +22 -1
- data/lib/fontico/railtie.rb +7 -1
- data/lib/fontico/version.rb +1 -1
- data/lib/fontico.rb +28 -2
- data/lib/tasks/fontico.rake +38 -29
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3ad5f56ad9c1523dbd17d2cdb07da3a2d6aac315008ebd08ba84551d125083c0
|
|
4
|
+
data.tar.gz: 207804df603f81d1da9117d5b081a73dbcf649bf882dbeb43fdec33678fcacb4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4a4bf9595c5257803d26ff2c79607d0a44b48b0c4bc7b1584ce9a71e6e61f18fd71447884eba9d9e48d296a5aec6c42ad6973b7c82e197443be02c6b1032756e
|
|
7
|
+
data.tar.gz: 3132cfd1d3a9fa3997a23ed450fa749416aac364414b883e5c65e6995b7708cbbb4155ed672de376c0089543ea3b36167cc1d93deb055e402529ca705685f030
|
data/README.md
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
```
|
|
4
|
+
╔═╗╔═╗╔╗╔╔╦╗╦╔═╗╔═╗
|
|
5
|
+
╠╣ ║ ║║║║ ║ ║║ ║ ║
|
|
6
|
+
╚ ╚═╝╝╚╝ ╩ ╩╚═╝╚═╝
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
**Name icons by intent. Source them from anywhere. Ship one artifact.**
|
|
10
|
+
|
|
11
|
+
[](https://rubygems.org/gems/fontico)
|
|
12
|
+
[](https://github.com/fireho/fontico/actions/workflows/ci.yml)
|
|
13
|
+
[](LICENSE.txt)
|
|
14
|
+
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
---
|
|
4
18
|
|
|
5
19
|
```erb
|
|
6
20
|
<%= icon "save" %> <%# Lucide %>
|
|
@@ -11,6 +25,30 @@ Name icons by intent. Source them from anywhere. Ship one artifact.
|
|
|
11
25
|
Three providers, one call. Templates never name a vendor, so re-skinning the
|
|
12
26
|
app — or surviving an upstream rename — is a diff in one file.
|
|
13
27
|
|
|
28
|
+
| | |
|
|
29
|
+
| --- | --- |
|
|
30
|
+
| **353,000 icons** | any of [Iconify's 238 sets](https://icon-sets.iconify.design/), plus your own folder |
|
|
31
|
+
| **One request** | a single sprite, 2.3KB brotli, not render-blocking |
|
|
32
|
+
| **361ms cold, 2ms warm** | measured on 35 icons across two remote providers and five local files |
|
|
33
|
+
| **No Node, no npm** | the sprite target is pure Ruby; deploys rebuild offline from the lockfile |
|
|
34
|
+
| **Also PDFs** | a real TTF for Prawn, with pinned codepoints |
|
|
35
|
+
|
|
36
|
+
## Install
|
|
37
|
+
|
|
38
|
+
```ruby
|
|
39
|
+
# Gemfile
|
|
40
|
+
gem "fontico"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
bundle install
|
|
45
|
+
$EDITOR icons.yml # the manifest, below
|
|
46
|
+
rake fontico:build
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
No JS bundle, no `package.json`, no importmap pin. Artifacts land in
|
|
50
|
+
`app/assets/builds/`, which Propshaft already serves.
|
|
51
|
+
|
|
14
52
|
## The manifest
|
|
15
53
|
|
|
16
54
|
`icons.yml`, one line per icon:
|
|
@@ -35,26 +73,25 @@ icons:
|
|
|
35
73
|
```
|
|
36
74
|
|
|
37
75
|
Like pokemon, you gotta catch 'em all.
|
|
38
|
-
Any of [Iconify's
|
|
39
|
-
|
|
76
|
+
Any of [Iconify's sets](https://icon-sets.iconify.design/) work as a provider
|
|
77
|
+
prefix. Your own SVGs go in `app/assets/icons/`, filename as slug.
|
|
78
|
+
|
|
79
|
+
A Rails engine that ships `config/icons.yml` (or `icons.yml` at its root) is
|
|
80
|
+
merged under the app's file, the same way `config/locales/` layers. Later
|
|
81
|
+
wins a name — the app always has the last word. Nested groups merge, so an
|
|
82
|
+
engine can ship `auth.google` and the app can add `auth.apple` without
|
|
83
|
+
copying the rest. `rake fontico:build` reads the same list.
|
|
40
84
|
|
|
41
85
|
## Build
|
|
42
86
|
|
|
43
87
|
```bash
|
|
44
88
|
rake fontico:build # resolve, normalise, emit
|
|
45
|
-
rake fontico:update # re-fetch
|
|
89
|
+
rake fontico:update # re-fetch bodies; codepoints stay pinned
|
|
46
90
|
```
|
|
47
91
|
|
|
48
|
-
|
|
49
|
-
no manifest, no precompile list. `rake assets:precompile` is hooked, so deploys
|
|
50
|
-
need no extra step.
|
|
51
|
-
|
|
52
|
-
That directory is gitignored in a stock Rails app, so nothing is committed from
|
|
53
|
-
it. **`icons.lock` is the thing you commit**: it holds every normalised body,
|
|
54
|
-
so a deploy rebuilds the sprite from it in milliseconds with no network access
|
|
55
|
-
and no Node.
|
|
92
|
+
`rake assets:precompile` is hooked, so deploys need no extra step.
|
|
56
93
|
|
|
57
|
-
In development you rarely type either one
|
|
94
|
+
**In development you rarely type either one.** Saving `icons.yml` — or a local
|
|
58
95
|
SVG — rebuilds the artifacts and drops the cached manifest, so the icon is live
|
|
59
96
|
on the next request: no rake, no restart. A save that only reshuffles known
|
|
60
97
|
icons costs a couple of milliseconds; a brand-new one pays its provider fetch
|
|
@@ -73,13 +110,14 @@ there — is named in red and left out; the rest of the manifest still builds.
|
|
|
73
110
|
It keeps its codepoint reserved, so fixing the entry and rebuilding brings it
|
|
74
111
|
back with the same glyph. A provider that is unreachable is still fatal.
|
|
75
112
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
provider — not one per icon.
|
|
113
|
+
Vendor icons are fetched in one batched request per provider — not one per
|
|
114
|
+
icon.
|
|
79
115
|
|
|
80
116
|
## Why there is a lockfile
|
|
81
117
|
|
|
82
|
-
`
|
|
118
|
+
`app/assets/builds/` is gitignored in a stock Rails app, so nothing is
|
|
119
|
+
committed from it. **`icons.lock` is the thing you commit.** It pins two things
|
|
120
|
+
that must not drift:
|
|
83
121
|
|
|
84
122
|
- **Codepoints**, append-only. Adding an icon must not renumber the others, or
|
|
85
123
|
every glyph in a built font moves and the committed artifact churns
|
|
@@ -88,7 +126,8 @@ provider — not one per icon.
|
|
|
88
126
|
Iconify API serves *latest*; without this an icon can silently change shape
|
|
89
127
|
between two builds of the same manifest.
|
|
90
128
|
|
|
91
|
-
|
|
129
|
+
A deploy rebuilds the sprite from it in milliseconds, with no network access
|
|
130
|
+
and no Node. Commit it.
|
|
92
131
|
|
|
93
132
|
## What happens to your SVGs
|
|
94
133
|
|
|
@@ -204,12 +243,27 @@ build names each one it dropped.
|
|
|
204
243
|
Font targets need Node, installed on demand into `~/.cache/fontico`. A manifest
|
|
205
244
|
with `targets: [sprite]` never touches it and stays pure Ruby.
|
|
206
245
|
|
|
246
|
+
## How it compares
|
|
247
|
+
|
|
248
|
+
| | vendor gems (`lucide-rails`, `heroicon`) | `iconify-icon` web component | fontico |
|
|
249
|
+
| --- | --- | --- | --- |
|
|
250
|
+
| Icon sets | one, per gem | 238 | 238, plus your own folder |
|
|
251
|
+
| Where the SVG comes from | inlined per render | fetched at runtime, per client | one build-time sprite |
|
|
252
|
+
| Requests | 0, but repeated in every response body | 1+ per icon, per visitor | 1, cached |
|
|
253
|
+
| JS required | no | yes | no |
|
|
254
|
+
| Rename-proof templates | no — `lucide_icon "pencil"` | no — `icon="lucide:pencil"` | yes — `icon "edit"` |
|
|
255
|
+
| Offline / reproducible build | yes | no | yes, via `icons.lock` |
|
|
256
|
+
| PDF | no | no | yes, TTF for Prawn |
|
|
257
|
+
|
|
207
258
|
## Status
|
|
208
259
|
|
|
209
260
|
- ✅ Manifest, resolver, preprocessor, lockfile, sprite emitter, Rails helper
|
|
210
261
|
- ✅ TTF emitter with glyph extraction, codepoint API, Prawn helpers
|
|
211
262
|
- ⏳ `woff2` — declared targets are skipped with a notice
|
|
263
|
+
- ⏳ `variant:` — accepted and ignored by the helper; see [TODO.md](TODO.md)
|
|
212
264
|
|
|
213
265
|
## License
|
|
214
266
|
|
|
215
|
-
MIT
|
|
267
|
+
MIT.
|
|
268
|
+
Icons keep their upstream licenses:
|
|
269
|
+
`icons.lock` records what you declared and shipped.
|
data/lib/fontico/builder.rb
CHANGED
|
@@ -12,11 +12,13 @@ module Fontico
|
|
|
12
12
|
Report = Struct.new(:written, :warnings, :skipped, :cached, :fetched, :pending,
|
|
13
13
|
:missing, keyword_init: true)
|
|
14
14
|
|
|
15
|
-
def initialize(manifest, root: Dir.pwd, output: "app/assets/builds",
|
|
15
|
+
def initialize(manifest, root: Dir.pwd, output: "app/assets/builds",
|
|
16
|
+
offline: false, force: false)
|
|
16
17
|
@manifest = manifest
|
|
17
18
|
@root = root
|
|
18
19
|
@output = File.join(root, output)
|
|
19
20
|
@offline = offline
|
|
21
|
+
@force = force
|
|
20
22
|
@lock = Lockfile.new(File.join(root, "icons.lock"))
|
|
21
23
|
end
|
|
22
24
|
|
|
@@ -25,11 +27,23 @@ module Fontico
|
|
|
25
27
|
cached, fetched = [], []
|
|
26
28
|
missing = {}
|
|
27
29
|
|
|
28
|
-
|
|
30
|
+
# The lock caches Iconify bodies so deploys run offline. Local files
|
|
31
|
+
# are already on disk: treating them as fresh meant editing logo.svg
|
|
32
|
+
# rebuilt nothing. Force is `rake fontico:update` — re-fetch remotes,
|
|
33
|
+
# keep the append-only codepoints.
|
|
34
|
+
stale = @manifest.icons.select { _1.local? || @force || !@lock.fresh?(_1.name, _1.source) }
|
|
29
35
|
cached = @manifest.icons.map(&:name) - stale.map(&:name)
|
|
30
36
|
|
|
31
37
|
unless stale.empty?
|
|
32
|
-
|
|
38
|
+
remote_stale = stale.reject(&:local?)
|
|
39
|
+
# Local files do not need the network. Offline is a hard fail only
|
|
40
|
+
# when a remote body has to come off the wire — which under force is
|
|
41
|
+
# every remote, lock or no lock. Saying "missing" there would be a
|
|
42
|
+
# lie: the bodies are present, force is what made them stale.
|
|
43
|
+
if @offline && remote_stale.any?
|
|
44
|
+
reason = @force ? "re-fetch #{remote_stale.size} icon(s)" : "resolve #{remote_stale.size} icon(s) missing from icons.lock"
|
|
45
|
+
raise Error, "cannot #{reason} and --offline was given"
|
|
46
|
+
end
|
|
33
47
|
|
|
34
48
|
resolver = Resolver.new(@manifest, root: @root)
|
|
35
49
|
sources = resolver.call(only: stale.map(&:name))
|
|
@@ -43,9 +57,16 @@ module Fontico
|
|
|
43
57
|
|
|
44
58
|
pre = Preprocessor.new(icon, size: @manifest.size)
|
|
45
59
|
.call(src.markup, width: src.width, height: src.height)
|
|
60
|
+
# Locals are re-read every build, so "stale" does not mean changed.
|
|
61
|
+
# Compare the stored digest to keep an untouched logo.svg counted as
|
|
62
|
+
# cached rather than reported as a fetch that never happened. A
|
|
63
|
+
# remote is judged by the wire, not the digest: under force it was
|
|
64
|
+
# genuinely re-fetched even when it came back byte-identical.
|
|
65
|
+
before = @lock.entry(icon.name)&.fetch("digest", nil)
|
|
46
66
|
@lock.store(icon.name, source: icon.source, body: pre.body,
|
|
47
67
|
multicolor: pre.multicolor, warnings: pre.warnings)
|
|
48
|
-
|
|
68
|
+
unchanged = icon.local? && @lock.entry(icon.name)["digest"] == before
|
|
69
|
+
(unchanged ? cached : fetched) << icon.name
|
|
49
70
|
end
|
|
50
71
|
end
|
|
51
72
|
|
|
@@ -26,9 +26,16 @@ module Fontico
|
|
|
26
26
|
outlines = @outliner.outlines(@build, size: @manifest.size)
|
|
27
27
|
|
|
28
28
|
glyphs = @build.map do |icon, body|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
# Never fall back to allocating here. The builder has already
|
|
30
|
+
# save!d the lock by the time it emits, so a codepoint minted now
|
|
31
|
+
# would never reach disk: the font would ship a glyph that
|
|
32
|
+
# Fontico.glyph cannot name. A nil is worse still — it reaches
|
|
33
|
+
# String.fromCodePoint as null and maps the glyph to U+0000
|
|
34
|
+
# without complaint.
|
|
35
|
+
cp = @lock.codepoint_for(icon.name)
|
|
36
|
+
raise Fontico::Error, "#{icon.name} has no codepoint in icons.lock" if cp.nil?
|
|
37
|
+
|
|
38
|
+
{ name: icon.key, codepoint: cp, svg: document(outlines[icon.name], body) }
|
|
32
39
|
end
|
|
33
40
|
|
|
34
41
|
result = @outliner.instance_variable_get(:@runner)
|
data/lib/fontico/lockfile.rb
CHANGED
|
@@ -29,7 +29,13 @@ module Fontico
|
|
|
29
29
|
@entries = data["icons"] || {}
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
# Lookup only. A missing name is nil — callers that draw a glyph must
|
|
33
|
+
# not invent a codepoint, or a typo silently becomes a .notdef.
|
|
34
|
+
def codepoint_for(name) = @codepoints[name]
|
|
35
|
+
|
|
36
|
+
# Append-only reservation. store is the production caller; tests use it
|
|
37
|
+
# to pin order without going through a full build.
|
|
38
|
+
def allocate(name)
|
|
33
39
|
@codepoints[name] ||= next_free
|
|
34
40
|
end
|
|
35
41
|
|
|
@@ -43,7 +49,7 @@ module Fontico
|
|
|
43
49
|
"warnings" => warnings,
|
|
44
50
|
"body" => body
|
|
45
51
|
}
|
|
46
|
-
|
|
52
|
+
allocate(name)
|
|
47
53
|
end
|
|
48
54
|
|
|
49
55
|
# Names present in the lock but absent from the manifest keep their
|
data/lib/fontico/manifest.rb
CHANGED
|
@@ -13,7 +13,28 @@ module Fontico
|
|
|
13
13
|
|
|
14
14
|
attr_reader :path, :defaults, :providers, :targets, :icons
|
|
15
15
|
|
|
16
|
-
def self.load(
|
|
16
|
+
def self.load(*paths)
|
|
17
|
+
paths = paths.flatten.compact.select { File.file?(_1) }
|
|
18
|
+
raise Errno::ENOENT, "icons.yml" if paths.empty?
|
|
19
|
+
|
|
20
|
+
data = paths.map { YAML.safe_load_file(_1) || {} }.reduce { |a, b| merge_data(a, b) }
|
|
21
|
+
new(data, path: paths.last)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Later overlay wins a leaf; nested groups merge so an engine can ship
|
|
25
|
+
# `auth.google` and the app can add `auth.apple` without copying.
|
|
26
|
+
def self.merge_data(base, overlay)
|
|
27
|
+
{
|
|
28
|
+
"defaults" => (base["defaults"] || {}).merge(overlay["defaults"] || {}),
|
|
29
|
+
"targets" => overlay["targets"] || base["targets"] || ["sprite"],
|
|
30
|
+
"providers" => (base["providers"] || {}).merge(overlay["providers"] || {}),
|
|
31
|
+
"icons" => deep_merge(base["icons"] || {}, overlay["icons"] || {})
|
|
32
|
+
}
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def self.deep_merge(left, right)
|
|
36
|
+
left.merge(right) { |_, a, b| a.is_a?(Hash) && b.is_a?(Hash) ? deep_merge(a, b) : b }
|
|
37
|
+
end
|
|
17
38
|
|
|
18
39
|
def initialize(data, path: nil)
|
|
19
40
|
@path = path
|
data/lib/fontico/railtie.rb
CHANGED
|
@@ -12,6 +12,12 @@ module Fontico
|
|
|
12
12
|
Fontico.root = Rails.root.to_s
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
+
# Engines' config/icons.yml under the app's icons.yml. After root: the
|
|
16
|
+
# app file is Rails.root/icons.yml, not whatever Dir.pwd was at require.
|
|
17
|
+
initializer "fontico.load_path", after: "fontico.root" do |app|
|
|
18
|
+
Fontico.load_path = Fontico.discover(app)
|
|
19
|
+
end
|
|
20
|
+
|
|
15
21
|
# Saving icons.yml — or a local SVG — rebuilds the artifacts and drops the
|
|
16
22
|
# memoized manifest, so a new icon is live on the next request with no
|
|
17
23
|
# restart and no rake. That memo is the only thing that ever needed one:
|
|
@@ -20,7 +26,7 @@ module Fontico
|
|
|
20
26
|
initializer "fontico.reloader" do |app|
|
|
21
27
|
next unless app.config.enable_reloading
|
|
22
28
|
|
|
23
|
-
watcher = app.config.file_watcher.new(
|
|
29
|
+
watcher = app.config.file_watcher.new(Fontico.load_path, Railtie.local_dirs) do
|
|
24
30
|
Fontico.reset!
|
|
25
31
|
Fontico.rebuild!
|
|
26
32
|
# Recorded rather than raised: a save that half-breaks the manifest
|
data/lib/fontico/version.rb
CHANGED
data/lib/fontico.rb
CHANGED
|
@@ -34,9 +34,35 @@ module Fontico
|
|
|
34
34
|
def root = @root ||= Dir.pwd
|
|
35
35
|
def output_dir = @output_dir ||= "app/assets/builds"
|
|
36
36
|
def manifest_path = @manifest_path ||= File.join(root, "icons.yml")
|
|
37
|
-
|
|
37
|
+
# Same shape as I18n.load_path: engines first, the app last, later wins
|
|
38
|
+
# a name. Unset, it is just the app's icons.yml (non-Rails, tests).
|
|
39
|
+
def load_path = @load_path || [manifest_path].select { File.file?(_1) }
|
|
40
|
+
|
|
41
|
+
def load_path=(paths)
|
|
42
|
+
@load_path = paths.nil? ? nil : Array(paths)
|
|
43
|
+
reset!
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def manifest = @manifest ||= Manifest.load(*load_path)
|
|
38
47
|
def sprite_file = File.join(root, output_dir, "icons.svg")
|
|
39
48
|
|
|
49
|
+
# Rails engines that ship config/icons.yml (or icons.yml at the gem
|
|
50
|
+
# root), then the app's file. The app is last on purpose.
|
|
51
|
+
def discover(app)
|
|
52
|
+
files = []
|
|
53
|
+
app.railties.each do |rt|
|
|
54
|
+
next unless rt.is_a?(Rails::Engine)
|
|
55
|
+
next if rt.is_a?(Rails::Application)
|
|
56
|
+
|
|
57
|
+
root = rt.root
|
|
58
|
+
found = %w[config/icons.yml icons.yml].map { root.join(_1) }.find { File.file?(_1.to_s) }
|
|
59
|
+
files << found.to_s if found
|
|
60
|
+
end
|
|
61
|
+
# manifest_path goes in even when absent: the dev watcher has to notice
|
|
62
|
+
# an icons.yml created after boot. Manifest.load skips what isn't there.
|
|
63
|
+
(files.select { File.file?(_1) } << manifest_path).uniq
|
|
64
|
+
end
|
|
65
|
+
|
|
40
66
|
# Inline mode embeds <symbol> definitions in the layout instead of
|
|
41
67
|
# referencing an external file — required when assets are served from a
|
|
42
68
|
# CDN, where cross-origin <use href> silently renders nothing.
|
|
@@ -85,7 +111,7 @@ module Fontico
|
|
|
85
111
|
# a reference in Ruby source never goes stale.
|
|
86
112
|
def codepoint(name)
|
|
87
113
|
cp = lockfile.codepoint_for(name.to_s)
|
|
88
|
-
raise Error, "no icon named #{name.inspect}
|
|
114
|
+
raise Error, "no icon named #{name.inspect} in icons.lock" if cp.nil?
|
|
89
115
|
|
|
90
116
|
cp
|
|
91
117
|
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
|
|
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: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- nofxx
|
|
@@ -126,7 +126,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
126
126
|
- !ruby/object:Gem::Version
|
|
127
127
|
version: '0'
|
|
128
128
|
requirements: []
|
|
129
|
-
rubygems_version: 3.6.
|
|
129
|
+
rubygems_version: 3.6.9
|
|
130
130
|
specification_version: 4
|
|
131
131
|
summary: Name icons by intent. Source them from anywhere. Ship one artifact.
|
|
132
132
|
test_files: []
|