jekyll_picture_tag 1.11.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.envrc +4 -0
- data/.github/workflows/code-checks.yml +33 -0
- data/.gitignore +3 -0
- data/.rubocop.yml +31 -3
- data/.ruby-version +1 -1
- data/docs/.envrc +2 -0
- data/docs/Gemfile +4 -2
- data/docs/Gemfile.lock +14 -12
- data/docs/_config.yml +6 -10
- data/docs/devs/contributing/code.md +54 -0
- data/docs/devs/contributing/docs.md +31 -0
- data/docs/devs/contributing/index.md +15 -0
- data/docs/devs/contributing/setup.md +33 -0
- data/docs/devs/contributing/testing.md +23 -0
- data/docs/devs/index.md +7 -0
- data/docs/devs/releases.md +118 -0
- data/docs/index.md +67 -31
- data/docs/logo.png +0 -0
- data/docs/logo.svg +880 -0
- data/docs/users/configuration/directories.md +34 -0
- data/docs/users/configuration/disable.md +24 -0
- data/docs/users/configuration/fast_build.md +28 -0
- data/docs/users/configuration/ignore_missing.md +23 -0
- data/docs/users/configuration/index.md +29 -0
- data/docs/users/configuration/kramdown_fix.md +20 -0
- data/docs/users/configuration/suppress_warnings.md +16 -0
- data/docs/users/configuration/urls.md +69 -0
- data/docs/users/getting_started.md +55 -0
- data/docs/users/index.md +7 -0
- data/docs/users/installation.md +32 -0
- data/docs/users/liquid_tag/argument_reference/alternate_images.md +18 -0
- data/docs/users/liquid_tag/argument_reference/attributes.md +42 -0
- data/docs/users/liquid_tag/argument_reference/base_image.md +12 -0
- data/docs/users/liquid_tag/argument_reference/crop.md +33 -0
- data/docs/users/liquid_tag/argument_reference/link.md +16 -0
- data/docs/users/liquid_tag/argument_reference/preset.md +17 -0
- data/docs/users/liquid_tag/argument_reference/readme.md +9 -0
- data/docs/users/liquid_tag/examples.md +81 -0
- data/docs/users/liquid_tag/index.md +31 -0
- data/docs/users/notes/git_lfs.md +7 -0
- data/docs/users/notes/github_pages.md +5 -0
- data/docs/users/notes/html_attributes.md +5 -0
- data/docs/users/notes/index.md +6 -0
- data/docs/users/notes/kramdown_bug.md +41 -0
- data/docs/users/notes/managing_images.md +21 -0
- data/docs/{migration.md → users/notes/migration_1.md} +1 -1
- data/docs/users/notes/migration_2.md +99 -0
- data/docs/users/presets/cropping.md +60 -0
- data/docs/users/presets/default.md +32 -0
- data/docs/users/presets/examples.md +111 -0
- data/docs/users/presets/fallback_image.md +28 -0
- data/docs/users/presets/html_attributes.md +26 -0
- data/docs/users/presets/image_formats.md +21 -0
- data/docs/users/presets/image_quality.md +120 -0
- data/docs/users/presets/index.md +75 -0
- data/docs/users/presets/link_source.md +16 -0
- data/docs/users/presets/markup_formats/fragments.md +48 -0
- data/docs/users/presets/markup_formats/javascript_friendly.md +57 -0
- data/docs/users/presets/markup_formats/readme.md +43 -0
- data/docs/users/presets/markup_formats/standard_html.md +25 -0
- data/docs/users/presets/media_queries.md +36 -0
- data/docs/users/presets/nomarkdown_override.md +17 -0
- data/docs/users/presets/pixel_ratio_srcsets.md +32 -0
- data/docs/users/presets/quality_width_graph.png +0 -0
- data/docs/users/presets/width_height_attributes.md +34 -0
- data/docs/users/presets/width_srcsets.md +123 -0
- data/docs/users/presets/writing_presets.md +65 -0
- data/docs/users/tutorial.md +97 -0
- data/jekyll_picture_tag.gemspec +38 -23
- data/lib/jekyll_picture_tag.rb +11 -10
- data/lib/jekyll_picture_tag/cache.rb +64 -3
- data/lib/jekyll_picture_tag/defaults/global.rb +18 -0
- data/lib/jekyll_picture_tag/defaults/presets.rb +57 -0
- data/lib/jekyll_picture_tag/images.rb +4 -0
- data/lib/jekyll_picture_tag/images/generated_image.rb +92 -0
- data/lib/jekyll_picture_tag/images/image_file.rb +90 -0
- data/lib/jekyll_picture_tag/{img_uri.rb → images/img_uri.rb} +3 -10
- data/lib/jekyll_picture_tag/{source_image.rb → images/source_image.rb} +44 -9
- data/lib/jekyll_picture_tag/instructions.rb +70 -6
- data/lib/jekyll_picture_tag/instructions/children/config.rb +128 -0
- data/lib/jekyll_picture_tag/instructions/children/context.rb +24 -0
- data/lib/jekyll_picture_tag/instructions/children/params.rb +90 -0
- data/lib/jekyll_picture_tag/instructions/children/parsers.rb +41 -0
- data/lib/jekyll_picture_tag/instructions/children/preset.rb +182 -0
- data/lib/jekyll_picture_tag/instructions/parents/conditional_instruction.rb +69 -0
- data/lib/jekyll_picture_tag/instructions/parents/env_instruction.rb +29 -0
- data/lib/jekyll_picture_tag/output_formats/basic.rb +5 -17
- data/lib/jekyll_picture_tag/parsers.rb +5 -0
- data/lib/jekyll_picture_tag/{instructions → parsers}/arg_splitter.rb +1 -1
- data/lib/jekyll_picture_tag/parsers/configuration.rb +28 -0
- data/lib/jekyll_picture_tag/{instructions → parsers}/html_attributes.rb +1 -1
- data/lib/jekyll_picture_tag/parsers/preset.rb +43 -0
- data/lib/jekyll_picture_tag/{instructions → parsers}/tag_parser.rb +15 -12
- data/lib/jekyll_picture_tag/router.rb +35 -93
- data/lib/jekyll_picture_tag/srcsets/basic.rb +4 -10
- data/lib/jekyll_picture_tag/utils.rb +24 -20
- data/lib/jekyll_picture_tag/version.rb +1 -1
- data/readme.md +15 -13
- metadata +215 -93
- data/.travis.yml +0 -8
- data/Dockerfile +0 -9
- data/docs/_layouts/directory.html +0 -32
- data/docs/assets/style.css +0 -31
- data/docs/contributing.md +0 -109
- data/docs/example_presets.md +0 -116
- data/docs/global_configuration.md +0 -173
- data/docs/installation.md +0 -45
- data/docs/notes.md +0 -91
- data/docs/output.md +0 -63
- data/docs/presets.md +0 -391
- data/docs/releases.md +0 -70
- data/docs/usage.md +0 -157
- data/jekyll-picture-tag.gemspec +0 -52
- data/lib/jekyll-picture-tag.rb +0 -25
- data/lib/jekyll_picture_tag/cache/base.rb +0 -59
- data/lib/jekyll_picture_tag/cache/generated.rb +0 -20
- data/lib/jekyll_picture_tag/cache/source.rb +0 -19
- data/lib/jekyll_picture_tag/defaults/global.yml +0 -11
- data/lib/jekyll_picture_tag/defaults/presets.yml +0 -11
- data/lib/jekyll_picture_tag/generated_image.rb +0 -140
- data/lib/jekyll_picture_tag/instructions/configuration.rb +0 -121
- data/lib/jekyll_picture_tag/instructions/preset.rb +0 -103
- data/lib/jekyll_picture_tag/instructions/set.rb +0 -71
@@ -0,0 +1,97 @@
|
|
1
|
+
---
|
2
|
+
sort: 3
|
3
|
+
---
|
4
|
+
|
5
|
+
# Tutorial
|
6
|
+
|
7
|
+
## Hello, world!
|
8
|
+
|
9
|
+
Once you've followed the [installation](installation) instructions, it's a good
|
10
|
+
time to make sure we're set up correctly. Drop an image or two in the site root
|
11
|
+
(or `source` directory if you [configured it](configuration/directories)), pick
|
12
|
+
some page and write the following (substitute the image filename as
|
13
|
+
appropriate):
|
14
|
+
|
15
|
+
{% raw %}
|
16
|
+
```
|
17
|
+
{% picture my_image.jpg %}
|
18
|
+
```
|
19
|
+
{% endraw %}
|
20
|
+
|
21
|
+
Build/serve the site and check it out! Your image should be there, and if you inspect it with the
|
22
|
+
dev tools you should see an `<img>` tag with a `srcset` attribute. You're officially serving
|
23
|
+
responsive images.
|
24
|
+
|
25
|
+
## Webp
|
26
|
+
|
27
|
+
JPT includes several built-in presets and media queries, documented in the
|
28
|
+
[examples](presets/examples). They're intended as a starting point and a learning tool, not for
|
29
|
+
production use. Don't dig to deeply into that link just yet, try them out first:
|
30
|
+
|
31
|
+
{% raw %}
|
32
|
+
```
|
33
|
+
{% picture jpt-webp my_image.jpg %}
|
34
|
+
```
|
35
|
+
{% endraw %}
|
36
|
+
|
37
|
+
Now instead of a lone `<img>` tag, you get a `<picture>` surrounding two `<source>`s and an `<img>`.
|
38
|
+
The first source contains webp images, and the second contains jpgs. Success! Lighthouse is happier
|
39
|
+
and happier.
|
40
|
+
|
41
|
+
## Alt text
|
42
|
+
|
43
|
+
Good web developers add alt text. JPT makes this easy:
|
44
|
+
|
45
|
+
{% raw %}
|
46
|
+
```
|
47
|
+
{% picture my_image.jpg --alt Happy Puppy %}
|
48
|
+
```
|
49
|
+
{% endraw %}
|
50
|
+
|
51
|
+
## Crop
|
52
|
+
|
53
|
+
|
54
|
+
{% raw %}
|
55
|
+
```
|
56
|
+
{% picture my_image.jpg 16:9 %}
|
57
|
+
```
|
58
|
+
{% endraw %}
|
59
|
+
|
60
|
+
Feeling cinematic? If you don't like how the image gets cropped, you can adjust it:
|
61
|
+
|
62
|
+
{% raw %}
|
63
|
+
```
|
64
|
+
{% picture my_image.jpg 16:9 center %}
|
65
|
+
```
|
66
|
+
{% endraw %}
|
67
|
+
|
68
|
+
Your options are `attention` (which is the default), `entropy`, and `center`.
|
69
|
+
|
70
|
+
## Art Direction
|
71
|
+
|
72
|
+
(Usually means "Cropping, but only sometimes.")
|
73
|
+
|
74
|
+
Art direction is tricky to understand; I know it tripped me up for awhile when learning the subject.
|
75
|
+
Here's a short explanation, along with a demo: Let's pretend that we have some image which looks
|
76
|
+
good on desktop, but on a mobile screen it's hard to see the subject. Resolution isn't the problem,
|
77
|
+
the image just needs to be cropped for smaller screens. JPT makes this easy:
|
78
|
+
|
79
|
+
{% raw %}
|
80
|
+
```
|
81
|
+
{% picture my_image.jpg 2:1 jpt-mobile: my_image.jpg 1:1 %}
|
82
|
+
```
|
83
|
+
{% endraw %}
|
84
|
+
|
85
|
+
This tag is pretty complicated, so here's a breakdown in plain english:
|
86
|
+
* Use the default preset.
|
87
|
+
* use my_image.jpg as the base image.
|
88
|
+
* Crop it to a 2:1 aspect ratio.
|
89
|
+
* When the media query named 'jpt-mobile' is true, also use my_image.jpg
|
90
|
+
* but this time crop it square.
|
91
|
+
|
92
|
+
Now adjust the browser width. When skinny, you should see a square crop of your image, and when it's
|
93
|
+
wide you should see a 2:1 crop of the same image. That's art direction. Note that there's no
|
94
|
+
requirement at all for them to be the same image, and you don't have to use JPT to do the cropping.
|
95
|
+
|
96
|
+
There are several more liquid tag examples [here](liquid_tag/examples) that you may want to look
|
97
|
+
over, as well as the [liquid tag instructions](liquid_tag).
|
data/jekyll_picture_tag.gemspec
CHANGED
@@ -4,43 +4,58 @@ require 'jekyll_picture_tag/version'
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = 'jekyll_picture_tag'
|
7
|
-
spec.version = PictureTag::VERSION
|
8
7
|
spec.authors = ['Robert Wierzbowski', 'Brendan Tobolaski',
|
9
8
|
'Robert Buchberger']
|
10
9
|
spec.email = ['robert@buchberger.cc']
|
11
|
-
|
10
|
+
spec.homepage = 'https://github.com/rbuchberger/jekyll_picture_tag'
|
11
|
+
spec.metadata = { 'documentation_uri' =>
|
12
|
+
'https://rbuchberger.github.io/jekyll_picture_tag/' }
|
13
|
+
spec.license = 'BSD-3-Clause'
|
12
14
|
spec.summary = 'Easy responsive images for Jekyll.'
|
13
15
|
spec.description = <<-HEREDOC
|
14
|
-
Jekyll Picture Tag
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
simple template tag.
|
16
|
+
Jekyll Picture Tag adds responsive images to your Jekyll static site. It
|
17
|
+
automatically creates resized source images, is fully configurable, and
|
18
|
+
covers all use cases, including art direction and resolution switching, with
|
19
|
+
a little YAML configuration and a simple template tag.
|
19
20
|
HEREDOC
|
20
|
-
spec.homepage = 'https://github.com/rbuchberger/jekyll_picture_tag'
|
21
|
-
spec.license = 'BSD-3-Clause'
|
22
|
-
spec.require_paths = ['lib']
|
23
21
|
|
22
|
+
spec.version = PictureTag::VERSION
|
23
|
+
spec.require_paths = ['lib']
|
24
24
|
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
25
|
-
f.match(%r{^(test
|
25
|
+
f.match(%r{^(test)/})
|
26
26
|
end
|
27
27
|
|
28
|
-
spec.required_ruby_version = ['>= 2.
|
28
|
+
spec.required_ruby_version = ['>= 2.6', '< 4.0']
|
29
|
+
|
30
|
+
# addressable is used to url-encode image filenames.
|
31
|
+
spec.add_runtime_dependency 'addressable', '~> 2.6'
|
32
|
+
# Jekyll versions older than 4.0 are not supported.
|
33
|
+
spec.add_runtime_dependency 'jekyll', '~> 4.0'
|
34
|
+
# MIME types are needed for <source> tags' type= attributes.
|
35
|
+
spec.add_runtime_dependency 'mime-types', '~> 3.0'
|
36
|
+
# objective_elements handles HTML generation.
|
37
|
+
spec.add_runtime_dependency 'objective_elements', '~> 1.1'
|
38
|
+
# rainbow is used to colorize terminal output.
|
39
|
+
spec.add_runtime_dependency 'rainbow', '~> 3.0'
|
40
|
+
# ruby-vips interfaces with libvips.
|
41
|
+
spec.add_runtime_dependency 'ruby-vips', '~> 2.0.17'
|
29
42
|
|
43
|
+
# libvips handles all image processing operations.
|
44
|
+
spec.requirements << 'libvips'
|
45
|
+
|
46
|
+
# Development dependencies are not installed when using this gem. You can
|
47
|
+
# ignore these, unless you are working on JPT itself.
|
30
48
|
spec.add_development_dependency 'bundler', '~> 2.0'
|
31
|
-
spec.add_development_dependency 'minitest', '~> 5.
|
49
|
+
spec.add_development_dependency 'minitest', '~> 5.14'
|
50
|
+
spec.add_development_dependency 'minitest-rg'
|
32
51
|
spec.add_development_dependency 'mocha', '~> 1.9'
|
33
|
-
spec.add_development_dependency 'nokogiri', '~> 1.
|
52
|
+
spec.add_development_dependency 'nokogiri', '~> 1.1'
|
34
53
|
spec.add_development_dependency 'pry'
|
35
54
|
spec.add_development_dependency 'rake', '~> 12.3'
|
36
|
-
spec.add_development_dependency 'rubocop'
|
37
|
-
spec.add_development_dependency '
|
55
|
+
spec.add_development_dependency 'rubocop', '~> 1.7.0'
|
56
|
+
spec.add_development_dependency 'rubocop-minitest', '~> 0.10.0'
|
57
|
+
spec.add_development_dependency 'rubocop-performance', '~> 1.9.0'
|
58
|
+
spec.add_development_dependency 'rubocop-rake', '~> 0.5.0'
|
59
|
+
spec.add_development_dependency 'simplecov', '~> 0.20.0'
|
38
60
|
spec.add_development_dependency 'solargraph'
|
39
|
-
|
40
|
-
spec.add_dependency 'addressable', '~> 2.6'
|
41
|
-
spec.add_dependency 'mime-types', '~> 3'
|
42
|
-
spec.add_dependency 'mini_magick', '~> 4'
|
43
|
-
spec.add_dependency 'objective_elements', '~> 1.1.2'
|
44
|
-
|
45
|
-
spec.add_runtime_dependency 'jekyll', '< 5'
|
46
61
|
end
|
data/lib/jekyll_picture_tag.rb
CHANGED
@@ -1,15 +1,16 @@
|
|
1
1
|
require 'jekyll'
|
2
2
|
require 'objective_elements'
|
3
3
|
|
4
|
-
require_relative 'jekyll_picture_tag/
|
4
|
+
require_relative 'jekyll_picture_tag/cache'
|
5
|
+
require_relative 'jekyll_picture_tag/images'
|
5
6
|
require_relative 'jekyll_picture_tag/instructions'
|
6
7
|
require_relative 'jekyll_picture_tag/output_formats'
|
7
|
-
require_relative 'jekyll_picture_tag/
|
8
|
+
require_relative 'jekyll_picture_tag/parsers'
|
9
|
+
require_relative 'jekyll_picture_tag/router'
|
8
10
|
require_relative 'jekyll_picture_tag/srcsets'
|
9
11
|
require_relative 'jekyll_picture_tag/utils'
|
10
|
-
require_relative 'jekyll_picture_tag/
|
11
|
-
require_relative 'jekyll_picture_tag/
|
12
|
-
require_relative 'jekyll_picture_tag/cache'
|
12
|
+
require_relative 'jekyll_picture_tag/defaults/presets'
|
13
|
+
require_relative 'jekyll_picture_tag/defaults/global'
|
13
14
|
|
14
15
|
# Title: Jekyll Picture Tag
|
15
16
|
# Authors: Rob Wierzbowski : @robwierzbowski
|
@@ -62,7 +63,9 @@ module PictureTag
|
|
62
63
|
def render(context)
|
63
64
|
setup(context)
|
64
65
|
|
65
|
-
if PictureTag.disabled?
|
66
|
+
if PictureTag.disabled? || PictureTag.raw_params.empty?
|
67
|
+
Utils.warning 'You have called JPT without any arguments.'
|
68
|
+
|
66
69
|
''
|
67
70
|
else
|
68
71
|
PictureTag.output_class.new.to_s
|
@@ -72,11 +75,9 @@ module PictureTag
|
|
72
75
|
private
|
73
76
|
|
74
77
|
def setup(context)
|
78
|
+
PictureTag.clear_instructions
|
75
79
|
PictureTag.context = context
|
76
|
-
|
77
|
-
# Now that we have both the tag parameters and the context object, we can
|
78
|
-
# build our instruction set.
|
79
|
-
PictureTag.instructions = Instructions::Set.new(@raw_params)
|
80
|
+
PictureTag.raw_params = @raw_params
|
80
81
|
|
81
82
|
# We need to explicitly prevent jekyll from overwriting our generated
|
82
83
|
# image files:
|
@@ -1,3 +1,64 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module PictureTag
|
4
|
+
# Store expensive bits of information between text files. Originally cached
|
5
|
+
# width & heights of images in addition to digests, now just image digests.
|
6
|
+
class Cache
|
7
|
+
def initialize(base_name)
|
8
|
+
@base_name = base_name
|
9
|
+
end
|
10
|
+
|
11
|
+
def [](key)
|
12
|
+
data[key]
|
13
|
+
end
|
14
|
+
|
15
|
+
def []=(key, value)
|
16
|
+
raise ArgumentError unless template.keys.include? key
|
17
|
+
|
18
|
+
data[key] = value
|
19
|
+
end
|
20
|
+
|
21
|
+
# Call after updating data.
|
22
|
+
def write
|
23
|
+
return if PictureTag.config['disable_disk_cache']
|
24
|
+
|
25
|
+
FileUtils.mkdir_p(File.join(base_directory, sub_directory))
|
26
|
+
|
27
|
+
File.open(filename, 'w+') do |f|
|
28
|
+
f.write JSON.generate(data)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def data
|
35
|
+
@data ||= if File.exist?(filename)
|
36
|
+
JSON.parse(File.read(filename)).transform_keys(&:to_sym)
|
37
|
+
else
|
38
|
+
template
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# /home/dave/my_blog/.jekyll-cache/jpt/(cache_dir)/assets/myimage.jpg.json
|
43
|
+
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
44
|
+
def base_directory
|
45
|
+
File.join(PictureTag.site.cache_dir, 'jpt')
|
46
|
+
end
|
47
|
+
|
48
|
+
# /home/dave/my_blog/.jekyll-cache/jpt/(cache_dir)/assets/myimage.jpg.json
|
49
|
+
# ^^^^^^^^
|
50
|
+
def sub_directory
|
51
|
+
File.dirname(@base_name)
|
52
|
+
end
|
53
|
+
|
54
|
+
# /home/dave/my_blog/.jekyll-cache/jpt/somefolder/myimage.jpg.json
|
55
|
+
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
56
|
+
def filename
|
57
|
+
File.join(base_directory, @base_name + '.json')
|
58
|
+
end
|
59
|
+
|
60
|
+
def template
|
61
|
+
{ digest: nil }
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module PictureTag
|
2
|
+
# Default settings for _config.yml
|
3
|
+
DEFAULT_CONFIG = {
|
4
|
+
'picture' => {
|
5
|
+
'source' => '',
|
6
|
+
'output' => 'generated',
|
7
|
+
'suppress_warnings' => false,
|
8
|
+
'relative_url' => true,
|
9
|
+
'cdn_environments' => ['production'],
|
10
|
+
'nomarkdown' => true,
|
11
|
+
'ignore_missing_images' => false,
|
12
|
+
'disabled' => false,
|
13
|
+
'fast_build' => false,
|
14
|
+
'ignore_baseurl' => false,
|
15
|
+
'baseurl_key' => 'baseurl'
|
16
|
+
}
|
17
|
+
}.freeze
|
18
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module PictureTag
|
2
|
+
DEFAULT_PRESET = { 'markup' => 'auto',
|
3
|
+
'formats' => ['original'],
|
4
|
+
'widths' => [400, 600, 800, 1000],
|
5
|
+
'fallback_width' => 800,
|
6
|
+
'fallback_format' => 'original',
|
7
|
+
'noscript' => false,
|
8
|
+
'link_source' => false,
|
9
|
+
'quality' => 75,
|
10
|
+
'format_quality' => { 'webp' => 50,
|
11
|
+
'avif' => 30,
|
12
|
+
'jp2' => 30 },
|
13
|
+
'data_sizes' => true,
|
14
|
+
'keep' => 'attention',
|
15
|
+
'dimension_attributes' => false,
|
16
|
+
'strip_metadata' => true,
|
17
|
+
'image_options' => {
|
18
|
+
'avif' => { 'compression' => 'av1', 'speed' => 8 }
|
19
|
+
} }.freeze
|
20
|
+
|
21
|
+
STOCK_PRESETS = {
|
22
|
+
'jpt-webp' => { 'formats' => %w[webp original] },
|
23
|
+
|
24
|
+
'jpt-avif' => { 'formats' => %w[avif webp original] },
|
25
|
+
|
26
|
+
'jpt-lazy' => { 'markup' => 'data_auto',
|
27
|
+
'noscript' => true,
|
28
|
+
'formats' => %w[webp original],
|
29
|
+
'attributes' => { 'parent' => 'class="lazy"' } },
|
30
|
+
|
31
|
+
'jpt-loaded' => { 'formats' => %w[avif jp2 webp original],
|
32
|
+
'dimension_attributes' => true },
|
33
|
+
|
34
|
+
'jpt-direct' => { 'markup' => 'direct_url',
|
35
|
+
'fallback_format' => 'webp',
|
36
|
+
'fallback_width' => 600 },
|
37
|
+
|
38
|
+
'jpt-thumbnail' => { 'base_width' => 250,
|
39
|
+
'pixel_ratios' => [1, 1.5, 2],
|
40
|
+
'formats' => %w[webp original],
|
41
|
+
'fallback_width' => 250,
|
42
|
+
'attributes' => { 'picture' => 'class="icon"' } },
|
43
|
+
|
44
|
+
'jpt-avatar' => { 'base_width' => 100,
|
45
|
+
'pixel_ratios' => [1, 1.5, 2],
|
46
|
+
'fallback_width' => 100,
|
47
|
+
'crop' => '1:1' }
|
48
|
+
}.freeze
|
49
|
+
|
50
|
+
STOCK_MEDIA_QUERIES = {
|
51
|
+
'jpt-mobile' => 'max-width: 480px',
|
52
|
+
'jpt-tablet' => 'max-width: 768',
|
53
|
+
'jpt-laptop' => 'max-width: 1024px',
|
54
|
+
'jpt-desktop' => 'max-width: 1200',
|
55
|
+
'jpt-wide' => 'min-width: 1201'
|
56
|
+
}.freeze
|
57
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'ruby-vips'
|
2
|
+
|
3
|
+
module PictureTag
|
4
|
+
# Represents a generated image, but not the file itself. Its purpose is to
|
5
|
+
# make its properties available for query, and hand them off to the ImageFile
|
6
|
+
# class for generation.
|
7
|
+
class GeneratedImage
|
8
|
+
attr_reader :width
|
9
|
+
|
10
|
+
def initialize(source_file:, width:, format:)
|
11
|
+
@source = source_file
|
12
|
+
@width = width
|
13
|
+
@raw_format = format
|
14
|
+
end
|
15
|
+
|
16
|
+
def format
|
17
|
+
@format ||= process_format(@raw_format)
|
18
|
+
end
|
19
|
+
|
20
|
+
def exists?
|
21
|
+
File.exist?(absolute_filename)
|
22
|
+
end
|
23
|
+
|
24
|
+
def generate
|
25
|
+
generate_image unless @source.missing || exists?
|
26
|
+
end
|
27
|
+
|
28
|
+
# /home/dave/my_blog/_site/generated/somefolder/myimage-100-123abc.jpg
|
29
|
+
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
30
|
+
def absolute_filename
|
31
|
+
@absolute_filename ||= File.join(PictureTag.dest_dir, name)
|
32
|
+
end
|
33
|
+
|
34
|
+
# /home/dave/my_blog/_site/generated/somefolder/myimage-100-123abc.jpg
|
35
|
+
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
36
|
+
def name
|
37
|
+
@name ||= "#{@source.base_name}-#{@width}-#{id}.#{@format}"
|
38
|
+
end
|
39
|
+
|
40
|
+
# https://example.com/assets/somefolder/myimage-100-123abc.jpg
|
41
|
+
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
42
|
+
def uri
|
43
|
+
ImgURI.new(name).to_s
|
44
|
+
end
|
45
|
+
|
46
|
+
# Post crop
|
47
|
+
def source_width
|
48
|
+
image.width
|
49
|
+
end
|
50
|
+
|
51
|
+
# Post crop
|
52
|
+
def source_height
|
53
|
+
image.height
|
54
|
+
end
|
55
|
+
|
56
|
+
def quality
|
57
|
+
PictureTag.quality(format, width)
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
# Hash all inputs and truncate, so we know when they change without getting
|
63
|
+
# too long.
|
64
|
+
# /home/dave/my_blog/_site/generated/somefolder/myimage-100-1234abcde.jpg
|
65
|
+
# ^^^^^^^^^
|
66
|
+
def id
|
67
|
+
@id ||= Digest::MD5.hexdigest(settings.join)[0..8]
|
68
|
+
end
|
69
|
+
|
70
|
+
def settings
|
71
|
+
[@source.digest, @source.crop, @source.keep, quality]
|
72
|
+
end
|
73
|
+
|
74
|
+
def image
|
75
|
+
@image ||= Vips::Image.new_from_file @source.name
|
76
|
+
end
|
77
|
+
|
78
|
+
def generate_image
|
79
|
+
return if @source.missing
|
80
|
+
|
81
|
+
ImageFile.new(@source, self)
|
82
|
+
end
|
83
|
+
|
84
|
+
def process_format(format)
|
85
|
+
if format.casecmp('original').zero?
|
86
|
+
@source.ext
|
87
|
+
else
|
88
|
+
format.downcase
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|