jekyll-favicon 0.2.9 → 1.0.0.pre.1

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.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/.devcontainer/Dockerfile +20 -0
  3. data/.devcontainer/devcontainer.json +35 -0
  4. data/.github/PULL_REQUEST_TEMPLATE.md +4 -4
  5. data/.github/workflows/gem-push.yml +3 -3
  6. data/.github/workflows/test.yml +38 -0
  7. data/.gitignore +5 -0
  8. data/CHANGELOG.md +21 -0
  9. data/Gemfile +2 -0
  10. data/README.md +74 -24
  11. data/Rakefile +9 -7
  12. data/bin/console +1 -0
  13. data/config/jekyll/favicon.yml +115 -0
  14. data/config/jekyll/favicon/static_file.yml +3 -0
  15. data/config/jekyll/favicon/static_file/convertible.yml +42 -0
  16. data/config/jekyll/favicon/static_file/mutable.yml +22 -0
  17. data/config/jekyll/favicon/static_file/referenceable.yml +15 -0
  18. data/config/jekyll/favicon/static_file/sourceable.yml +3 -0
  19. data/config/jekyll/favicon/static_file/taggable.yml +22 -0
  20. data/gemfiles/jekyll36.gemfile +6 -0
  21. data/gemfiles/jekyll37.gemfile +6 -0
  22. data/gemfiles/jekyll38.gemfile +6 -0
  23. data/gemfiles/jekyll39.gemfile +6 -0
  24. data/gemfiles/jekyll40.gemfile +6 -0
  25. data/gemfiles/jekyll41.gemfile +6 -0
  26. data/gemfiles/jekyll42.gemfile +6 -0
  27. data/jekyll-favicon.gemspec +8 -8
  28. data/lib/jekyll-favicon.rb +7 -14
  29. data/lib/jekyll/favicon.rb +19 -13
  30. data/lib/jekyll/favicon/configuration.rb +73 -0
  31. data/lib/jekyll/favicon/configuration/defaults.rb +49 -0
  32. data/lib/jekyll/favicon/generator.rb +11 -84
  33. data/lib/jekyll/favicon/hooks.rb +12 -10
  34. data/lib/jekyll/favicon/static_data_file.rb +17 -0
  35. data/lib/jekyll/favicon/static_file.rb +97 -0
  36. data/lib/jekyll/favicon/static_file/convertible.rb +118 -0
  37. data/lib/jekyll/favicon/static_file/mutable.rb +81 -0
  38. data/lib/jekyll/favicon/static_file/referenceable.rb +22 -0
  39. data/lib/jekyll/favicon/static_file/sourceable.rb +73 -0
  40. data/lib/jekyll/favicon/static_file/taggable.rb +59 -0
  41. data/lib/jekyll/favicon/static_graphic_file.rb +21 -0
  42. data/lib/jekyll/favicon/tag.rb +14 -16
  43. data/lib/jekyll/favicon/utils.rb +24 -0
  44. data/lib/jekyll/favicon/utils/configuration/compact.rb +61 -0
  45. data/lib/jekyll/favicon/utils/configuration/merge.rb +63 -0
  46. data/lib/jekyll/favicon/utils/configuration/patch.rb +48 -0
  47. data/lib/jekyll/favicon/utils/convert.rb +42 -0
  48. data/lib/jekyll/favicon/utils/tag.rb +54 -0
  49. data/lib/jekyll/favicon/version.rb +3 -1
  50. metadata +71 -73
  51. data/.rubocop.yml +0 -5
  52. data/.ruby-version +0 -1
  53. data/.travis.yml +0 -21
  54. data/Gemfile.lock +0 -97
  55. data/lib/browserconfig.rb +0 -54
  56. data/lib/hash.rb +0 -12
  57. data/lib/image.rb +0 -33
  58. data/lib/jekyll/favicon/config/defaults.yml +0 -55
  59. data/lib/jekyll/favicon/icon.rb +0 -73
  60. data/lib/jekyll/favicon/metadata.rb +0 -12
  61. data/lib/jekyll/favicon/templates/chrome.html.erb +0 -6
  62. data/lib/jekyll/favicon/templates/classic.html.erb +0 -8
  63. data/lib/jekyll/favicon/templates/ie.html.erb +0 -4
  64. data/lib/jekyll/favicon/templates/safari.html.erb +0 -8
  65. data/lib/string.rb +0 -14
  66. data/lib/webmanifest.rb +0 -30
