jekyll-favicon 0.2.5 → 1.0.0.pre.1
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 +35 -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 +5 -0
- data/CHANGELOG.md +44 -0
- data/Gemfile +2 -0
- data/README.md +86 -20
- data/Rakefile +9 -7
- data/bin/console +1 -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/gemfiles/jekyll36.gemfile +6 -0
- data/gemfiles/jekyll37.gemfile +6 -0
- data/gemfiles/jekyll38.gemfile +6 -0
- data/gemfiles/jekyll39.gemfile +6 -0
- data/gemfiles/jekyll40.gemfile +6 -0
- data/gemfiles/jekyll41.gemfile +6 -0
- data/gemfiles/jekyll42.gemfile +6 -0
- data/jekyll-favicon.gemspec +9 -9
- data/lib/jekyll-favicon.rb +7 -14
- data/lib/jekyll/favicon.rb +19 -13
- data/lib/jekyll/favicon/configuration.rb +73 -0
- data/lib/jekyll/favicon/configuration/defaults.rb +49 -0
- data/lib/jekyll/favicon/generator.rb +11 -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 +118 -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 +59 -0
- data/lib/jekyll/favicon/static_graphic_file.rb +21 -0
- data/lib/jekyll/favicon/tag.rb +14 -16
- data/lib/jekyll/favicon/utils.rb +24 -0
- data/lib/jekyll/favicon/utils/configuration/compact.rb +61 -0
- data/lib/jekyll/favicon/utils/configuration/merge.rb +63 -0
- data/lib/jekyll/favicon/utils/configuration/patch.rb +48 -0
- data/lib/jekyll/favicon/utils/convert.rb +42 -0
- data/lib/jekyll/favicon/utils/tag.rb +54 -0
- data/lib/jekyll/favicon/version.rb +3 -1
- metadata +71 -66
- data/.rubocop.yml +0 -5
- 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 -74
- 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,18 @@
|
|
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
|
-
|
6
|
-
|
7
|
-
attr_accessor :template
|
8
|
-
|
11
|
+
# :reek:UtilityFunction
|
9
12
|
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
|
13
|
+
Favicon.assets(site)
|
14
|
+
.select(&:generable?)
|
15
|
+
.each { |asset| site.static_files << asset }
|
79
16
|
end
|
80
17
|
end
|
81
18
|
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['exclude']
|
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(url)
|
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,118 @@
|
|
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 = name.match(/^.*-(\d+x\d+)\..*$/)) then [match[1]]
|
35
|
+
elsif (define = convert_spec['define'])
|
36
|
+
define.split('=').last.split(',').collect { |size| [size, size].join 'x' }
|
37
|
+
elsif (resize = convert_spec['resize']) then [resize]
|
38
|
+
elsif (scale = convert_spec['scale']) then [scale]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Jekyll::StaticFile method
|
43
|
+
# asks if dest mtime is older than source mtime after original modified?
|
44
|
+
def modified?
|
45
|
+
super || self.class.mtimes[href] < mtime
|
46
|
+
end
|
47
|
+
|
48
|
+
# Jekyll::StaticFile method
|
49
|
+
# adds dest mtime to list after original write
|
50
|
+
# :reek:ControlParameter
|
51
|
+
def write(dest)
|
52
|
+
super(dest) && self.class.mtimes[href] = mtime
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
# Jekyll::StaticFile method
|
58
|
+
# add file creation instead of copying
|
59
|
+
def copy_file(dest_path)
|
60
|
+
case @extname
|
61
|
+
when '.svg' then super(dest_path)
|
62
|
+
when '.ico', '.png'
|
63
|
+
Utils.convert path, dest_path, convert
|
64
|
+
else Jekyll.logger.warn "Jekyll::Favicon: Can't generate " \
|
65
|
+
" #{dest_path}. Extension not supported."
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def convert_allow_empty?
|
70
|
+
@extname == '.svg' && @extname == File.extname(path)
|
71
|
+
end
|
72
|
+
|
73
|
+
def convert_spec
|
74
|
+
spec.fetch 'convert', {}
|
75
|
+
end
|
76
|
+
|
77
|
+
def convert_normalize(options)
|
78
|
+
return {} unless options
|
79
|
+
|
80
|
+
Utils.compact options.slice(*convertible_defaults['defaults'].keys)
|
81
|
+
end
|
82
|
+
|
83
|
+
def convert_defaults
|
84
|
+
convertible_defaults.dig File.extname(path), @extname
|
85
|
+
end
|
86
|
+
|
87
|
+
# :reek:FeatureEnvy
|
88
|
+
def convert_patch(options)
|
89
|
+
%w[density extent].each do |name|
|
90
|
+
method = "convert_patch_#{name}".to_sym
|
91
|
+
options.merge! name => send(method, options[name])
|
92
|
+
end
|
93
|
+
Utils.compact options.slice(*convertible_defaults['defaults'].keys)
|
94
|
+
end
|
95
|
+
|
96
|
+
def convert_patch_density(density)
|
97
|
+
case density
|
98
|
+
when :max
|
99
|
+
length = sizes.collect { |size| size.split('x').max }.max.to_i
|
100
|
+
length * 3
|
101
|
+
else density
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def convert_patch_extent(extent)
|
106
|
+
case extent
|
107
|
+
when :auto
|
108
|
+
if (size = sizes.first)
|
109
|
+
width, height = size.split 'x'
|
110
|
+
size if width != height
|
111
|
+
end
|
112
|
+
else extent
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
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 = String.new
|
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
|