jekyll-imgflow 0.2.0 โ 0.3.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/lib/jekyll-imgflow/config.rb +3 -1
- data/lib/jekyll-imgflow/hooks.rb +7 -0
- data/lib/jekyll-imgflow/html_generator.rb +9 -2
- data/lib/jekyll-imgflow/imgflow_tag.rb +2 -1
- data/lib/jekyll-imgflow/modal_assets.rb +107 -0
- data/lib/jekyll-imgflow/parser.rb +1 -1
- data/lib/jekyll-imgflow/version.rb +1 -1
- data/lib/jekyll-imgflow.rb +1 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d37c208e7250fe6da8291bfab933d5df7391347d0ce95492e32e1d94e54df7a8
|
|
4
|
+
data.tar.gz: cd222c0e6dbdcffe168ec0919a12d53c57324a277cb9efeecb5173a98c4c5b04
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2f566b0e2d70993a209a5353cf1b91d54e3b3f3143397146f58bbbcf19428eab9797ed5def60efdd3d8f926f214fa2ec6670d47ccfd6c000fe2f9c35b2bac00c
|
|
7
|
+
data.tar.gz: 0b601aea8c16d71133816f034b4277e399e6108569af169c0984416ef6e5d90edc30490d17af254f736f2897eae5c6b55d515888a4b71af35dd8020b63f37a88
|
|
@@ -20,11 +20,12 @@ module JekyllImgFlow
|
|
|
20
20
|
# Format used for the <img> fallback in <picture> elements.
|
|
21
21
|
# All other formats in `formats` get <source> tags for browsers that support them.
|
|
22
22
|
DEFAULT_FALLBACK_FORMAT = "jpg"
|
|
23
|
+
DEFAULT_IMAGE_MODAL = true
|
|
23
24
|
|
|
24
25
|
attr_reader :site, :originals, :output, :input_formats, :sizes, :formats,
|
|
25
26
|
:quality, :backend_priority, :imgproxy_url,
|
|
26
27
|
:weserv_url, :flyimg_url,
|
|
27
|
-
:optimize_qualities, :fallback_format
|
|
28
|
+
:optimize_qualities, :fallback_format, :image_modal
|
|
28
29
|
|
|
29
30
|
def initialize(site)
|
|
30
31
|
shared = site.config["shared_images_configs"] || {}
|
|
@@ -40,6 +41,7 @@ module JekyllImgFlow
|
|
|
40
41
|
@quality = cfg["quality"] || DEFAULT_QUALITY
|
|
41
42
|
@backend_priority = cfg["backend_priority"] || DEFAULT_BACKEND_PRIORITY
|
|
42
43
|
@fallback_format = cfg["fallback_format"] || DEFAULT_FALLBACK_FORMAT
|
|
44
|
+
@image_modal = cfg.fetch("image_modal", DEFAULT_IMAGE_MODAL)
|
|
43
45
|
|
|
44
46
|
@imgproxy_url = cfg["imgproxy_url"]
|
|
45
47
|
@weserv_url = cfg["weserv_url"]
|
data/lib/jekyll-imgflow/hooks.rb
CHANGED
|
@@ -47,6 +47,13 @@ module JekyllImgFlow
|
|
|
47
47
|
end
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
+
# Inject modal CSS/JS into pages that contain data-imgflow-modal triggers
|
|
51
|
+
%i[pages documents].each do |type|
|
|
52
|
+
Jekyll::Hooks.register type, :post_render do |doc|
|
|
53
|
+
doc.output = ModalAssets.inject(doc.output) if doc.output
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
50
57
|
def self.cleanup_orphaned_images(site, manifest = nil)
|
|
51
58
|
Jekyll.logger.info "๐งน ImgFlow: Checking for orphaned specialized images..."
|
|
52
59
|
|
|
@@ -4,6 +4,8 @@ module JekyllImgFlow
|
|
|
4
4
|
# Unified HTML Generator for all markup formats
|
|
5
5
|
# Supports Picture Tag compatibility with multiple markup formats and attributes
|
|
6
6
|
class HtmlGenerator
|
|
7
|
+
include ModalWrapper
|
|
8
|
+
|
|
7
9
|
# Generate HTML based on markup format and attributes
|
|
8
10
|
# @param results [Array<String>] Processed image paths
|
|
9
11
|
# @param attributes [Hash] HTML attributes by element
|
|
@@ -47,6 +49,9 @@ module JekyllImgFlow
|
|
|
47
49
|
# Wrap in link if specified
|
|
48
50
|
html = wrap_with_link(html) if @attributes[:link]
|
|
49
51
|
|
|
52
|
+
# Wrap in modal trigger if enabled (only for HTML elements, not raw URLs)
|
|
53
|
+
html = wrap_with_modal(html) if modal_enabled? && html_element?
|
|
54
|
+
|
|
50
55
|
# Wrap in parent container if specified
|
|
51
56
|
html = wrap_with_parent(html) if @attributes[:parent]&.any?
|
|
52
57
|
|
|
@@ -77,7 +82,8 @@ module JekyllImgFlow
|
|
|
77
82
|
a: attributes[:a] || {},
|
|
78
83
|
parent: attributes[:parent] || {},
|
|
79
84
|
alt: attributes[:alt],
|
|
80
|
-
link: attributes[:link]
|
|
85
|
+
link: attributes[:link],
|
|
86
|
+
modal: attributes[:modal]
|
|
81
87
|
}
|
|
82
88
|
end
|
|
83
89
|
|
|
@@ -89,7 +95,8 @@ module JekyllImgFlow
|
|
|
89
95
|
a: {},
|
|
90
96
|
parent: {},
|
|
91
97
|
alt: nil,
|
|
92
|
-
link: nil
|
|
98
|
+
link: nil,
|
|
99
|
+
modal: nil
|
|
93
100
|
}
|
|
94
101
|
end
|
|
95
102
|
|
|
@@ -193,7 +193,8 @@ module Jekyll
|
|
|
193
193
|
a: extract_prefixed_attrs(base_attrs, "a-"),
|
|
194
194
|
parent: extract_prefixed_attrs(base_attrs, "parent-"),
|
|
195
195
|
alt: base_attrs[:alt],
|
|
196
|
-
link: base_attrs[:link]
|
|
196
|
+
link: base_attrs[:link],
|
|
197
|
+
modal: base_attrs[:modal]
|
|
197
198
|
}
|
|
198
199
|
end
|
|
199
200
|
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module JekyllImgFlow
|
|
4
|
+
# Inline CSS and JS for the image modal/lightbox feature.
|
|
5
|
+
# Injected by hooks.rb into pages that contain data-imgflow-modal triggers.
|
|
6
|
+
module ModalAssets
|
|
7
|
+
CSS = <<~CSS
|
|
8
|
+
.imgflow-modal-overlay{position:fixed;inset:0;background:rgba(0,0,0,.85);
|
|
9
|
+
display:flex;align-items:center;justify-content:center;z-index:9999;
|
|
10
|
+
cursor:pointer;animation:imgflow-fade .15s ease-out}
|
|
11
|
+
.imgflow-modal-image{max-width:90vw;max-height:90vh;object-fit:contain;
|
|
12
|
+
cursor:auto;border-radius:4px;box-shadow:0 4px 30px rgba(0,0,0,.5)}
|
|
13
|
+
.imgflow-modal-close{position:absolute;top:1rem;right:1rem;
|
|
14
|
+
background:rgba(255,255,255,.2);border:none;color:#fff;font-size:2rem;
|
|
15
|
+
width:3rem;height:3rem;border-radius:50%;cursor:pointer;
|
|
16
|
+
display:flex;align-items:center;justify-content:center;line-height:1}
|
|
17
|
+
.imgflow-modal-close:hover{background:rgba(255,255,255,.4)}
|
|
18
|
+
@keyframes imgflow-fade{from{opacity:0}to{opacity:1}}
|
|
19
|
+
CSS
|
|
20
|
+
|
|
21
|
+
JS = <<~JS
|
|
22
|
+
(function(){
|
|
23
|
+
function openModal(src,alt){
|
|
24
|
+
var o=document.createElement('div');
|
|
25
|
+
o.className='imgflow-modal-overlay';
|
|
26
|
+
var i=document.createElement('img');
|
|
27
|
+
i.src=src;i.alt=alt||'';i.className='imgflow-modal-image';
|
|
28
|
+
var b=document.createElement('button');
|
|
29
|
+
b.className='imgflow-modal-close';b.setAttribute('aria-label','Close');
|
|
30
|
+
b.innerHTML='×';
|
|
31
|
+
o.appendChild(b);o.appendChild(i);document.body.appendChild(o);
|
|
32
|
+
function c(){document.body.removeChild(o);
|
|
33
|
+
document.removeEventListener('keydown',k);}
|
|
34
|
+
function k(e){if(e.key==='Escape')c();}
|
|
35
|
+
o.addEventListener('click',function(e){
|
|
36
|
+
if(e.target===o||e.target===b)c();});
|
|
37
|
+
document.addEventListener('keydown',k);}
|
|
38
|
+
document.addEventListener('click',function(e){
|
|
39
|
+
var t=e.target.closest('[data-imgflow-modal]');
|
|
40
|
+
if(!t)return;e.preventDefault();
|
|
41
|
+
openModal(t.getAttribute('href'),t.getAttribute('data-imgflow-alt'));});
|
|
42
|
+
})();
|
|
43
|
+
JS
|
|
44
|
+
|
|
45
|
+
def self.inject(html)
|
|
46
|
+
return html unless html&.include?("data-imgflow-modal")
|
|
47
|
+
|
|
48
|
+
style_tag = "<style>\n#{CSS}</style>"
|
|
49
|
+
script_tag = "<script>\n#{JS}</script>"
|
|
50
|
+
|
|
51
|
+
if html.include?("</head>")
|
|
52
|
+
html = html.sub("</head>", "#{style_tag}\n</head>")
|
|
53
|
+
html = html.sub("</body>", "#{script_tag}\n</body>") if html.include?("</body>")
|
|
54
|
+
elsif html.include?("</body>")
|
|
55
|
+
html = html.sub("</body>", "#{style_tag}\n#{script_tag}\n</body>")
|
|
56
|
+
else
|
|
57
|
+
html = "#{html}\n#{style_tag}\n#{script_tag}"
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
html
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Modal wrapping logic for HtmlGenerator โ extracted to keep HtmlGenerator
|
|
65
|
+
# under the RuboCop class length limit.
|
|
66
|
+
module ModalWrapper
|
|
67
|
+
# Formats that produce raw URLs/srcsets (not wrappable HTML elements)
|
|
68
|
+
NON_HTML_FORMATS = %w[direct_url naked_srcset].freeze
|
|
69
|
+
|
|
70
|
+
# Check if the current markup format produces an HTML element
|
|
71
|
+
def html_element?
|
|
72
|
+
!NON_HTML_FORMATS.include?(@markup_format)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Determine if modal behavior is enabled for this image
|
|
76
|
+
# Per-image modal:true/false overrides config default
|
|
77
|
+
# Modal is skipped when an explicit link is set
|
|
78
|
+
def modal_enabled?
|
|
79
|
+
return false if @attributes[:link]
|
|
80
|
+
|
|
81
|
+
modal_attr = @attributes[:modal]
|
|
82
|
+
return modal_attr.to_s == "true" if modal_attr
|
|
83
|
+
|
|
84
|
+
@config&.image_modal ? true : false
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Pick the best image path for the modal โ prefer the fallback format
|
|
88
|
+
# (e.g. jpg) for maximum browser compatibility
|
|
89
|
+
def modal_image_path
|
|
90
|
+
fallback_ext = @config&.fallback_format ? ".#{@config.fallback_format}" : ".jpg"
|
|
91
|
+
fallback = @results.find { |r| File.extname(r).downcase == fallback_ext }
|
|
92
|
+
fallback || @results.last
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Wrap HTML in modal trigger anchor
|
|
96
|
+
def wrap_with_modal(html)
|
|
97
|
+
modal_href = html_path(modal_image_path)
|
|
98
|
+
return html unless modal_href
|
|
99
|
+
|
|
100
|
+
data_attrs = " data-imgflow-modal"
|
|
101
|
+
alt = @attributes[:alt]
|
|
102
|
+
data_attrs += " data-imgflow-alt=\"#{escape_attr_value(alt)}\"" if alt
|
|
103
|
+
|
|
104
|
+
"<a href=\"#{modal_href}\"#{data_attrs}>#{html}</a>"
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
@@ -9,7 +9,7 @@ module JekyllImgFlow
|
|
|
9
9
|
# Define valid operation parameters and attribute types
|
|
10
10
|
OPERATION_PARAMS = %i[width height ratio aspect_ratio quality format formats
|
|
11
11
|
optimize level watermark opacity position keep preset].freeze
|
|
12
|
-
HTML_ATTRIBUTES = %i[alt class title loading].freeze
|
|
12
|
+
HTML_ATTRIBUTES = %i[alt class title loading link modal].freeze
|
|
13
13
|
|
|
14
14
|
# Simple operation mappings for single-parameter operations
|
|
15
15
|
SIMPLE_OPERATIONS = {
|
data/lib/jekyll-imgflow.rb
CHANGED
|
@@ -23,6 +23,7 @@ require_relative "jekyll-imgflow/provider_registry"
|
|
|
23
23
|
require_relative "jekyll-imgflow/build_time_processor"
|
|
24
24
|
require_relative "jekyll-imgflow/parser"
|
|
25
25
|
require_relative "jekyll-imgflow/tags/tag_registry"
|
|
26
|
+
require_relative "jekyll-imgflow/modal_assets"
|
|
26
27
|
require_relative "jekyll-imgflow/html_generator"
|
|
27
28
|
require_relative "jekyll-imgflow/imgflow_tag"
|
|
28
29
|
require_relative "jekyll-imgflow/picture_tag_adaptor"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: jekyll-imgflow
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Svend Gundestrup
|
|
@@ -74,6 +74,7 @@ files:
|
|
|
74
74
|
- lib/jekyll-imgflow/html_generator.rb
|
|
75
75
|
- lib/jekyll-imgflow/imgflow_tag.rb
|
|
76
76
|
- lib/jekyll-imgflow/manifest_manager.rb
|
|
77
|
+
- lib/jekyll-imgflow/modal_assets.rb
|
|
77
78
|
- lib/jekyll-imgflow/operation_processor.rb
|
|
78
79
|
- lib/jekyll-imgflow/parser.rb
|
|
79
80
|
- lib/jekyll-imgflow/path_resolver.rb
|