favicon_factory 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|