jekyll-picture-tag-ng 0.5.1 → 0.6.0
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 +4 -4
- data/README.md +4 -0
- data/lib/jekyll-picture-tag-ng/jekyll/picture_tag/out_image_file.rb +120 -0
- data/lib/jekyll-picture-tag-ng/jekyll/picture_tag/pics_generator.rb +29 -0
- data/lib/jekyll-picture-tag-ng/jekyll/picture_tag.rb +22 -0
- data/lib/jekyll-picture-tag-ng/jekyll/site.rb +70 -0
- data/lib/jekyll-picture-tag-ng/jekyll/static_file.rb +10 -0
- data/lib/jekyll-picture-tag-ng/jekyll.rb +4 -0
- data/lib/jekyll-picture-tag-ng/kramdown/converter.rb +83 -0
- data/lib/jekyll-picture-tag-ng/kramdown/parser.rb +27 -0
- data/lib/jekyll-picture-tag-ng/kramdown.rb +4 -0
- data/lib/jekyll-picture-tag-ng/version.rb +1 -1
- data/lib/jekyll-picture-tag-ng.rb +2 -308
- metadata +11 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9ecbda23da1dbfffd515c08c3e043b358aed63dc2aa00fb26a38278bc6d583b5
|
4
|
+
data.tar.gz: df5b90707f95f61608f73c0fcb24116a9dd3bef8a74a1c90172836f3f68abca0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 469c4de79cf10f8bafce3741be16955b1086736fa051571cda0cefe7969619b37df907e7886fa81b47014e4ef4253d3440a0a2404687b3c7072150d6a59ae7aa
|
7
|
+
data.tar.gz: cf5eebe3a10469c8abf41054f9ee8f5f41e69011e7c504f6abe37f97ef8e85904b51b40acf55c6381f675636f42444fd10c83ecdbf57745e6dc48b9a4b457e92
|
data/README.md
CHANGED
@@ -61,6 +61,7 @@ Configuration is done in the `_config.yml` of your website, under the `picture_t
|
|
61
61
|
|
62
62
|
```yaml
|
63
63
|
picture_tag_ng:
|
64
|
+
backend: imagemagick
|
64
65
|
parallel: false
|
65
66
|
threads: 16
|
66
67
|
background_color: FFFFFF
|
@@ -71,6 +72,7 @@ picture_tag_ng:
|
|
71
72
|
|
72
73
|
The example above is equivalent to the defaults.
|
73
74
|
|
75
|
+
- `backend` can be either `imagemagick` (more well-tested) or `libvips` (a lot faster but less tested)
|
74
76
|
- `background_color` is the color used to replace transparency when converting from `webp` to `jpeg`
|
75
77
|
- `picture_versions` in the simplest form, maps version names to target widths in pixels. The default configuration above produces output files 700px wide in `img/m/` and 400px wide in `img/s/`. See below for more complex forms.
|
76
78
|
- `parallel` is a boolean indicating if you want to generate the output files in parallel threads. With a website that has a lot of large pictures, I get ~30% speed improvements when generating the site locally.
|
@@ -161,6 +163,8 @@ to the following HTML :
|
|
161
163
|
|
162
164
|
#### Extra `convert` arguments
|
163
165
|
|
166
|
+
:warning: The options in this section will do nothing when used with the `libvips` backend :warning:
|
167
|
+
|
164
168
|
The `extra_convert_args` and `pre_extra_convert_args` options allow you to add any [`convert` argument](https://imagemagick.org/script/convert.php) to the image conversion processes. The `pre_extra_convert_args` will be added before the resize operation, and the `extra_convert_args` after the resize operation. These options must be either arrays of strings or a string that will be split on spaces. This can be used to add a watermark to all your pictures (see example below).
|
165
169
|
|
166
170
|
Additionally, you can set different values based on the version for both these options. In the example below, the `m` version of output pictures will be blurred :
|
@@ -0,0 +1,120 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jekyll
|
4
|
+
module PictureTag
|
5
|
+
# Class that holds generated variants of pictures.
|
6
|
+
# Handles the call to the external program for image resizing (`convert`)
|
7
|
+
class OutImageFile < StaticFile
|
8
|
+
def initialize(site, orig_static_file, version, pictype)
|
9
|
+
super(site, site.source, orig_static_file.dir, orig_static_file.name)
|
10
|
+
@version = version
|
11
|
+
@picture_dim = if picture_versions[@version].is_a?(Hash)
|
12
|
+
picture_versions[@version]["out_size"]
|
13
|
+
else
|
14
|
+
picture_versions[@version]
|
15
|
+
end
|
16
|
+
@pictype = pictype
|
17
|
+
@collection = nil
|
18
|
+
end
|
19
|
+
|
20
|
+
def copy_file(dest_path)
|
21
|
+
cmd = if config["backend"] == "libvips"
|
22
|
+
vips_popen_args dest_path
|
23
|
+
else
|
24
|
+
imagemagick_popen_args dest_path
|
25
|
+
end
|
26
|
+
Jekyll.logger.debug "copy_file : #{path} -> #{dest_path} (#{cmd})"
|
27
|
+
p = IO.popen(cmd, err: %i[child out])
|
28
|
+
Jekyll.logger.debug "command_output :\n #{p.readlines.join(" ")}"
|
29
|
+
p.close
|
30
|
+
File.utime(self.class.mtimes[path], self.class.mtimes[path], dest_path)
|
31
|
+
end
|
32
|
+
|
33
|
+
def imagemagick_popen_args(dest_path)
|
34
|
+
args = ["convert", @path]
|
35
|
+
args.concat pre_convert_args
|
36
|
+
args.concat ["-resize", "#{@picture_dim}x>"] unless replace_args
|
37
|
+
if @pictype == "jpg"
|
38
|
+
args.concat ["-background", "##{@config["background_color"]}",
|
39
|
+
"-flatten", "-alpha", "off"]
|
40
|
+
end
|
41
|
+
args.concat convert_args
|
42
|
+
args.push dest_path
|
43
|
+
end
|
44
|
+
|
45
|
+
def vips_popen_args(dest_path)
|
46
|
+
args = ["vips", "thumbnail", @path]
|
47
|
+
dest_path = dest_path.clone.concat "[background=#{rgb_bg_color}]" if @pictype == "jpg"
|
48
|
+
args.push dest_path
|
49
|
+
args.push @picture_dim.to_s
|
50
|
+
args.concat ["--size", "down", "--height", "999999"]
|
51
|
+
end
|
52
|
+
|
53
|
+
def destination(dest)
|
54
|
+
output_dir = File.join("img", @version, @dir)
|
55
|
+
output_basename = @site.in_dest_dir(
|
56
|
+
@site.dest,
|
57
|
+
File.join(output_dir, "#{basename}.#{@pictype}")
|
58
|
+
)
|
59
|
+
FileUtils.mkdir_p(File.dirname(output_dir))
|
60
|
+
@destination ||= {}
|
61
|
+
@destination[dest] ||= output_basename
|
62
|
+
end
|
63
|
+
|
64
|
+
def as_args(input)
|
65
|
+
if input.nil?
|
66
|
+
[]
|
67
|
+
elsif input.is_a?(Array)
|
68
|
+
input.clone
|
69
|
+
elsif input.is_a?(String)
|
70
|
+
input.split(" ")
|
71
|
+
else
|
72
|
+
raise(
|
73
|
+
TypeError,
|
74
|
+
"[jekyll-picture-tag-ng] `extra_convert_args` must be an array or a string (#{input})"
|
75
|
+
)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def rgb_bg_color
|
80
|
+
hex = config["background_color"]
|
81
|
+
@rgb_bg_color ||= "#{hex.slice(0, 2).to_i(16)} #{hex.slice(2, 2).to_i(16)} #{hex.slice(4, 2).to_i(16)}"
|
82
|
+
end
|
83
|
+
|
84
|
+
def picture?
|
85
|
+
extname =~ /(\.jpg|\.jpeg|\.webp)$/i
|
86
|
+
end
|
87
|
+
|
88
|
+
def config
|
89
|
+
@config ||= CONFIG.merge(@site.config["picture_tag_ng"] || {})
|
90
|
+
end
|
91
|
+
|
92
|
+
def picture_versions
|
93
|
+
config["picture_versions"]
|
94
|
+
end
|
95
|
+
|
96
|
+
def replace_args
|
97
|
+
if picture_versions[@version].is_a?(Hash) &&
|
98
|
+
!picture_versions[@version]["replace_convert_args"].nil?
|
99
|
+
picture_versions[@version]["replace_convert_args"]
|
100
|
+
else
|
101
|
+
config["replace_convert_args"]
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def convert_args
|
106
|
+
@convert_args ||= as_args(config["extra_convert_args"]).concat(
|
107
|
+
picture_versions[@version].is_a?(Hash) &&
|
108
|
+
picture_versions[@version]["extra_convert_args"] || []
|
109
|
+
)
|
110
|
+
end
|
111
|
+
|
112
|
+
def pre_convert_args
|
113
|
+
@pre_convert_args ||= as_args(config["pre_extra_convert_args"]).concat(
|
114
|
+
picture_versions[@version].is_a?(Hash) &&
|
115
|
+
picture_versions[@version]["pre_extra_convert_args"] || []
|
116
|
+
)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "out_image_file"
|
4
|
+
|
5
|
+
module Jekyll
|
6
|
+
module PictureTag
|
7
|
+
# Adds `OutImageFile` instances to the site's static files
|
8
|
+
class PicsGenerator < Generator
|
9
|
+
safe true
|
10
|
+
priority :lowest
|
11
|
+
|
12
|
+
def generate(site)
|
13
|
+
@config ||= CONFIG.merge(site.config["picture_tag_ng"] || {})
|
14
|
+
@picture_versions = @config["picture_versions"]
|
15
|
+
new_statics = []
|
16
|
+
site.static_files.filter { |f| f.extname =~ /(\.jpg|\.jpeg|\.webp)$/i }.each do |f|
|
17
|
+
@config["picture_versions"].each do |v, _s|
|
18
|
+
img_f = OutImageFile.new(site, f, v, "jpg")
|
19
|
+
new_statics << img_f
|
20
|
+
img_f = OutImageFile.new(site, f, v, "webp")
|
21
|
+
new_statics << img_f
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
new_statics.each { |f| site.static_files << f }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "static_file"
|
4
|
+
require_relative "picture_tag/pics_generator"
|
5
|
+
|
6
|
+
module Jekyll
|
7
|
+
class Error < StandardError; end
|
8
|
+
|
9
|
+
module PictureTag
|
10
|
+
# Module's default config
|
11
|
+
CONFIG = {
|
12
|
+
"backend" => "imagemagick",
|
13
|
+
"picture_versions" => {
|
14
|
+
"s" => "400",
|
15
|
+
"m" => "700"
|
16
|
+
},
|
17
|
+
"background_color" => "FFFFFF",
|
18
|
+
"extra_convert_args" => [],
|
19
|
+
"replace_convert_args" => false
|
20
|
+
}.freeze
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "jekyll"
|
4
|
+
|
5
|
+
module Jekyll
|
6
|
+
# Override the write methid to paralellize it
|
7
|
+
class Site
|
8
|
+
alias_method "old_write", "write"
|
9
|
+
|
10
|
+
def write
|
11
|
+
if config["picture_tag_ng"]["parallel"]
|
12
|
+
Jekyll.logger.info "Writing files in parallel"
|
13
|
+
Jekyll::Commands::Doctor.conflicting_urls(self)
|
14
|
+
each_site_file do |item|
|
15
|
+
regenerator.regenerate?(item) && add_task { item.write(dest) }
|
16
|
+
end
|
17
|
+
thread_pool.each do
|
18
|
+
add_task { -1 } # Each thread will terminate when a task returns `-1`
|
19
|
+
end
|
20
|
+
thread_pool.each(&:join)
|
21
|
+
reset_thread_pool # Cleanup to be ready for next generation (`jekyll serve`)
|
22
|
+
regenerator.write_metadata
|
23
|
+
Jekyll::Hooks.trigger :site, :post_write, self
|
24
|
+
nil
|
25
|
+
else
|
26
|
+
old_write
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def thread_pool
|
31
|
+
@thread_pool ||= (0..n_threads).map do |i|
|
32
|
+
Jekyll.logger.debug "Creating thread num #{i}"
|
33
|
+
Thread.new do
|
34
|
+
j = 0
|
35
|
+
Kernel.loop do
|
36
|
+
Jekyll.logger.debug "Doing task num. #{j}"
|
37
|
+
j += 1
|
38
|
+
task = next_task
|
39
|
+
if task.nil?
|
40
|
+
sleep 0.1
|
41
|
+
elsif task.instance_of?(Proc)
|
42
|
+
res = task.call
|
43
|
+
end
|
44
|
+
|
45
|
+
break if res == -1
|
46
|
+
end
|
47
|
+
Jekyll.logger.debug "Finishing thread num #{i}"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def n_threads
|
53
|
+
config["picture_tag_ng"]["threads"] || 8
|
54
|
+
end
|
55
|
+
|
56
|
+
def reset_thread_pool
|
57
|
+
@thread_pool = nil
|
58
|
+
end
|
59
|
+
|
60
|
+
def next_task
|
61
|
+
@task_queue ||= []
|
62
|
+
@task_queue.shift
|
63
|
+
end
|
64
|
+
|
65
|
+
def add_task(&task)
|
66
|
+
@task_queue ||= []
|
67
|
+
@task_queue.push(task)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "kramdown"
|
4
|
+
require_relative "../jekyll/picture_tag"
|
5
|
+
|
6
|
+
module Kramdown
|
7
|
+
module Converter
|
8
|
+
# Override Kramdown HTML converter to output picture tags
|
9
|
+
class Html
|
10
|
+
def convert_img(el, _indent)
|
11
|
+
require "cgi"
|
12
|
+
res = "<picture>"
|
13
|
+
new_src = el.attr["src"]
|
14
|
+
if File.extname(el.attr["src"]) =~ /(\.jpg|\.jpeg|\.webp)$/i &&
|
15
|
+
el.attr["src"] !~ %r{^https?://}
|
16
|
+
picture_versions.each do |version, _geometry|
|
17
|
+
src_base = File.join(
|
18
|
+
"/img",
|
19
|
+
version,
|
20
|
+
File.dirname(el.attr["src"]).split("/").map do |x|
|
21
|
+
x.gsub(" ", "%20")
|
22
|
+
end.join("/"),
|
23
|
+
File.basename(el.attr["src"], File.extname(el.attr["src"])).gsub(" ", "%20")
|
24
|
+
)
|
25
|
+
media = media_attribute(version)
|
26
|
+
new_src = "#{src_base}.jpg" if version == default_pic_version
|
27
|
+
res += "<source #{media} srcset=\"#{src_base}.webp\" type=\"image/webp\">"
|
28
|
+
res += "<source #{media} srcset=\"#{src_base}.jpg\" type=\"image/jpeg\">"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
el.attr["src"] = new_src
|
32
|
+
res += "<img#{html_attributes(el.attr)}>"
|
33
|
+
res += "</picture>"
|
34
|
+
end
|
35
|
+
|
36
|
+
def media_attribute(version)
|
37
|
+
geometry = picture_versions[version]
|
38
|
+
if geometry.is_a?(Hash)
|
39
|
+
if geometry["media"].is_a?(String)
|
40
|
+
"media=\"#{geometry["media"]}\""
|
41
|
+
elsif geometry["media"].is_a?(Integer)
|
42
|
+
"media=\"(max-width: #{geometry["media"]}px)\""
|
43
|
+
else
|
44
|
+
"media=\"(max-width: #{geometry["out_size"]}px)\""
|
45
|
+
end
|
46
|
+
else
|
47
|
+
"media=\"(max-width: #{geometry}px)\""
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def site_config
|
52
|
+
@site_config ||= Jekyll::PictureTag::CONFIG.merge(JEKYLL_SITE.config["picture_tag_ng"] || {})
|
53
|
+
end
|
54
|
+
|
55
|
+
def default_pic_version
|
56
|
+
@default_pic_version ||= _get_default_pic_version
|
57
|
+
end
|
58
|
+
|
59
|
+
def _get_default_pic_version
|
60
|
+
largest_version = ""
|
61
|
+
largest_size = 0
|
62
|
+
picture_versions.each do |version, geometry|
|
63
|
+
size = if geometry.is_a?(Integer)
|
64
|
+
geometry
|
65
|
+
elsif geometry["default"]
|
66
|
+
999_999_999
|
67
|
+
else
|
68
|
+
geometry["out_size"]
|
69
|
+
end
|
70
|
+
if size > largest_size
|
71
|
+
largest_version = version
|
72
|
+
largest_size = size
|
73
|
+
end
|
74
|
+
end
|
75
|
+
largest_version
|
76
|
+
end
|
77
|
+
|
78
|
+
def picture_versions
|
79
|
+
site_config["picture_versions"]
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "kramdown"
|
4
|
+
|
5
|
+
module Kramdown
|
6
|
+
module Parser
|
7
|
+
# Override Kramdown parser to add `loading="lazy"` to images
|
8
|
+
class Kramdown
|
9
|
+
def add_link(el, href, title, alt_text = nil, ial = nil)
|
10
|
+
el.options[:ial] = ial
|
11
|
+
update_attr_with_ial(el.attr, ial) if ial
|
12
|
+
if el.type == :a
|
13
|
+
el.attr["href"] = href
|
14
|
+
else
|
15
|
+
el.attr["src"] = href
|
16
|
+
el.attr["alt"] = alt_text
|
17
|
+
el.attr["loading"] = el.attr["loading"] || "lazy"
|
18
|
+
el.children.clear
|
19
|
+
end
|
20
|
+
el.attr["title"] = title if title
|
21
|
+
@tree.children << el
|
22
|
+
end
|
23
|
+
|
24
|
+
require "kramdown/parser/kramdown"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -1,315 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "jekyll"
|
4
|
-
require "kramdown"
|
5
3
|
require_relative "jekyll-picture-tag-ng/version"
|
6
|
-
|
7
|
-
|
8
|
-
# Override default static file to make some instance variables readable
|
9
|
-
class StaticFile
|
10
|
-
attr_reader :site, :dest, :dir, :name
|
11
|
-
end
|
12
|
-
|
13
|
-
module PictureTag
|
14
|
-
CONFIG = {
|
15
|
-
"picture_versions" => {
|
16
|
-
"s" => "400",
|
17
|
-
"m" => "700"
|
18
|
-
},
|
19
|
-
"background_color" => "FFFFFF",
|
20
|
-
"extra_convert_args" => [],
|
21
|
-
"replace_convert_args" => false
|
22
|
-
}.freeze
|
23
|
-
|
24
|
-
class Error < StandardError; end
|
25
|
-
|
26
|
-
# Class that holds generated variants of pictures
|
27
|
-
class OutImageFile < StaticFile
|
28
|
-
def initialize(site, orig_static_file, version, pictype)
|
29
|
-
super(site, site.source, orig_static_file.dir, orig_static_file.name)
|
30
|
-
@version = version
|
31
|
-
@picture_dim = if picture_versions[@version].is_a?(Hash)
|
32
|
-
picture_versions[@version]["out_size"]
|
33
|
-
else
|
34
|
-
picture_versions[@version]
|
35
|
-
end
|
36
|
-
@pictype = pictype
|
37
|
-
@collection = nil
|
38
|
-
end
|
39
|
-
|
40
|
-
def config
|
41
|
-
@config ||= CONFIG.merge(@site.config["picture_tag_ng"] || {})
|
42
|
-
end
|
43
|
-
|
44
|
-
def replace_args
|
45
|
-
result = config["replace_convert_args"]
|
46
|
-
if picture_versions[@version].is_a?(Hash) &&
|
47
|
-
!picture_versions[@version]["replace_convert_args"].nil?
|
48
|
-
result = picture_versions[@version]["replace_convert_args"]
|
49
|
-
end
|
50
|
-
result
|
51
|
-
end
|
52
|
-
|
53
|
-
def picture_versions
|
54
|
-
config["picture_versions"]
|
55
|
-
end
|
56
|
-
|
57
|
-
def as_args(input)
|
58
|
-
if input.nil?
|
59
|
-
[]
|
60
|
-
elsif input.is_a?(Array)
|
61
|
-
input.clone
|
62
|
-
elsif input.is_a?(String)
|
63
|
-
input.split(" ")
|
64
|
-
else
|
65
|
-
raise(
|
66
|
-
TypeError,
|
67
|
-
"[jekyll-picture-tag-ng] `extra_convert_args` must be an array or a string (#{input})"
|
68
|
-
)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
def convert_args
|
73
|
-
@convert_args ||= as_args(config["extra_convert_args"]).concat(
|
74
|
-
picture_versions[@version].is_a?(Hash) &&
|
75
|
-
picture_versions[@version]["extra_convert_args"] || []
|
76
|
-
)
|
77
|
-
end
|
78
|
-
|
79
|
-
def pre_convert_args
|
80
|
-
@pre_convert_args ||= as_args(config["pre_extra_convert_args"]).concat(
|
81
|
-
picture_versions[@version].is_a?(Hash) &&
|
82
|
-
picture_versions[@version]["pre_extra_convert_args"] || []
|
83
|
-
)
|
84
|
-
end
|
85
|
-
|
86
|
-
def picture?
|
87
|
-
extname =~ /(\.jpg|\.jpeg|\.webp)$/i
|
88
|
-
end
|
89
|
-
|
90
|
-
def destination(dest)
|
91
|
-
output_dir = File.join("img", @version, @dir)
|
92
|
-
output_basename = @site.in_dest_dir(
|
93
|
-
@site.dest,
|
94
|
-
File.join(output_dir, "#{basename}.#{@pictype}")
|
95
|
-
)
|
96
|
-
FileUtils.mkdir_p(File.dirname(output_dir))
|
97
|
-
@destination ||= {}
|
98
|
-
@destination[dest] ||= output_basename
|
99
|
-
end
|
100
|
-
|
101
|
-
def popen_args(dest_path)
|
102
|
-
args = ["convert", @path]
|
103
|
-
args.concat pre_convert_args
|
104
|
-
args.concat ["-resize", "#{@picture_dim}x>"] unless replace_args
|
105
|
-
if @pictype == "jpg"
|
106
|
-
args.concat ["-background", "##{@config["background_color"]}",
|
107
|
-
"-flatten", "-alpha", "off"]
|
108
|
-
end
|
109
|
-
args.concat convert_args
|
110
|
-
args.push dest_path
|
111
|
-
end
|
112
|
-
|
113
|
-
def copy_file(dest_path)
|
114
|
-
Jekyll.logger.debug "copy_file : #{path} -> #{dest_path} (#{popen_args(dest_path)})"
|
115
|
-
p = IO.popen(popen_args(dest_path))
|
116
|
-
p.close
|
117
|
-
File.utime(self.class.mtimes[path], self.class.mtimes[path], dest_path)
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
# Will generate the picture variants
|
122
|
-
class PicsGenerator < Generator
|
123
|
-
safe true
|
124
|
-
priority :lowest
|
125
|
-
|
126
|
-
def generate(site)
|
127
|
-
@config ||= CONFIG.merge(site.config["picture_tag_ng"] || {})
|
128
|
-
@picture_versions = @config["picture_versions"]
|
129
|
-
new_statics = []
|
130
|
-
site.static_files.filter { |f| f.extname =~ /(\.jpg|\.jpeg|\.webp)$/i }.each do |f|
|
131
|
-
@config["picture_versions"].each do |v, _s|
|
132
|
-
img_f = OutImageFile.new(site, f, v, "jpg")
|
133
|
-
new_statics << img_f
|
134
|
-
img_f = OutImageFile.new(site, f, v, "webp")
|
135
|
-
new_statics << img_f
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
new_statics.each { |f| site.static_files << f }
|
140
|
-
end
|
141
|
-
end
|
142
|
-
end
|
143
|
-
end
|
4
|
+
require_relative "jekyll-picture-tag-ng/jekyll"
|
5
|
+
require_relative "jekyll-picture-tag-ng/kramdown"
|
144
6
|
|
145
7
|
Jekyll::Hooks.register :site, :after_init do |site|
|
146
8
|
Kramdown::Converter::JEKYLL_SITE = site
|
147
9
|
end
|
148
|
-
|
149
|
-
module Jekyll
|
150
|
-
# Override the write methid to paralellize it
|
151
|
-
class Site
|
152
|
-
alias_method "old_write", "write"
|
153
|
-
|
154
|
-
def n_threads
|
155
|
-
config["picture_tag_ng"]["threads"] || 8
|
156
|
-
end
|
157
|
-
|
158
|
-
def thread_pool
|
159
|
-
@thread_pool ||= (0..n_threads).map do |i|
|
160
|
-
Jekyll.logger.debug "Creating thread num #{i}"
|
161
|
-
Thread.new do
|
162
|
-
j = 0
|
163
|
-
Kernel.loop do
|
164
|
-
Jekyll.logger.debug "Doing task num. #{j}"
|
165
|
-
j += 1
|
166
|
-
task = next_task
|
167
|
-
if task.nil?
|
168
|
-
sleep 0.1
|
169
|
-
elsif task.instance_of?(Proc)
|
170
|
-
res = task.call
|
171
|
-
end
|
172
|
-
|
173
|
-
break if res == -1
|
174
|
-
end
|
175
|
-
Jekyll.logger.debug "Finishing thread num #{i}"
|
176
|
-
end
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
def reset_thread_pool
|
181
|
-
@thread_pool = nil
|
182
|
-
end
|
183
|
-
|
184
|
-
def next_task
|
185
|
-
@task_queue ||= []
|
186
|
-
@task_queue.shift
|
187
|
-
end
|
188
|
-
|
189
|
-
def add_task(&task)
|
190
|
-
@task_queue ||= []
|
191
|
-
@task_queue.push(task)
|
192
|
-
end
|
193
|
-
|
194
|
-
def write
|
195
|
-
if config["picture_tag_ng"]["parallel"]
|
196
|
-
Jekyll.logger.info "Writing files in parallel"
|
197
|
-
Jekyll::Commands::Doctor.conflicting_urls(self)
|
198
|
-
each_site_file do |item|
|
199
|
-
regenerator.regenerate?(item) && add_task { item.write(dest) }
|
200
|
-
end
|
201
|
-
thread_pool.each do
|
202
|
-
add_task { -1 }
|
203
|
-
end
|
204
|
-
thread_pool.each(&:join)
|
205
|
-
reset_thread_pool
|
206
|
-
regenerator.write_metadata
|
207
|
-
Jekyll::Hooks.trigger :site, :post_write, self
|
208
|
-
nil
|
209
|
-
else
|
210
|
-
old_write
|
211
|
-
end
|
212
|
-
end
|
213
|
-
end
|
214
|
-
end
|
215
|
-
|
216
|
-
module Kramdown
|
217
|
-
module Parser
|
218
|
-
# Override Kramdown parser
|
219
|
-
class Kramdown
|
220
|
-
def add_link(el, href, title, alt_text = nil, ial = nil)
|
221
|
-
el.options[:ial] = ial
|
222
|
-
update_attr_with_ial(el.attr, ial) if ial
|
223
|
-
if el.type == :a
|
224
|
-
el.attr["href"] = href
|
225
|
-
else
|
226
|
-
el.attr["src"] = href
|
227
|
-
el.attr["alt"] = alt_text
|
228
|
-
el.attr["loading"] = el.attr["loading"] || "lazy"
|
229
|
-
el.children.clear
|
230
|
-
end
|
231
|
-
el.attr["title"] = title if title
|
232
|
-
@tree.children << el
|
233
|
-
end
|
234
|
-
|
235
|
-
require "kramdown/parser/kramdown"
|
236
|
-
end
|
237
|
-
end
|
238
|
-
|
239
|
-
module Converter
|
240
|
-
# Override Kramdown HTML converter
|
241
|
-
class Html
|
242
|
-
def site_config
|
243
|
-
@site_config ||= Jekyll::PictureTag::CONFIG.merge(JEKYLL_SITE.config["picture_tag_ng"] || {})
|
244
|
-
end
|
245
|
-
|
246
|
-
def picture_versions
|
247
|
-
site_config["picture_versions"]
|
248
|
-
end
|
249
|
-
|
250
|
-
def _get_default_pic_version
|
251
|
-
largest_version = ""
|
252
|
-
largest_size = 0
|
253
|
-
picture_versions.each do |version, geometry|
|
254
|
-
size = if geometry.is_a?(Integer)
|
255
|
-
geometry
|
256
|
-
elsif geometry["default"]
|
257
|
-
999_999_999
|
258
|
-
else
|
259
|
-
geometry["out_size"]
|
260
|
-
end
|
261
|
-
if size > largest_size
|
262
|
-
largest_version = version
|
263
|
-
largest_size = size
|
264
|
-
end
|
265
|
-
end
|
266
|
-
largest_version
|
267
|
-
end
|
268
|
-
|
269
|
-
def default_pic_version
|
270
|
-
@default_pic_version ||= _get_default_pic_version
|
271
|
-
end
|
272
|
-
|
273
|
-
def media_attribute(version)
|
274
|
-
geometry = picture_versions[version]
|
275
|
-
if geometry.is_a?(Hash)
|
276
|
-
if geometry["media"].is_a?(String)
|
277
|
-
"media=\"#{geometry["media"]}\""
|
278
|
-
elsif geometry["media"].is_a?(Integer)
|
279
|
-
"media=\"(max-width: #{geometry["media"]}px)\""
|
280
|
-
else
|
281
|
-
"media=\"(max-width: #{geometry["out_size"]}px)\""
|
282
|
-
end
|
283
|
-
else
|
284
|
-
"media=\"(max-width: #{geometry}px)\""
|
285
|
-
end
|
286
|
-
end
|
287
|
-
|
288
|
-
def convert_img(el, _indent)
|
289
|
-
require "cgi"
|
290
|
-
res = "<picture>"
|
291
|
-
new_src = el.attr["src"]
|
292
|
-
if File.extname(el.attr["src"]) =~ /(\.jpg|\.jpeg|\.webp)$/i &&
|
293
|
-
el.attr["src"] !~ %r{^https?://}
|
294
|
-
picture_versions.each do |version, _geometry|
|
295
|
-
src_base = File.join(
|
296
|
-
"/img",
|
297
|
-
version,
|
298
|
-
File.dirname(el.attr["src"]).split("/").map do |x|
|
299
|
-
x.gsub(" ", "%20")
|
300
|
-
end.join("/"),
|
301
|
-
File.basename(el.attr["src"], File.extname(el.attr["src"])).gsub(" ", "%20")
|
302
|
-
)
|
303
|
-
media = media_attribute(version)
|
304
|
-
new_src = "#{src_base}.jpg" if version == default_pic_version
|
305
|
-
res += "<source #{media} srcset=\"#{src_base}.webp\" type=\"image/webp\">"
|
306
|
-
res += "<source #{media} srcset=\"#{src_base}.jpg\" type=\"image/jpeg\">"
|
307
|
-
end
|
308
|
-
end
|
309
|
-
el.attr["src"] = new_src
|
310
|
-
res += "<img#{html_attributes(el.attr)}>"
|
311
|
-
res += "</picture>"
|
312
|
-
end
|
313
|
-
end
|
314
|
-
end
|
315
|
-
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jekyll-picture-tag-ng
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- pcouy
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-05-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: jekyll
|
@@ -68,6 +68,15 @@ files:
|
|
68
68
|
- README.md
|
69
69
|
- Rakefile
|
70
70
|
- lib/jekyll-picture-tag-ng.rb
|
71
|
+
- lib/jekyll-picture-tag-ng/jekyll.rb
|
72
|
+
- lib/jekyll-picture-tag-ng/jekyll/picture_tag.rb
|
73
|
+
- lib/jekyll-picture-tag-ng/jekyll/picture_tag/out_image_file.rb
|
74
|
+
- lib/jekyll-picture-tag-ng/jekyll/picture_tag/pics_generator.rb
|
75
|
+
- lib/jekyll-picture-tag-ng/jekyll/site.rb
|
76
|
+
- lib/jekyll-picture-tag-ng/jekyll/static_file.rb
|
77
|
+
- lib/jekyll-picture-tag-ng/kramdown.rb
|
78
|
+
- lib/jekyll-picture-tag-ng/kramdown/converter.rb
|
79
|
+
- lib/jekyll-picture-tag-ng/kramdown/parser.rb
|
71
80
|
- lib/jekyll-picture-tag-ng/version.rb
|
72
81
|
- sig/jekyll/picture_tag.rbs
|
73
82
|
homepage: https://pierre-couy.dev/projects/jekyll-picture-tag-ng.html
|