jekyll-favicon 0.2.6 → 1.0.0.pre.2
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 +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
|