@@ -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.merge site.config['favicon']
3
- favicon_config = Jekyll::Favicon.config
4
- site.config['exclude'] << favicon_config['source']
5
- site.config['exclude'] << favicon_config['chrome']['manifest']['source']
6
- site.config['exclude'] << favicon_config['ie']['browserconfig']['source']
7
- end
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::Hooks.register :site, :post_write do |site|
10
- favicon_generators = site.generators.select do |generator|
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
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'jekyll/favicon/configuration/defaults'
4
+
5
+ module Jekyll
6
+ module Favicon
7
+ class StaticFile < Jekyll::StaticFile
8
+ # Add reference to a static file
9
+ module Referenceable
10
+ include Configuration::Defaults
11
+
12
+ def referenceable?
13
+ refer.any?
14
+ end
15
+
16
+ def refer
17
+ patch spec.fetch('refer', [])
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,73 @@
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
+ # Add source to a static file
10
+ module Sourceable
11
+ include Configuration::Defaults
12
+
13
+ def sourceable?
14
+ source.any? && File.file?(path)
15
+ end
16
+
17
+ def source
18
+ Utils.merge sourceable_defaults, source_site, source_asset
19
+ end
20
+
21
+ # overrides Jekyll::StaticFile method
22
+ def path
23
+ File.join(*[@base, source_relative_path].compact)
24
+ end
25
+
26
+ def source_relative_path
27
+ source_relative_pathname.to_s
28
+ end
29
+
30
+ def self.source_normalize(options)
31
+ case options
32
+ when String
33
+ source_dir, source_name = File.split options
34
+ { 'dir' => source_dir, 'name' => source_name }
35
+ when Hash
36
+ Utils.compact options
37
+ else {}
38
+ end
39
+ end
40
+
41
+ def self.source_filter(options)
42
+ options.fetch 'source', {}
43
+ end
44
+
45
+ private
46
+
47
+ def source_relative_pathname
48
+ Pathname.new(source['dir'])
49
+ .join(source['name'])
50
+ .cleanpath
51
+ end
52
+
53
+ def source_defaults
54
+ sourceable_defaults
55
+ end
56
+
57
+ def source_site
58
+ site_config = Configuration.merged @site
59
+ config = Sourceable.source_filter site_config
60
+ Sourceable.source_normalize config
61
+ end
62
+
63
+ def source_spec
64
+ Sourceable.source_filter spec
65
+ end
66
+
67
+ def source_asset
68
+ Sourceable.source_normalize source_spec
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rexml/document'
4
+ require 'jekyll/favicon/configuration/defaults'
5
+ require 'jekyll/favicon/utils'
6
+
7
+ module Jekyll
8
+ module Favicon
9
+ class StaticFile < Jekyll::StaticFile
10
+ # Add tags to favicon's static files
11
+ module Taggable
12
+ include Configuration::Defaults
13
+
14
+ def taggable?
15
+ tags.any?
16
+ end
17
+
18
+ def tags
19
+ tag_spec.collect do |options|
20
+ tag_name, tag_options = options.first
21
+ tag_defaults = taggable_defaults[tag_name]
22
+ tag_attributes = tag_defaults.merge tag_options
23
+ tag_build tag_name, patch(tag_attributes)
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def tag_spec
30
+ spec.fetch 'tag', []
31
+ end
32
+
33
+ # :reek:UtilityFunction
34
+ def tag_build(name, attributes = {})
35
+ config = attributes.transform_keys { |key| "_#{key}" }
36
+ Jekyll::Favicon::Utils.build_element name, nil, config
37
+ end
38
+
39
+ def mimetype
40
+ mappings = {
41
+ '.ico' => 'image/x-icon',
42
+ '.png' => 'image/png',
43
+ '.svg' => 'image/svg+xml'
44
+ }
45
+ mappings[extname]
46
+ end
47
+
48
+ def taggable_patch(configuration)
49
+ Favicon::Utils.patch configuration do |value|
50
+ case value
51
+ when :mime then mimetype
52
+ else value
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end