jekyll-uj-powertools 1.5.2 → 1.6.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.
- checksums.yaml +4 -4
- data/README.md +113 -4
- data/jekyll-uj-powertools.gemspec +2 -1
- data/lib/filters/main.rb +37 -19
- data/lib/generators/inject-properties.rb +29 -7
- data/lib/hooks/inject-properties.rb +10 -0
- data/lib/hooks/markdown-images.rb +40 -0
- data/lib/jekyll-uj-powertools.rb +12 -1
- data/lib/tags/fake_comments.rb +72 -0
- data/lib/tags/icon.rb +262 -0
- data/lib/tags/iffalsy.rb +38 -0
- data/lib/tags/iftruthy.rb +38 -0
- data/lib/tags/image.rb +208 -0
- data/lib/tags/language.rb +301 -0
- data/lib/tags/member.rb +204 -0
- data/lib/tags/post.rb +258 -0
- data/lib/tags/readtime.rb +73 -0
- data/lib/tags/social.rb +84 -0
- data/lib/tags/translation_url.rb +154 -0
- metadata +28 -3
- data/lib/tags/ifistruthy.rb +0 -161
data/lib/tags/icon.rb
ADDED
@@ -0,0 +1,262 @@
|
|
1
|
+
# Libraries
|
2
|
+
require "jekyll"
|
3
|
+
|
4
|
+
module Jekyll
|
5
|
+
class UJIconTag < Liquid::Tag
|
6
|
+
# Default icon to show when requested icon is not found
|
7
|
+
DEFAULT_ICON = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M320 64C334.7 64 348.2 72.1 355.2 85L571.2 485C577.9 497.4 577.6 512.4 570.4 524.5C563.2 536.6 550.1 544 536 544L104 544C89.9 544 76.9 536.6 69.6 524.5C62.3 512.4 62.1 497.4 68.8 485L284.8 85C291.8 72.1 305.3 64 320 64zM320 232C306.7 232 296 242.7 296 256L296 368C296 381.3 306.7 392 320 392C333.3 392 344 381.3 344 368L344 256C344 242.7 333.3 232 320 232zM346.7 448C347.3 438.1 342.4 428.7 333.9 423.5C325.4 418.4 314.7 418.4 306.2 423.5C297.7 428.7 292.8 438.1 293.4 448C292.8 457.9 297.7 467.3 306.2 472.5C314.7 477.6 325.4 477.6 333.9 472.5C342.4 467.3 347.3 457.9 346.7 448z"/></svg>'
|
8
|
+
|
9
|
+
# Language code to country code mapping for flags
|
10
|
+
LANGUAGE_TO_COUNTRY = {
|
11
|
+
'en' => 'us', # English -> United States (could also be 'gb' for Great Britain)
|
12
|
+
'es' => 'es', # Spanish -> Spain
|
13
|
+
'fr' => 'fr', # French -> France
|
14
|
+
'de' => 'de', # German -> Germany
|
15
|
+
'it' => 'it', # Italian -> Italy
|
16
|
+
'pt' => 'pt', # Portuguese -> Portugal
|
17
|
+
'ru' => 'ru', # Russian -> Russia
|
18
|
+
'ja' => 'jp', # Japanese -> Japan
|
19
|
+
'ko' => 'kr', # Korean -> South Korea
|
20
|
+
'zh' => 'cn', # Chinese -> China
|
21
|
+
'ar' => 'sa', # Arabic -> Saudi Arabia
|
22
|
+
'hi' => 'in', # Hindi -> India
|
23
|
+
'tr' => 'tr', # Turkish -> Turkey
|
24
|
+
'pl' => 'pl', # Polish -> Poland
|
25
|
+
'nl' => 'nl', # Dutch -> Netherlands
|
26
|
+
'sv' => 'se', # Swedish -> Sweden
|
27
|
+
'no' => 'no', # Norwegian -> Norway
|
28
|
+
'da' => 'dk', # Danish -> Denmark
|
29
|
+
'fi' => 'fi', # Finnish -> Finland
|
30
|
+
'he' => 'il', # Hebrew -> Israel
|
31
|
+
'th' => 'th', # Thai -> Thailand
|
32
|
+
'vi' => 'vn', # Vietnamese -> Vietnam
|
33
|
+
'uk' => 'ua', # Ukrainian -> Ukraine
|
34
|
+
'cs' => 'cz', # Czech -> Czech Republic
|
35
|
+
'hu' => 'hu', # Hungarian -> Hungary
|
36
|
+
'ro' => 'ro', # Romanian -> Romania
|
37
|
+
'bg' => 'bg', # Bulgarian -> Bulgaria
|
38
|
+
'hr' => 'hr', # Croatian -> Croatia
|
39
|
+
'sk' => 'sk', # Slovak -> Slovakia
|
40
|
+
'sl' => 'si', # Slovenian -> Slovenia
|
41
|
+
'et' => 'ee', # Estonian -> Estonia
|
42
|
+
'lv' => 'lv', # Latvian -> Latvia
|
43
|
+
'lt' => 'lt', # Lithuanian -> Lithuania
|
44
|
+
'mt' => 'mt', # Maltese -> Malta
|
45
|
+
'ga' => 'ie', # Irish -> Ireland
|
46
|
+
'cy' => 'gb', # Welsh -> Great Britain
|
47
|
+
'ca' => 'es', # Catalan -> Spain (could also be ad for Andorra)
|
48
|
+
'eu' => 'es', # Basque -> Spain
|
49
|
+
'gl' => 'es', # Galician -> Spain
|
50
|
+
}
|
51
|
+
|
52
|
+
# Font Awesome size mappings - commented out for now
|
53
|
+
# FA_SIZES = {
|
54
|
+
# 'fa-2xs' => '0.625em',
|
55
|
+
# 'fa-xs' => '0.75em',
|
56
|
+
# 'fa-sm' => '0.875em',
|
57
|
+
# 'fa-md' => '1em',
|
58
|
+
# 'fa-lg' => '1.25em',
|
59
|
+
# 'fa-xl' => '1.5em',
|
60
|
+
# 'fa-2xl' => '2em'
|
61
|
+
# }
|
62
|
+
|
63
|
+
# Cache for loaded icons to improve performance
|
64
|
+
@@icon_cache = {}
|
65
|
+
|
66
|
+
def initialize(tag_name, markup, tokens)
|
67
|
+
super
|
68
|
+
@markup = markup.strip
|
69
|
+
end
|
70
|
+
|
71
|
+
def render(context)
|
72
|
+
# Parse arguments that can be quoted or unquoted
|
73
|
+
parts = parse_arguments(@markup)
|
74
|
+
icon_name_input = parts[0]
|
75
|
+
css_classes = parts[1]
|
76
|
+
|
77
|
+
# Check if the input was originally quoted (literal string)
|
78
|
+
is_quoted = @markup.strip.match(/^['"]/)
|
79
|
+
|
80
|
+
# If quoted, use as literal. Otherwise, try to resolve as variable
|
81
|
+
if is_quoted
|
82
|
+
icon_name = icon_name_input
|
83
|
+
else
|
84
|
+
# Try to resolve as a variable
|
85
|
+
icon_name = resolve_variable(context, icon_name_input)
|
86
|
+
# If it didn't resolve to a string, use the input as literal
|
87
|
+
icon_name = icon_name_input if icon_name.nil? || !icon_name.is_a?(String)
|
88
|
+
end
|
89
|
+
|
90
|
+
# Strip quotes from resolved icon name if present
|
91
|
+
if icon_name.is_a?(String) && icon_name.match(/^['"].*['"]$/)
|
92
|
+
icon_name = icon_name[1..-2]
|
93
|
+
end
|
94
|
+
|
95
|
+
# Get site from context
|
96
|
+
site = context.registers[:site]
|
97
|
+
return '' unless site
|
98
|
+
|
99
|
+
# Load the icon SVG from file
|
100
|
+
icon_svg = load_icon_from_file(site, icon_name.to_s)
|
101
|
+
return '' unless icon_svg
|
102
|
+
|
103
|
+
# Process SVG to inject required attributes
|
104
|
+
processed_svg = inject_svg_attributes(icon_svg)
|
105
|
+
|
106
|
+
# Determine CSS classes
|
107
|
+
# font_size = '1em' # default
|
108
|
+
# if size_input && !size_input.empty?
|
109
|
+
# # Check if it's a Font Awesome preset size
|
110
|
+
# font_size = FA_SIZES[size_input] || size_input
|
111
|
+
# end
|
112
|
+
|
113
|
+
# Wrap in i tag with CSS classes (always include 'fa' class)
|
114
|
+
if css_classes && !css_classes.empty?
|
115
|
+
"<i class=\"fa #{css_classes}\">#{processed_svg}</i>"
|
116
|
+
else
|
117
|
+
"<i class=\"fa\">#{processed_svg}</i>"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
private
|
122
|
+
|
123
|
+
def inject_svg_attributes(svg_content)
|
124
|
+
# Inject width, height, and fill attributes into the SVG tag
|
125
|
+
if svg_content.include?('<svg')
|
126
|
+
# Replace the opening SVG tag to include our required attributes
|
127
|
+
svg_content.sub(/<svg([^>]*)>/) do |match|
|
128
|
+
existing_attrs = $1
|
129
|
+
# Only add attributes if they don't already exist
|
130
|
+
attrs_to_add = []
|
131
|
+
attrs_to_add << 'width="1em"' unless existing_attrs.include?('width=')
|
132
|
+
attrs_to_add << 'height="1em"' unless existing_attrs.include?('height=')
|
133
|
+
attrs_to_add << 'fill="currentColor"' unless existing_attrs.include?('fill=')
|
134
|
+
|
135
|
+
if attrs_to_add.any?
|
136
|
+
"<svg#{existing_attrs} #{attrs_to_add.join(' ')}>"
|
137
|
+
else
|
138
|
+
match
|
139
|
+
end
|
140
|
+
end
|
141
|
+
else
|
142
|
+
svg_content
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def load_icon_from_file(site, icon_name)
|
147
|
+
# Get the style from site config
|
148
|
+
style = site.config.dig('icons', 'style') || 'solid'
|
149
|
+
|
150
|
+
# Create cache key
|
151
|
+
cache_key = "#{style}/#{icon_name}"
|
152
|
+
|
153
|
+
# Return cached version if available
|
154
|
+
return @@icon_cache[cache_key] if @@icon_cache.key?(cache_key)
|
155
|
+
|
156
|
+
# Try to load icon from multiple sources in order
|
157
|
+
icon_svg = try_load_fontawesome_icon(icon_name, style) ||
|
158
|
+
try_load_flag_icon(icon_name) ||
|
159
|
+
DEFAULT_ICON
|
160
|
+
|
161
|
+
# Cache the result
|
162
|
+
@@icon_cache[cache_key] = icon_svg
|
163
|
+
return icon_svg
|
164
|
+
end
|
165
|
+
|
166
|
+
def try_load_fontawesome_icon(icon_name, style)
|
167
|
+
# Build file path for the configured style
|
168
|
+
icon_path = File.join(Dir.pwd, 'node_modules', 'ultimate-jekyll-manager', 'assets', 'icons', 'font-awesome', style, "#{icon_name}.svg")
|
169
|
+
|
170
|
+
# Read file if it exists in the configured style
|
171
|
+
if File.exist?(icon_path)
|
172
|
+
return File.read(icon_path)
|
173
|
+
end
|
174
|
+
|
175
|
+
# If not found and style is not 'brands', try brands style as fallback
|
176
|
+
if style != 'brands'
|
177
|
+
brands_path = File.join(Dir.pwd, 'node_modules', 'ultimate-jekyll-manager', 'assets', 'icons', 'font-awesome', 'brands', "#{icon_name}.svg")
|
178
|
+
|
179
|
+
if File.exist?(brands_path)
|
180
|
+
return File.read(brands_path)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
nil
|
185
|
+
end
|
186
|
+
|
187
|
+
def try_load_flag_icon(icon_name)
|
188
|
+
# First try direct country code (e.g., 'us', 'gb')
|
189
|
+
flag_path = File.join(Dir.pwd, 'node_modules', 'ultimate-jekyll-manager', 'assets', 'icons', 'flags', 'modern-square', "#{icon_name}.svg")
|
190
|
+
|
191
|
+
if File.exist?(flag_path)
|
192
|
+
return File.read(flag_path)
|
193
|
+
end
|
194
|
+
|
195
|
+
# If not found, try language code to country code mapping (e.g., 'en' -> 'us')
|
196
|
+
country_code = LANGUAGE_TO_COUNTRY[icon_name.downcase]
|
197
|
+
if country_code
|
198
|
+
mapped_flag_path = File.join(Dir.pwd, 'node_modules', 'ultimate-jekyll-manager', 'assets', 'icons', 'flags', 'modern-square', "#{country_code}.svg")
|
199
|
+
|
200
|
+
if File.exist?(mapped_flag_path)
|
201
|
+
return File.read(mapped_flag_path)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
nil
|
206
|
+
end
|
207
|
+
|
208
|
+
def parse_arguments(markup)
|
209
|
+
# Parse arguments that can be quoted or unquoted
|
210
|
+
# Examples: award, fa-md OR 'award', 'fa-md' OR myVar, "2em"
|
211
|
+
args = []
|
212
|
+
current_arg = ''
|
213
|
+
in_quotes = false
|
214
|
+
quote_char = nil
|
215
|
+
|
216
|
+
markup.each_char.with_index do |char, i|
|
217
|
+
if !in_quotes && (char == '"' || char == "'")
|
218
|
+
# Start of quoted string
|
219
|
+
in_quotes = true
|
220
|
+
quote_char = char
|
221
|
+
elsif in_quotes && char == quote_char
|
222
|
+
# End of quoted string
|
223
|
+
in_quotes = false
|
224
|
+
quote_char = nil
|
225
|
+
elsif !in_quotes && char == ','
|
226
|
+
# Argument separator
|
227
|
+
args << current_arg.strip
|
228
|
+
current_arg = ''
|
229
|
+
else
|
230
|
+
# Regular character
|
231
|
+
current_arg += char
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
# Add the last argument
|
236
|
+
args << current_arg.strip if current_arg.strip.length > 0
|
237
|
+
|
238
|
+
args
|
239
|
+
end
|
240
|
+
|
241
|
+
def resolve_variable(context, variable_name)
|
242
|
+
# Handle nested variable access like page.icon
|
243
|
+
parts = variable_name.split('.')
|
244
|
+
current = context
|
245
|
+
|
246
|
+
parts.each do |part|
|
247
|
+
if current.respond_to?(:[])
|
248
|
+
current = current[part]
|
249
|
+
elsif current.respond_to?(:key?) && current.key?(part)
|
250
|
+
current = current[part]
|
251
|
+
else
|
252
|
+
return nil
|
253
|
+
end
|
254
|
+
return nil if current.nil?
|
255
|
+
end
|
256
|
+
|
257
|
+
current
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
Liquid::Template.register_tag('uj_icon', Jekyll::UJIconTag)
|
data/lib/tags/iffalsy.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# Libraries
|
2
|
+
# ...
|
3
|
+
|
4
|
+
# Tag
|
5
|
+
module Jekyll
|
6
|
+
module UJPowertools
|
7
|
+
class IfFalsyTag < Liquid::Block
|
8
|
+
def initialize(tag_name, markup, tokens)
|
9
|
+
super
|
10
|
+
@variable = markup.strip
|
11
|
+
end
|
12
|
+
|
13
|
+
def render(context)
|
14
|
+
# Use Liquid's variable lookup to handle nested properties
|
15
|
+
value = context.scopes.last[@variable] || context[@variable]
|
16
|
+
|
17
|
+
# For nested properties like page.my.variable
|
18
|
+
if @variable.include?('.')
|
19
|
+
parts = @variable.split('.')
|
20
|
+
value = context[parts.first]
|
21
|
+
parts[1..-1].each do |part|
|
22
|
+
value = value.is_a?(Hash) ? value[part] : nil
|
23
|
+
break if value.nil?
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Check if the value is falsy (nil, false, empty string, or 0)
|
28
|
+
if value.nil? || value == false || value == "" || value == 0
|
29
|
+
super
|
30
|
+
else
|
31
|
+
""
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
Liquid::Template.register_tag('iffalsy', Jekyll::UJPowertools::IfFalsyTag)
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# Libraries
|
2
|
+
# ...
|
3
|
+
|
4
|
+
# Tag
|
5
|
+
module Jekyll
|
6
|
+
module UJPowertools
|
7
|
+
class IfTruthyTag < Liquid::Block
|
8
|
+
def initialize(tag_name, markup, tokens)
|
9
|
+
super
|
10
|
+
@variable = markup.strip
|
11
|
+
end
|
12
|
+
|
13
|
+
def render(context)
|
14
|
+
# Use Liquid's variable lookup to handle nested properties
|
15
|
+
value = context.scopes.last[@variable] || context[@variable]
|
16
|
+
|
17
|
+
# For nested properties like page.my.variable
|
18
|
+
if @variable.include?('.')
|
19
|
+
parts = @variable.split('.')
|
20
|
+
value = context[parts.first]
|
21
|
+
parts[1..-1].each do |part|
|
22
|
+
value = value.is_a?(Hash) ? value[part] : nil
|
23
|
+
break if value.nil?
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Check if the value is truthy (not nil, not false, not empty string, not 0)
|
28
|
+
if value && value != false && value != "" && value != 0
|
29
|
+
super
|
30
|
+
else
|
31
|
+
""
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
Liquid::Template.register_tag('iftruthy', Jekyll::UJPowertools::IfTruthyTag)
|
data/lib/tags/image.rb
ADDED
@@ -0,0 +1,208 @@
|
|
1
|
+
# Libraries
|
2
|
+
require "jekyll"
|
3
|
+
|
4
|
+
module Jekyll
|
5
|
+
class UJImageTag < Liquid::Tag
|
6
|
+
def initialize(tag_name, markup, tokens)
|
7
|
+
super
|
8
|
+
@markup = markup.strip
|
9
|
+
end
|
10
|
+
|
11
|
+
def render(context)
|
12
|
+
# Parse arguments
|
13
|
+
args = parse_arguments(@markup)
|
14
|
+
src_input = args[0]
|
15
|
+
options = parse_options(args[1..-1])
|
16
|
+
|
17
|
+
# Resolve source path
|
18
|
+
src = resolve_variable(context, src_input)
|
19
|
+
return '' unless src
|
20
|
+
|
21
|
+
# Check if this is an external URL
|
22
|
+
is_external = !!(src =~ /^https?:\/\//)
|
23
|
+
|
24
|
+
if is_external
|
25
|
+
# For external URLs, just create a simple responsive img tag
|
26
|
+
build_external_image(src, options)
|
27
|
+
else
|
28
|
+
# Extract file extension
|
29
|
+
extension = File.extname(src)
|
30
|
+
src_path = src.chomp(extension)
|
31
|
+
|
32
|
+
# Determine max width
|
33
|
+
max_width = options['max_width'] || options['max-width'] || false
|
34
|
+
max_width = max_width.to_s if max_width
|
35
|
+
|
36
|
+
# Build picture element for local images
|
37
|
+
build_picture_element(src, src_path, extension, max_width, options)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def parse_arguments(markup)
|
44
|
+
args = []
|
45
|
+
current_arg = ''
|
46
|
+
in_quotes = false
|
47
|
+
quote_char = nil
|
48
|
+
|
49
|
+
markup.each_char do |char|
|
50
|
+
if !in_quotes && (char == '"' || char == "'")
|
51
|
+
in_quotes = true
|
52
|
+
quote_char = char
|
53
|
+
current_arg += char
|
54
|
+
elsif in_quotes && char == quote_char
|
55
|
+
in_quotes = false
|
56
|
+
quote_char = nil
|
57
|
+
current_arg += char
|
58
|
+
elsif !in_quotes && char == ','
|
59
|
+
args << current_arg.strip
|
60
|
+
current_arg = ''
|
61
|
+
else
|
62
|
+
current_arg += char
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
args << current_arg.strip if current_arg.strip.length > 0
|
67
|
+
args
|
68
|
+
end
|
69
|
+
|
70
|
+
def parse_options(option_args)
|
71
|
+
options = {}
|
72
|
+
|
73
|
+
option_args.each do |arg|
|
74
|
+
if arg.include?('=')
|
75
|
+
key, value = arg.split('=', 2)
|
76
|
+
key = key.strip.gsub(/^['"]|['"]$/, '')
|
77
|
+
value = value.strip.gsub(/^['"]|['"]$/, '')
|
78
|
+
options[key] = value
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
options
|
83
|
+
end
|
84
|
+
|
85
|
+
def resolve_variable(context, variable_input)
|
86
|
+
# Strip quotes if present
|
87
|
+
if variable_input.match(/^['"]/)
|
88
|
+
variable_input.gsub(/^['"]|['"]$/, '')
|
89
|
+
else
|
90
|
+
# Resolve as variable
|
91
|
+
parts = variable_input.split('.')
|
92
|
+
current = context
|
93
|
+
|
94
|
+
parts.each do |part|
|
95
|
+
return nil unless current.respond_to?(:[]) || current.is_a?(Hash)
|
96
|
+
current = current[part]
|
97
|
+
return nil if current.nil?
|
98
|
+
end
|
99
|
+
|
100
|
+
current
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def build_picture_element(src, src_path, extension, max_width, options)
|
105
|
+
html = "<picture>\n"
|
106
|
+
|
107
|
+
# Add WebP sources unless disabled
|
108
|
+
unless options['webp'] == 'false'
|
109
|
+
html += build_webp_sources(src_path, max_width)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Add original format sources
|
113
|
+
html += build_original_sources(src_path, extension, max_width, src)
|
114
|
+
|
115
|
+
# Build img tag
|
116
|
+
alt = options['alt'] || ''
|
117
|
+
css_class = options['class'] || ''
|
118
|
+
style = options['style'] || ''
|
119
|
+
width = options['width'] || ''
|
120
|
+
height = options['height'] || ''
|
121
|
+
|
122
|
+
html += "<img\n"
|
123
|
+
html += "src=\"data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\"\n"
|
124
|
+
html += "data-lazy=\"@src #{src}\"\n"
|
125
|
+
html += "class=\"#{css_class}\"\n" unless css_class.empty?
|
126
|
+
html += "alt=\"#{alt}\"\n"
|
127
|
+
html += "style=\"#{style}\"\n" unless style.empty?
|
128
|
+
html += "width=\"#{width}\"\n" unless width.empty?
|
129
|
+
html += "height=\"#{height}\"\n" unless height.empty?
|
130
|
+
html += ">\n"
|
131
|
+
html += "</picture>"
|
132
|
+
|
133
|
+
html
|
134
|
+
end
|
135
|
+
|
136
|
+
def build_webp_sources(src_path, max_width)
|
137
|
+
html = ""
|
138
|
+
|
139
|
+
case max_width
|
140
|
+
when "320"
|
141
|
+
html += "<source data-lazy=\"@srcset #{src_path}-320px.webp\" type=\"image/webp\">\n"
|
142
|
+
when "640"
|
143
|
+
html += "<source data-lazy=\"@srcset #{src_path}-320px.webp\" media=\"(max-width: 320px)\" type=\"image/webp\">\n"
|
144
|
+
html += "<source data-lazy=\"@srcset #{src_path}-640px.webp\" type=\"image/webp\">\n"
|
145
|
+
when "1024"
|
146
|
+
html += "<source data-lazy=\"@srcset #{src_path}-320px.webp\" media=\"(max-width: 320px)\" type=\"image/webp\">\n"
|
147
|
+
html += "<source data-lazy=\"@srcset #{src_path}-640px.webp\" media=\"(max-width: 640px)\" type=\"image/webp\">\n"
|
148
|
+
html += "<source data-lazy=\"@srcset #{src_path}-1024px.webp\" type=\"image/webp\">\n"
|
149
|
+
else
|
150
|
+
html += "<source data-lazy=\"@srcset #{src_path}-320px.webp\" media=\"(max-width: 320px)\" type=\"image/webp\">\n"
|
151
|
+
html += "<source data-lazy=\"@srcset #{src_path}-640px.webp\" media=\"(max-width: 640px)\" type=\"image/webp\">\n"
|
152
|
+
html += "<source data-lazy=\"@srcset #{src_path}-1024px.webp\" media=\"(max-width: 1024px)\" type=\"image/webp\">\n"
|
153
|
+
html += "<source data-lazy=\"@srcset #{src_path}.webp\" type=\"image/webp\">\n"
|
154
|
+
end
|
155
|
+
|
156
|
+
html
|
157
|
+
end
|
158
|
+
|
159
|
+
def build_original_sources(src_path, extension, max_width, src)
|
160
|
+
html = ""
|
161
|
+
|
162
|
+
case max_width
|
163
|
+
when "320"
|
164
|
+
html += "<source data-lazy=\"@srcset #{src_path}-320px#{extension}\">\n"
|
165
|
+
when "640"
|
166
|
+
html += "<source data-lazy=\"@srcset #{src_path}-320px#{extension}\" media=\"(max-width: 320px)\">\n"
|
167
|
+
html += "<source data-lazy=\"@srcset #{src_path}-640px#{extension}\">\n"
|
168
|
+
when "1024"
|
169
|
+
html += "<source data-lazy=\"@srcset #{src_path}-320px#{extension}\" media=\"(max-width: 320px)\">\n"
|
170
|
+
html += "<source data-lazy=\"@srcset #{src_path}-640px#{extension}\" media=\"(max-width: 640px)\">\n"
|
171
|
+
html += "<source data-lazy=\"@srcset #{src_path}-1024px#{extension}\">\n"
|
172
|
+
else
|
173
|
+
html += "<source data-lazy=\"@srcset #{src_path}-320px#{extension}\" media=\"(max-width: 320px)\">\n"
|
174
|
+
html += "<source data-lazy=\"@srcset #{src_path}-640px#{extension}\" media=\"(max-width: 640px)\">\n"
|
175
|
+
html += "<source data-lazy=\"@srcset #{src_path}-1024px#{extension}\" media=\"(max-width: 1024px)\">\n"
|
176
|
+
html += "<source data-lazy=\"@srcset #{src}\" media=\"(min-width: 1025px)\">\n"
|
177
|
+
end
|
178
|
+
|
179
|
+
html
|
180
|
+
end
|
181
|
+
|
182
|
+
def build_external_image(src, options)
|
183
|
+
# Build responsive img tag for external URLs
|
184
|
+
alt = options['alt'] || ''
|
185
|
+
css_class = options['class'] || ''
|
186
|
+
style = options['style'] || ''
|
187
|
+
width = options['width'] || ''
|
188
|
+
height = options['height'] || ''
|
189
|
+
loading = options['loading'] || 'lazy'
|
190
|
+
|
191
|
+
# Build img tag on a single line to prevent markdown parsing issues
|
192
|
+
html = "<img"
|
193
|
+
html += " src=\"data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\""
|
194
|
+
html += " data-lazy=\"@src #{src}\""
|
195
|
+
html += " class=\"#{css_class}\"" unless css_class.empty?
|
196
|
+
html += " alt=\"#{alt}\""
|
197
|
+
html += " style=\"#{style}\"" unless style.empty?
|
198
|
+
html += " width=\"#{width}\"" unless width.empty?
|
199
|
+
html += " height=\"#{height}\"" unless height.empty?
|
200
|
+
html += " loading=\"#{loading}\""
|
201
|
+
html += ">"
|
202
|
+
|
203
|
+
html
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
Liquid::Template.register_tag('uj_image', Jekyll::UJImageTag)
|