jekyll-favicon 0.2.6 → 1.0.0.pre.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.devcontainer/Dockerfile +20 -0
- data/.devcontainer/devcontainer.json +42 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +10 -13
- data/.github/PULL_REQUEST_TEMPLATE.md +11 -9
- data/.github/workflows/gem-push.yml +40 -0
- data/.github/workflows/test.yml +38 -0
- data/.gitignore +4 -0
- data/.reek.yml +25 -0
- data/.vscode/launch.json +16 -0
- data/.vscode/settings.json +7 -0
- data/.vscode/tasks.json +15 -0
- data/CHANGELOG.md +42 -0
- data/Gemfile +3 -1
- data/README.md +80 -20
- data/Rakefile +9 -7
- data/bin/console +1 -0
- data/bin/debug +22 -0
- data/config/jekyll/favicon.yml +115 -0
- data/config/jekyll/favicon/static_file.yml +3 -0
- data/config/jekyll/favicon/static_file/convertible.yml +42 -0
- data/config/jekyll/favicon/static_file/mutable.yml +22 -0
- data/config/jekyll/favicon/static_file/referenceable.yml +15 -0
- data/config/jekyll/favicon/static_file/sourceable.yml +3 -0
- data/config/jekyll/favicon/static_file/taggable.yml +22 -0
- data/jekyll-favicon.gemspec +24 -24
- data/lib/jekyll-favicon.rb +7 -16
- data/lib/jekyll/favicon.rb +19 -16
- data/lib/jekyll/favicon/configuration.rb +73 -0
- data/lib/jekyll/favicon/configuration/defaults.rb +49 -0
- data/lib/jekyll/favicon/generator.rb +10 -74
- data/lib/jekyll/favicon/hooks.rb +12 -10
- data/lib/jekyll/favicon/static_data_file.rb +17 -0
- data/lib/jekyll/favicon/static_file.rb +97 -0
- data/lib/jekyll/favicon/static_file/convertible.rb +121 -0
- data/lib/jekyll/favicon/static_file/mutable.rb +81 -0
- data/lib/jekyll/favicon/static_file/referenceable.rb +22 -0
- data/lib/jekyll/favicon/static_file/sourceable.rb +73 -0
- data/lib/jekyll/favicon/static_file/taggable.rb +53 -0
- data/lib/jekyll/favicon/static_graphic_file.rb +21 -0
- data/lib/jekyll/favicon/tag.rb +14 -17
- data/lib/jekyll/favicon/utils.rb +43 -0
- data/lib/jekyll/favicon/utils/configuration/compact.rb +58 -0
- data/lib/jekyll/favicon/utils/configuration/merge.rb +70 -0
- data/lib/jekyll/favicon/utils/configuration/patch.rb +49 -0
- data/lib/jekyll/favicon/utils/convert.rb +39 -0
- data/lib/jekyll/favicon/utils/tag.rb +70 -0
- data/lib/jekyll/favicon/version.rb +3 -1
- metadata +69 -67
- data/.rubocop.yml +0 -5
- data/.ruby-version +0 -1
- data/.travis.yml +0 -21
- data/Gemfile.lock +0 -97
- data/lib/browserconfig.rb +0 -54
- data/lib/hash.rb +0 -12
- data/lib/image.rb +0 -33
- data/lib/jekyll/favicon/config/defaults.yml +0 -54
- data/lib/jekyll/favicon/icon.rb +0 -73
- data/lib/jekyll/favicon/metadata.rb +0 -12
- data/lib/jekyll/favicon/templates/chrome.html.erb +0 -5
- data/lib/jekyll/favicon/templates/classic.html.erb +0 -8
- data/lib/jekyll/favicon/templates/ie.html.erb +0 -4
- data/lib/jekyll/favicon/templates/safari.html.erb +0 -8
- data/lib/string.rb +0 -14
- data/lib/webmanifest.rb +0 -30
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "yaml"
|
4
|
+
|
5
|
+
module Jekyll
|
6
|
+
module Favicon
|
7
|
+
ROOT = Pathname.new File.dirname(File.dirname(File.dirname(File.dirname(__dir__))))
|
8
|
+
|
9
|
+
module Configuration
|
10
|
+
# Create configurable for include
|
11
|
+
module Defaults
|
12
|
+
def self.included(base)
|
13
|
+
*modules, class_or_module_name = base_name_to_parts base.name
|
14
|
+
method_name = "#{class_or_module_name}_defaults"
|
15
|
+
define_defaults base, method_name do
|
16
|
+
Defaults.load_defaults(*modules, class_or_module_name)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.load_defaults(*parts)
|
21
|
+
load_file "config", *parts
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.load_file(*parts)
|
25
|
+
path = Favicon::ROOT.join(*parts).to_s
|
26
|
+
path = "#{path}.yml"
|
27
|
+
YAML.load_file path
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.define_defaults(base, method_name, &block)
|
31
|
+
base.define_singleton_method("defaults", &block)
|
32
|
+
define_method(method_name, &block)
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.base_name_to_parts(name)
|
36
|
+
name.split("::").collect do |module_or_class|
|
37
|
+
camelcase_to_snakecase module_or_class
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.camelcase_to_snakecase(camelcase)
|
42
|
+
camelcase.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
43
|
+
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
44
|
+
.downcase
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -1,81 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "jekyll/plugin"
|
4
|
+
require "jekyll/generator"
|
5
|
+
require "jekyll/favicon"
|
6
|
+
|
1
7
|
module Jekyll
|
2
8
|
module Favicon
|
3
|
-
#
|
9
|
+
# New generator that creates all the stastic icons and metadata files
|
4
10
|
class Generator < Jekyll::Generator
|
5
|
-
priority :high
|
6
|
-
|
7
|
-
attr_accessor :template
|
8
|
-
|
9
11
|
def generate(site)
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
generate_icons && generate_metadata
|
14
|
-
else
|
15
|
-
Jekyll.logger.warn 'Jekyll::Favicon: Missing ' \
|
16
|
-
"#{Favicon.config['source']}, not generating " \
|
17
|
-
'favicons.'
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def clean
|
22
|
-
return unless @template
|
23
|
-
@template.close
|
24
|
-
@template.unlink
|
25
|
-
end
|
26
|
-
|
27
|
-
private
|
28
|
-
|
29
|
-
def source_path(path = nil)
|
30
|
-
File.join(*[@site.source, path].compact)
|
31
|
-
end
|
32
|
-
|
33
|
-
def favicon_tempfile(source)
|
34
|
-
tempfile = Tempfile.new(['favicon-template', '.png'])
|
35
|
-
options = { background: 'none' }
|
36
|
-
if source.svg?
|
37
|
-
options[:density] = Favicon.config['svg']['density']
|
38
|
-
options[:resize] = Favicon.config['svg']['dimensions']
|
39
|
-
elsif source.png?
|
40
|
-
options[:resize] = Favicon.config['png']['dimensions']
|
41
|
-
end
|
42
|
-
Image.convert source, tempfile.path, options
|
43
|
-
tempfile
|
44
|
-
end
|
45
|
-
|
46
|
-
def generate_icons
|
47
|
-
@site.static_files.push ico_icon
|
48
|
-
@site.static_files.push(*png_icons)
|
49
|
-
end
|
50
|
-
|
51
|
-
def ico_icon
|
52
|
-
target = Favicon.config['ico']['target']
|
53
|
-
Icon.new @site, Favicon.config['source'], @template.path, target
|
54
|
-
end
|
55
|
-
|
56
|
-
def png_icons
|
57
|
-
Favicon.config.deep_find('sizes').uniq.collect do |size|
|
58
|
-
target = File.join Favicon.config['path'], "favicon-#{size}.png"
|
59
|
-
Icon.new @site, Favicon.config['source'], @template.path, target
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def generate_metadata
|
64
|
-
@site.pages.push metadata Browserconfig.new,
|
65
|
-
Favicon.config['ie']['browserconfig']
|
66
|
-
@site.pages.push metadata Webmanifest.new,
|
67
|
-
Favicon.config['chrome']['manifest']
|
68
|
-
end
|
69
|
-
|
70
|
-
def metadata(document, config)
|
71
|
-
page = Metadata.new @site, @site.source,
|
72
|
-
File.dirname(config['target']),
|
73
|
-
File.basename(config['target'])
|
74
|
-
favicon_path = File.join (@site.baseurl || ''), Favicon.config['path']
|
75
|
-
document.load source_path(config['source']), config, favicon_path
|
76
|
-
page.content = document.dump
|
77
|
-
page.data = { 'layout' => nil }
|
78
|
-
page
|
12
|
+
Favicon.assets(site)
|
13
|
+
.select(&:generable?)
|
14
|
+
.each { |asset| site.static_files << asset }
|
79
15
|
end
|
80
16
|
end
|
81
17
|
end
|
data/lib/jekyll/favicon/hooks.rb
CHANGED
@@ -1,14 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "jekyll/hooks"
|
4
|
+
|
1
5
|
Jekyll::Hooks.register :site, :after_init do |site|
|
2
|
-
Jekyll::Favicon.
|
3
|
-
|
4
|
-
site.config[
|
5
|
-
|
6
|
-
|
7
|
-
|
6
|
+
static_files = Jekyll::Favicon.assets(site)
|
7
|
+
.uniq(&:path)
|
8
|
+
excludes = site.config["exclude"]
|
9
|
+
static_files.each do |static_file|
|
10
|
+
source = static_file.source_relative_path
|
11
|
+
excludes << source and next if static_file.generable?
|
8
12
|
|
9
|
-
Jekyll
|
10
|
-
|
11
|
-
generator.is_a? Jekyll::Favicon::Generator
|
13
|
+
Jekyll.logger.warn Jekyll::Favicon,
|
14
|
+
"Missing #{source}, not generating favicons."
|
12
15
|
end
|
13
|
-
favicon_generators.each(&:clean)
|
14
16
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "jekyll/favicon/static_file"
|
4
|
+
require "jekyll/favicon/static_file/mutable"
|
5
|
+
|
6
|
+
module Jekyll
|
7
|
+
module Favicon
|
8
|
+
# StaticFile extension for data exchange formats
|
9
|
+
class StaticDataFile < StaticFile
|
10
|
+
include StaticFile::Mutable
|
11
|
+
|
12
|
+
def generable?
|
13
|
+
true
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pathname"
|
4
|
+
require "forwardable"
|
5
|
+
require "jekyll/static_file"
|
6
|
+
require "jekyll/favicon/static_file/sourceable"
|
7
|
+
require "jekyll/favicon/static_file/taggable"
|
8
|
+
require "jekyll/favicon/static_file/referenceable"
|
9
|
+
require "jekyll/favicon/utils"
|
10
|
+
require "jekyll/favicon/configuration"
|
11
|
+
|
12
|
+
module Jekyll
|
13
|
+
module Favicon
|
14
|
+
# Class for static files from with spec dictionary
|
15
|
+
# Modify source from spec source
|
16
|
+
# Enable tags from spec tags
|
17
|
+
# Enable refer
|
18
|
+
class StaticFile < Jekyll::StaticFile
|
19
|
+
include StaticFile::Sourceable
|
20
|
+
include StaticFile::Taggable
|
21
|
+
include StaticFile::Referenceable
|
22
|
+
|
23
|
+
attr_reader :spec, :site
|
24
|
+
|
25
|
+
def initialize(site, spec = {})
|
26
|
+
raise StandardError unless spec.include? "name"
|
27
|
+
|
28
|
+
@spec = spec
|
29
|
+
spec_dir, spec_name = File.split spec_relative_path
|
30
|
+
super site, site.source, spec_dir, spec_name
|
31
|
+
end
|
32
|
+
|
33
|
+
def generable?
|
34
|
+
sourceable?
|
35
|
+
end
|
36
|
+
|
37
|
+
def taggable?
|
38
|
+
generable? && super
|
39
|
+
end
|
40
|
+
|
41
|
+
def patch(configuration)
|
42
|
+
taggable_patch spec_patch configuration
|
43
|
+
end
|
44
|
+
|
45
|
+
def href
|
46
|
+
Pathname.new("/")
|
47
|
+
.join(*[site.baseurl, url].compact)
|
48
|
+
.to_s
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def spec_patch(configuration)
|
54
|
+
Utils.patch configuration do |value|
|
55
|
+
case value
|
56
|
+
when :site_dir then site_dir
|
57
|
+
when :background then site_background
|
58
|
+
when :href then href
|
59
|
+
else value
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def site_dir
|
65
|
+
site_configuration.fetch("dir", ".")
|
66
|
+
end
|
67
|
+
|
68
|
+
def site_background
|
69
|
+
site_configuration.fetch("background", "transparent")
|
70
|
+
end
|
71
|
+
|
72
|
+
def site_configuration
|
73
|
+
Configuration.merged site
|
74
|
+
end
|
75
|
+
|
76
|
+
def spec_relative_path
|
77
|
+
spec_relative_pathname.cleanpath
|
78
|
+
end
|
79
|
+
|
80
|
+
def spec_relative_pathname
|
81
|
+
return spec_pathname if spec_pathname.relative?
|
82
|
+
|
83
|
+
pathname.relative_path_from "/"
|
84
|
+
end
|
85
|
+
|
86
|
+
def spec_pathname
|
87
|
+
Pathname.new(site_dir)
|
88
|
+
.join(*spec_dir_name)
|
89
|
+
end
|
90
|
+
|
91
|
+
def spec_dir_name
|
92
|
+
spec.values_at("dir", "name")
|
93
|
+
.compact
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "jekyll/favicon/configuration/defaults"
|
4
|
+
require "jekyll/favicon/utils"
|
5
|
+
|
6
|
+
module Jekyll
|
7
|
+
module Favicon
|
8
|
+
class StaticFile < Jekyll::StaticFile
|
9
|
+
# Create static file based on a source file
|
10
|
+
module Convertible
|
11
|
+
include Configuration::Defaults
|
12
|
+
|
13
|
+
def convertible?
|
14
|
+
convert.any? || convert_allow_empty?
|
15
|
+
end
|
16
|
+
|
17
|
+
def convert
|
18
|
+
convert_defaults = convertible_defaults.dig File.extname(path), @extname
|
19
|
+
convert_normalized = convert_normalize convert_spec
|
20
|
+
convert_consolidated = Utils.merge convert_defaults, convert_normalized
|
21
|
+
patch convert_patch(convert_consolidated || {})
|
22
|
+
end
|
23
|
+
|
24
|
+
def convertible_patch(configuration)
|
25
|
+
Utils.patch configuration do |value|
|
26
|
+
case value
|
27
|
+
when :sizes then sizes.join " "
|
28
|
+
else value
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def sizes
|
34
|
+
if (match = Utils.name_to_size(name)) then [match[1]]
|
35
|
+
elsif (define = Utils.define_to_size(convert_spec["define"])) then define
|
36
|
+
elsif (resize = convert_spec["resize"]) then [resize]
|
37
|
+
elsif (scale = convert_spec["scale"]) then [scale]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Jekyll::StaticFile method
|
42
|
+
# asks if dest mtime is older than source mtime after original modified?
|
43
|
+
def modified?
|
44
|
+
super || self.class.mtimes.fetch(href, -1) < mtime
|
45
|
+
end
|
46
|
+
|
47
|
+
# Jekyll::StaticFile method
|
48
|
+
# adds dest mtime to list after original write
|
49
|
+
def write(dest)
|
50
|
+
super(dest) && self.class.mtimes[href] = mtime
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
# Jekyll::StaticFile method
|
56
|
+
# add file creation instead of copying
|
57
|
+
def copy_file(dest_path)
|
58
|
+
case @extname
|
59
|
+
when ".svg" then super(dest_path)
|
60
|
+
when ".ico", ".png"
|
61
|
+
Utils.convert path, dest_path, convert
|
62
|
+
else Jekyll.logger.warn "Jekyll::Favicon: Can't generate " \
|
63
|
+
" #{dest_path}. Extension not supported."
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def convert_allow_empty?
|
68
|
+
@extname == ".svg" && @extname == File.extname(path)
|
69
|
+
end
|
70
|
+
|
71
|
+
def convert_spec
|
72
|
+
spec.fetch "convert", {}
|
73
|
+
end
|
74
|
+
|
75
|
+
def convertible_keys
|
76
|
+
convertible_defaults["defaults"].keys
|
77
|
+
end
|
78
|
+
|
79
|
+
def convert_normalize(options)
|
80
|
+
return {} unless options
|
81
|
+
|
82
|
+
Utils.slice_and_compact options, convertible_keys
|
83
|
+
end
|
84
|
+
|
85
|
+
def convert_patch(options)
|
86
|
+
patched_options = convert_patch_options options
|
87
|
+
Utils.slice_and_compact patched_options, convertible_keys
|
88
|
+
end
|
89
|
+
|
90
|
+
def convert_patch_options(options)
|
91
|
+
%w[density extent].each_with_object(options) do |name, memo|
|
92
|
+
method = "convert_patch_option_#{name}".to_sym
|
93
|
+
memo[name] = send(method, options[name])
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def convert_patch_option_density(density)
|
98
|
+
case density
|
99
|
+
when :max
|
100
|
+
length = sizes.collect { |size| size.split("x").collect(&:to_i) }
|
101
|
+
.flatten
|
102
|
+
.max
|
103
|
+
length * 3
|
104
|
+
else density
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def convert_patch_option_extent(extent)
|
109
|
+
case extent
|
110
|
+
when :auto
|
111
|
+
if (size = sizes.first)
|
112
|
+
width, height = size.split "x"
|
113
|
+
size if width != height
|
114
|
+
end
|
115
|
+
else extent
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rexml/document"
|
4
|
+
require "jekyll/favicon/utils"
|
5
|
+
require "jekyll/favicon/static_graphic_file"
|
6
|
+
|
7
|
+
module Jekyll
|
8
|
+
module Favicon
|
9
|
+
class StaticFile < Jekyll::StaticFile
|
10
|
+
# Create static file based on a source file
|
11
|
+
module Mutable
|
12
|
+
def mutable?
|
13
|
+
mutation.any? || super
|
14
|
+
end
|
15
|
+
|
16
|
+
def mutation
|
17
|
+
refers = case @extname
|
18
|
+
when ".xml"
|
19
|
+
mutation_refers.select { |refer| refer.key? "browserconfig" }
|
20
|
+
else
|
21
|
+
mutation_refers.collect { |refer| refer["webmanifest"] }
|
22
|
+
.compact
|
23
|
+
end
|
24
|
+
patch(Utils.merge(*refers) || {})
|
25
|
+
end
|
26
|
+
|
27
|
+
# overrides Jekyll::StaticFile method
|
28
|
+
def mtime
|
29
|
+
return super if File.file? path
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
# overrides Jekyll::StaticFile method
|
35
|
+
def copy_file(dest_path)
|
36
|
+
# return unless mutable?
|
37
|
+
# return super(dest_path) unless mutation.any?
|
38
|
+
|
39
|
+
File.write dest_path, mutated_content
|
40
|
+
end
|
41
|
+
|
42
|
+
def mutated_content
|
43
|
+
case @extname
|
44
|
+
when ".json", ".webmanifest", ".manifest" then mutated_content_json
|
45
|
+
when ".xml" then mutated_content_xml
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def mutated_content_json
|
50
|
+
mutated = Jekyll::Utils.deep_merge_hashes (mutable || {}), mutation
|
51
|
+
JSON.pretty_generate mutated
|
52
|
+
end
|
53
|
+
|
54
|
+
def mutated_content_xml
|
55
|
+
mutated = Utils.mutate_element (mutable || REXML::Document.new), mutation
|
56
|
+
output = +""
|
57
|
+
mutated.write output
|
58
|
+
output
|
59
|
+
end
|
60
|
+
|
61
|
+
def mutable
|
62
|
+
return unless File.file? path
|
63
|
+
|
64
|
+
content = File.read path
|
65
|
+
case File.extname path
|
66
|
+
when ".xml" then REXML::Document.new content
|
67
|
+
else JSON.parse content
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def mutation_refers
|
72
|
+
site.static_files
|
73
|
+
.select { |static_file| static_file.is_a? StaticFile }
|
74
|
+
.select(&:referenceable?)
|
75
|
+
.collect(&:refer)
|
76
|
+
.flatten
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|