favicon_factory 0.1.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 +7 -0
- data/exe/favicon_factory +5 -0
- data/lib/favicon_factory/version.rb +5 -0
- data/lib/favicon_factory.rb +190 -0
- metadata +94 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e4c019833e1b1397a11142ee88f5ea2c9924aeb6c101316898babdd09ec526bb
|
4
|
+
data.tar.gz: b242b7a4575f87eb36047f9986481d8064b523fad955693613c85e41e618057a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 91e5b2c1db12ebdada6679e6d07452ad53acf26970de15e9ee3120806fc1bd6468b54e31a9146913f9c40b23e6569decdfbe8ef220d4f40a3cac5c9f9e239259
|
7
|
+
data.tar.gz: afa68fb6c33b90cca3a358872f48c77574ca3ac6570ebd46faedd6f527f5c83600919dbf4f61c77264a4d4ec8efa833f7da08259b5745777a72d1a646f4b01ab
|
data/exe/favicon_factory
ADDED
@@ -0,0 +1,190 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "favicon_factory/version"
|
4
|
+
require "mini_magick"
|
5
|
+
require "tty/which"
|
6
|
+
require "tty/option"
|
7
|
+
|
8
|
+
module FaviconFactory
|
9
|
+
SVG_DENSITY = 1_000
|
10
|
+
|
11
|
+
Params = Data.define(:favicon_svg, :background) do
|
12
|
+
def dir
|
13
|
+
File.dirname(favicon_svg)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
PngParams = Data.define(:favicon_svg, :background, :size) do
|
18
|
+
def self.from_params(size, params)
|
19
|
+
new(**params.to_h, size: size)
|
20
|
+
end
|
21
|
+
|
22
|
+
def dir
|
23
|
+
File.dirname(favicon_svg)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class Command
|
28
|
+
include TTY::Option
|
29
|
+
|
30
|
+
usage do
|
31
|
+
program "favicon_factory"
|
32
|
+
no_command
|
33
|
+
|
34
|
+
desc <<~DESC
|
35
|
+
`favicon_factory` generates from an SVG the minimal set of icons needed by modern browsers.
|
36
|
+
|
37
|
+
The source SVG is ideal for [modern browsers](https://caniuse.com/link-icon-svg). And it may contain a `<style>` tag with `@media (prefers-color-scheme: dark)` to support light/dark themes, which is ignored when generating favicons.
|
38
|
+
|
39
|
+
Icons will be generated in the same folder as the source SVG unless already existing:
|
40
|
+
|
41
|
+
- `favicon.ico` (32x32) for legacy browsers; serve it from `/favicon.ico` because tools, like RSS readers, just look there.
|
42
|
+
- `apple-touch-icon.png` (180x180) for Apple devices when adding a webpage to the home screen; a background and a padding around the icon is applied to make it look pretty.
|
43
|
+
- `manifest.webmanifest` that includes `icon-192.png` and `icon-512.png` for Android devices; the former for display on the home screen, and the latter for the splash screen while the PWA is loading.
|
44
|
+
DESC
|
45
|
+
|
46
|
+
example "favicon_factory path/to/favicon.svg"
|
47
|
+
example "favicon_factory --background red path/to/favicon.svg"
|
48
|
+
example "favicon_factory --background #000000 path/to/favicon.svg"
|
49
|
+
end
|
50
|
+
|
51
|
+
argument :favicon_svg do
|
52
|
+
name "favicon_svg"
|
53
|
+
desc "Path to the favicon.svg"
|
54
|
+
end
|
55
|
+
|
56
|
+
option :background do
|
57
|
+
short "-b"
|
58
|
+
long "--background string"
|
59
|
+
default "white"
|
60
|
+
desc "Background color for apple-touch-icon.png"
|
61
|
+
end
|
62
|
+
|
63
|
+
flag :help do
|
64
|
+
short "-h"
|
65
|
+
long "--help"
|
66
|
+
desc "Print usage"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
class Cli
|
71
|
+
def self.call
|
72
|
+
exit new(ARGV, $stderr).call
|
73
|
+
end
|
74
|
+
|
75
|
+
attr_reader :stderr
|
76
|
+
|
77
|
+
def initialize(argv, stderr)
|
78
|
+
@argv = argv
|
79
|
+
@stderr = stderr
|
80
|
+
end
|
81
|
+
|
82
|
+
def call
|
83
|
+
stderr.puts "imagemagick v7 not found, please install for best results" unless MiniMagick.imagemagick7?
|
84
|
+
stderr.puts "inkscape not found, install inkscape for best results" unless TTY::Which.which("inkscape")
|
85
|
+
|
86
|
+
params, status = parse(@argv)
|
87
|
+
return status if status >= 0
|
88
|
+
|
89
|
+
[
|
90
|
+
Thread.new { create("favicon.ico", params) },
|
91
|
+
Thread.new { create("icon-192.png", PngParams.from_params(192, params)) },
|
92
|
+
Thread.new { create("icon-512.png", PngParams.from_params(512, params)) },
|
93
|
+
Thread.new { create("apple-touch-icon.png", params) },
|
94
|
+
Thread.new { create("manifest.webmanifest", params) }
|
95
|
+
]
|
96
|
+
.each(&:join)
|
97
|
+
|
98
|
+
stderr.puts <<~TEXT
|
99
|
+
Info: Add the following to the `<head>`
|
100
|
+
<!-- favicons generated with the favicon_factory gem -->
|
101
|
+
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
|
102
|
+
<link rel="icon" href="/favicon.ico" sizes="32x32">
|
103
|
+
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
|
104
|
+
<link rel="manifest" href="/manifest.webmanifest">
|
105
|
+
TEXT
|
106
|
+
|
107
|
+
0
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
|
112
|
+
def parse(argv)
|
113
|
+
command = Command.new.parse(argv)
|
114
|
+
params = command.params
|
115
|
+
return exit_message(0, command.help) if params.fetch(:help) == true
|
116
|
+
return exit_message(1, params.errors.summary) if params.errors.any?
|
117
|
+
|
118
|
+
params = params.to_h
|
119
|
+
favicon_svg = params.fetch(:favicon_svg)
|
120
|
+
return exit_message(1, "Error: #{favicon_svg} does not end with .svg") unless favicon_svg.end_with?(".svg")
|
121
|
+
return exit_message(1, "Error: #{favicon_svg} does not exist") unless File.exist?(favicon_svg)
|
122
|
+
|
123
|
+
[Params.new(favicon_svg: favicon_svg, background: params.fetch(:background)), -1]
|
124
|
+
end
|
125
|
+
|
126
|
+
def exit_message(status, message)
|
127
|
+
stderr.puts message
|
128
|
+
[nil, status]
|
129
|
+
end
|
130
|
+
|
131
|
+
def create(name, params)
|
132
|
+
path = File.join(params.dir, name)
|
133
|
+
if File.exist?(path)
|
134
|
+
stderr.puts "Info: Skipping #{path} because it already exists"
|
135
|
+
return
|
136
|
+
end
|
137
|
+
|
138
|
+
stderr.puts "Info: Generating #{path}"
|
139
|
+
create_by_name.fetch(name).call(path, params)
|
140
|
+
end
|
141
|
+
|
142
|
+
def create_by_name
|
143
|
+
{
|
144
|
+
"favicon.ico" => method(:ico!),
|
145
|
+
"icon-192.png" => method(:png!),
|
146
|
+
"icon-512.png" => method(:png!),
|
147
|
+
"apple-touch-icon.png" => method(:touch!),
|
148
|
+
"manifest.webmanifest" => method(:manifest!)
|
149
|
+
}
|
150
|
+
end
|
151
|
+
|
152
|
+
def ico!(path, params)
|
153
|
+
MiniMagick::Tool::Convert.new do |convert|
|
154
|
+
convert.density(SVG_DENSITY).background("none")
|
155
|
+
convert << params.favicon_svg
|
156
|
+
convert.resize("32x32")
|
157
|
+
convert << path
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def png!(path, params)
|
162
|
+
MiniMagick::Tool::Convert.new do |convert|
|
163
|
+
convert.density(SVG_DENSITY).background("none")
|
164
|
+
convert << params.favicon_svg
|
165
|
+
convert.resize("#{params.size}x#{params.size}")
|
166
|
+
convert << path
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def touch!(path, params)
|
171
|
+
MiniMagick::Tool::Convert.new do |convert|
|
172
|
+
convert.density(SVG_DENSITY).background(params.background)
|
173
|
+
convert << params.favicon_svg
|
174
|
+
convert.resize("160x160").gravity("center").extent("180x180")
|
175
|
+
convert << path
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def manifest!(path, _params)
|
180
|
+
File.write(path, <<~MANIFEST)
|
181
|
+
{
|
182
|
+
"icons": [
|
183
|
+
{ "src": "/icon-192.png", "type": "image/png", "sizes": "192x192" },
|
184
|
+
{ "src": "/icon-512.png", "type": "image/png", "sizes": "512x512" }
|
185
|
+
]
|
186
|
+
}
|
187
|
+
MANIFEST
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
metadata
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: favicon_factory
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- 3v0k4
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-05-27 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: mini_magick
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.12'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4.12'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: tty-option
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.3.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.3.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: tty-which
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.5.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.5.0
|
55
|
+
description: FaviconFactory generates from an SVG the minimal set of icons needed
|
56
|
+
by modern browsers.
|
57
|
+
email:
|
58
|
+
- riccardo.odone@gmail.com
|
59
|
+
executables:
|
60
|
+
- favicon_factory
|
61
|
+
extensions: []
|
62
|
+
extra_rdoc_files: []
|
63
|
+
files:
|
64
|
+
- exe/favicon_factory
|
65
|
+
- lib/favicon_factory.rb
|
66
|
+
- lib/favicon_factory/version.rb
|
67
|
+
homepage: https://github.com/3v0k4/favicon_factory
|
68
|
+
licenses:
|
69
|
+
- MIT
|
70
|
+
metadata:
|
71
|
+
homepage_uri: https://github.com/3v0k4/favicon_factory
|
72
|
+
source_code_uri: https://github.com/3v0k4/favicon_factory
|
73
|
+
changelog_uri: https://github.com/3v0k4/favicon_factory/blob/main/CHANGELOG.md
|
74
|
+
rubygems_mfa_required: 'true'
|
75
|
+
post_install_message:
|
76
|
+
rdoc_options: []
|
77
|
+
require_paths:
|
78
|
+
- lib
|
79
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: 2.6.0
|
84
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
requirements: []
|
90
|
+
rubygems_version: 3.4.10
|
91
|
+
signing_key:
|
92
|
+
specification_version: 4
|
93
|
+
summary: Generate favicons from an SVG
|
94
|
+
test_files: []
|