jekyll-uj-powertools 1.6.0 → 1.6.2
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 +94 -0
- data/jekyll-uj-powertools.gemspec +2 -1
- data/lib/filters/main.rb +36 -18
- data/lib/generators/inject-properties.rb +23 -1
- 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/iffile.rb +70 -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 +27 -2
data/lib/tags/iffile.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
# Libraries
|
2
|
+
# ...
|
3
|
+
|
4
|
+
# Tag
|
5
|
+
module Jekyll
|
6
|
+
module UJPowertools
|
7
|
+
class IfFileTag < Liquid::Block
|
8
|
+
def initialize(tag_name, markup, tokens)
|
9
|
+
super
|
10
|
+
@path = markup.strip
|
11
|
+
end
|
12
|
+
|
13
|
+
def render(context)
|
14
|
+
# Get the site object
|
15
|
+
site = context.registers[:site]
|
16
|
+
|
17
|
+
puts "[iffile] Input markup: #{@path}"
|
18
|
+
|
19
|
+
# Resolve the path variable if it's a variable name
|
20
|
+
path = context[@path] || @path
|
21
|
+
puts "[iffile] After context lookup: #{path}"
|
22
|
+
|
23
|
+
# Handle nested variables like page.css_path
|
24
|
+
if @path.include?('.')
|
25
|
+
parts = @path.split('.')
|
26
|
+
path = context[parts.first]
|
27
|
+
parts[1..-1].each do |part|
|
28
|
+
path = path.is_a?(Hash) ? path[part] : nil
|
29
|
+
break if path.nil?
|
30
|
+
end
|
31
|
+
puts "[iffile] After nested lookup: #{path}"
|
32
|
+
end
|
33
|
+
|
34
|
+
# Ensure path starts with /
|
35
|
+
path = "/#{path}" unless path.to_s.start_with?('/')
|
36
|
+
puts "[iffile] Final path to check: #{path}"
|
37
|
+
|
38
|
+
# Check if file exists in static_files
|
39
|
+
puts "[iffile] Path to check: #{path}"
|
40
|
+
|
41
|
+
# Debug: show first few static files
|
42
|
+
puts "[iffile] Sample static files (first 5 CSS files):"
|
43
|
+
site.static_files.select { |f| f.relative_path.end_with?('.css') }.first(5).each do |file|
|
44
|
+
puts " - #{file.relative_path}"
|
45
|
+
end
|
46
|
+
|
47
|
+
file_exists = site.static_files.any? { |file|
|
48
|
+
# Compare both with and without leading slash
|
49
|
+
matches = file.relative_path == path ||
|
50
|
+
file.relative_path == path[1..-1] ||
|
51
|
+
"/#{file.relative_path}" == path
|
52
|
+
if matches
|
53
|
+
puts "[iffile] FOUND MATCH: #{file.relative_path}"
|
54
|
+
end
|
55
|
+
matches
|
56
|
+
}
|
57
|
+
|
58
|
+
puts "[iffile] File exists: #{file_exists}"
|
59
|
+
|
60
|
+
if file_exists
|
61
|
+
super
|
62
|
+
else
|
63
|
+
""
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
Liquid::Template.register_tag('iffile', Jekyll::UJPowertools::IfFileTag)
|
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)
|
@@ -0,0 +1,301 @@
|
|
1
|
+
# Libraries
|
2
|
+
require "jekyll"
|
3
|
+
|
4
|
+
module Jekyll
|
5
|
+
class UJLanguageTag < Liquid::Tag
|
6
|
+
# Language mappings: ISO code => [English name, Native name]
|
7
|
+
LANGUAGE_MAPPINGS = {
|
8
|
+
'aa' => ['Afar', 'Afaraf'],
|
9
|
+
'ab' => ['Abkhazian', 'аҧсуа бызшәа'],
|
10
|
+
'ae' => ['Avestan', 'avesta'],
|
11
|
+
'af' => ['Afrikaans', 'Afrikaans'],
|
12
|
+
'ak' => ['Akan', 'Akan'],
|
13
|
+
'am' => ['Amharic', 'አማርኛ'],
|
14
|
+
'an' => ['Aragonese', 'aragonés'],
|
15
|
+
'ar' => ['Arabic', 'العربية'],
|
16
|
+
'as' => ['Assamese', 'অসমীয়া'],
|
17
|
+
'av' => ['Avaric', 'авар мацӀ'],
|
18
|
+
'ay' => ['Aymara', 'aymar aru'],
|
19
|
+
'az' => ['Azerbaijani', 'azərbaycan dili'],
|
20
|
+
'ba' => ['Bashkir', 'башҡорт теле'],
|
21
|
+
'be' => ['Belarusian', 'беларуская мова'],
|
22
|
+
'bg' => ['Bulgarian', 'български език'],
|
23
|
+
'bh' => ['Bihari languages', 'भोजपुरी'],
|
24
|
+
'bi' => ['Bislama', 'Bislama'],
|
25
|
+
'bm' => ['Bambara', 'bamanankan'],
|
26
|
+
'bn' => ['Bengali', 'বাংলা'],
|
27
|
+
'bo' => ['Tibetan', 'བོད་ཡིག'],
|
28
|
+
'br' => ['Breton', 'brezhoneg'],
|
29
|
+
'bs' => ['Bosnian', 'bosanski jezik'],
|
30
|
+
'ca' => ['Catalan', 'català'],
|
31
|
+
'ce' => ['Chechen', 'нохчийн мотт'],
|
32
|
+
'ch' => ['Chamorro', 'Chamoru'],
|
33
|
+
'co' => ['Corsican', 'corsu'],
|
34
|
+
'cr' => ['Cree', 'ᓀᐦᐃᔭᐍᐏᐣ'],
|
35
|
+
'cs' => ['Czech', 'čeština'],
|
36
|
+
'cu' => ['Church Slavic', 'ѩзыкъ словѣньскъ'],
|
37
|
+
'cv' => ['Chuvash', 'чӑваш чӗлхи'],
|
38
|
+
'cy' => ['Welsh', 'Cymraeg'],
|
39
|
+
'da' => ['Danish', 'dansk'],
|
40
|
+
'de' => ['German', 'Deutsch'],
|
41
|
+
'dv' => ['Divehi', 'ދިވެހި'],
|
42
|
+
'dz' => ['Dzongkha', 'རྫོང་ཁ'],
|
43
|
+
'ee' => ['Ewe', 'Eʋegbe'],
|
44
|
+
'el' => ['Greek', 'ελληνικά'],
|
45
|
+
'en' => ['English', 'English'],
|
46
|
+
'eo' => ['Esperanto', 'Esperanto'],
|
47
|
+
'es' => ['Spanish', 'español'],
|
48
|
+
'et' => ['Estonian', 'eesti'],
|
49
|
+
'eu' => ['Basque', 'euskera'],
|
50
|
+
'fa' => ['Persian', 'فارسی'],
|
51
|
+
'ff' => ['Fulah', 'Fulfulde'],
|
52
|
+
'fi' => ['Finnish', 'suomi'],
|
53
|
+
'fj' => ['Fijian', 'vosa Vakaviti'],
|
54
|
+
'fo' => ['Faroese', 'føroyskt'],
|
55
|
+
'fr' => ['French', 'français'],
|
56
|
+
'fy' => ['Western Frisian', 'Frysk'],
|
57
|
+
'ga' => ['Irish', 'Gaeilge'],
|
58
|
+
'gd' => ['Gaelic', 'Gàidhlig'],
|
59
|
+
'gl' => ['Galician', 'galego'],
|
60
|
+
'gn' => ['Guarani', 'Avañe\'ẽ'],
|
61
|
+
'gu' => ['Gujarati', 'ગુજરાતી'],
|
62
|
+
'gv' => ['Manx', 'Gaelg'],
|
63
|
+
'ha' => ['Hausa', 'هَوُسَ'],
|
64
|
+
'he' => ['Hebrew', 'עברית'],
|
65
|
+
'hi' => ['Hindi', 'हिन्दी'],
|
66
|
+
'ho' => ['Hiri Motu', 'Hiri Motu'],
|
67
|
+
'hr' => ['Croatian', 'hrvatski jezik'],
|
68
|
+
'ht' => ['Haitian', 'Kreyòl ayisyen'],
|
69
|
+
'hu' => ['Hungarian', 'magyar'],
|
70
|
+
'hy' => ['Armenian', 'Հայերեն'],
|
71
|
+
'hz' => ['Herero', 'Otjiherero'],
|
72
|
+
'ia' => ['Interlingua', 'Interlingua'],
|
73
|
+
'id' => ['Indonesian', 'Bahasa Indonesia'],
|
74
|
+
'ie' => ['Interlingue', 'Interlingue'],
|
75
|
+
'ig' => ['Igbo', 'Asụsụ Igbo'],
|
76
|
+
'ii' => ['Nuosu', 'ꆈꌠ꒿ Nuosuhxop'],
|
77
|
+
'ik' => ['Inupiaq', 'Iñupiaq'],
|
78
|
+
'io' => ['Ido', 'Ido'],
|
79
|
+
'is' => ['Icelandic', 'Íslenska'],
|
80
|
+
'it' => ['Italian', 'italiano'],
|
81
|
+
'iu' => ['Inuktitut', 'ᐃᓄᒃᑎᑐᑦ'],
|
82
|
+
'ja' => ['Japanese', '日本語'],
|
83
|
+
'jv' => ['Javanese', 'basa Jawa'],
|
84
|
+
'ka' => ['Georgian', 'ქართული'],
|
85
|
+
'kg' => ['Kongo', 'Kikongo'],
|
86
|
+
'ki' => ['Kikuyu', 'Gĩkũyũ'],
|
87
|
+
'kj' => ['Kwanyama', 'Kuanyama'],
|
88
|
+
'kk' => ['Kazakh', 'қазақ тілі'],
|
89
|
+
'kl' => ['Kalaallisut', 'kalaallisut'],
|
90
|
+
'km' => ['Khmer', 'ខ្មែរ'],
|
91
|
+
'kn' => ['Kannada', 'ಕನ್ನಡ'],
|
92
|
+
'ko' => ['Korean', '한국어'],
|
93
|
+
'kr' => ['Kanuri', 'Kanuri'],
|
94
|
+
'ks' => ['Kashmiri', 'कश्मीरी'],
|
95
|
+
'ku' => ['Kurdish', 'Kurdî'],
|
96
|
+
'kv' => ['Komi', 'коми кыв'],
|
97
|
+
'kw' => ['Cornish', 'Kernewek'],
|
98
|
+
'ky' => ['Kirghiz', 'Кыргызча'],
|
99
|
+
'la' => ['Latin', 'latine'],
|
100
|
+
'lb' => ['Luxembourgish', 'Lëtzebuergesch'],
|
101
|
+
'lg' => ['Ganda', 'Luganda'],
|
102
|
+
'li' => ['Limburgish', 'Limburgs'],
|
103
|
+
'ln' => ['Lingala', 'Lingála'],
|
104
|
+
'lo' => ['Lao', 'ພາສາລາວ'],
|
105
|
+
'lt' => ['Lithuanian', 'lietuvių kalba'],
|
106
|
+
'lu' => ['Luba-Katanga', 'Tshiluba'],
|
107
|
+
'lv' => ['Latvian', 'latviešu valoda'],
|
108
|
+
'mg' => ['Malagasy', 'fiteny malagasy'],
|
109
|
+
'mh' => ['Marshallese', 'Kajin M̧ajeļ'],
|
110
|
+
'mi' => ['Māori', 'te reo Māori'],
|
111
|
+
'mk' => ['Macedonian', 'македонски јазик'],
|
112
|
+
'ml' => ['Malayalam', 'മലയാളം'],
|
113
|
+
'mn' => ['Mongolian', 'Монгол хэл'],
|
114
|
+
'mr' => ['Marathi', 'मराठी'],
|
115
|
+
'ms' => ['Malay', 'bahasa Melayu'],
|
116
|
+
'mt' => ['Maltese', 'Malti'],
|
117
|
+
'my' => ['Burmese', 'ဗမာစာ'],
|
118
|
+
'na' => ['Nauru', 'Dorerin Naoero'],
|
119
|
+
'nb' => ['Norwegian Bokmål', 'Norsk bokmål'],
|
120
|
+
'nd' => ['North Ndebele', 'isiNdebele'],
|
121
|
+
'ne' => ['Nepali', 'नेपाली'],
|
122
|
+
'ng' => ['Ndonga', 'Owambo'],
|
123
|
+
'nl' => ['Dutch', 'Nederlands'],
|
124
|
+
'nn' => ['Norwegian Nynorsk', 'Norsk nynorsk'],
|
125
|
+
'no' => ['Norwegian', 'Norsk'],
|
126
|
+
'nr' => ['South Ndebele', 'isiNdebele'],
|
127
|
+
'nv' => ['Navajo', 'Diné bizaad'],
|
128
|
+
'ny' => ['Chichewa', 'chiCheŵa'],
|
129
|
+
'oc' => ['Occitan', 'occitan'],
|
130
|
+
'oj' => ['Ojibwa', 'ᐊᓂᔑᓈᐯᒧᐎᓐ'],
|
131
|
+
'om' => ['Oromo', 'Afaan Oromoo'],
|
132
|
+
'or' => ['Oriya', 'ଓଡ଼ିଆ'],
|
133
|
+
'os' => ['Ossetian', 'ирон æвзаг'],
|
134
|
+
'pa' => ['Panjabi', 'ਪੰਜਾਬੀ'],
|
135
|
+
'pi' => ['Pāli', 'पाऴि'],
|
136
|
+
'pl' => ['Polish', 'język polski'],
|
137
|
+
'ps' => ['Pashto', 'پښتو'],
|
138
|
+
'pt' => ['Portuguese', 'português'],
|
139
|
+
'qu' => ['Quechua', 'Runa Simi'],
|
140
|
+
'rm' => ['Romansh', 'rumantsch grischun'],
|
141
|
+
'rn' => ['Kirundi', 'Ikirundi'],
|
142
|
+
'ro' => ['Romanian', 'română'],
|
143
|
+
'ru' => ['Russian', 'русский'],
|
144
|
+
'rw' => ['Kinyarwanda', 'Ikinyarwanda'],
|
145
|
+
'sa' => ['Sanskrit', 'संस्कृतम्'],
|
146
|
+
'sc' => ['Sardinian', 'sardu'],
|
147
|
+
'sd' => ['Sindhi', 'सिन्धी'],
|
148
|
+
'se' => ['Northern Sami', 'Davvisámegiella'],
|
149
|
+
'sg' => ['Sango', 'yângâ tî sängö'],
|
150
|
+
'si' => ['Sinhala', 'සිංහල'],
|
151
|
+
'sk' => ['Slovak', 'slovenčina'],
|
152
|
+
'sl' => ['Slovene', 'slovenski jezik'],
|
153
|
+
'sm' => ['Samoan', 'gagana fa\'a Samoa'],
|
154
|
+
'sn' => ['Shona', 'chiShona'],
|
155
|
+
'so' => ['Somali', 'Soomaaliga'],
|
156
|
+
'sq' => ['Albanian', 'gjuha shqipe'],
|
157
|
+
'sr' => ['Serbian', 'српски језик'],
|
158
|
+
'ss' => ['Swati', 'SiSwati'],
|
159
|
+
'st' => ['Southern Sotho', 'Sesotho'],
|
160
|
+
'su' => ['Sundanese', 'Basa Sunda'],
|
161
|
+
'sv' => ['Swedish', 'svenska'],
|
162
|
+
'sw' => ['Swahili', 'Kiswahili'],
|
163
|
+
'ta' => ['Tamil', 'தமிழ்'],
|
164
|
+
'te' => ['Telugu', 'తెలుగు'],
|
165
|
+
'tg' => ['Tajik', 'тоҷикӣ'],
|
166
|
+
'th' => ['Thai', 'ไทย'],
|
167
|
+
'ti' => ['Tigrinya', 'ትግርኛ'],
|
168
|
+
'tk' => ['Turkmen', 'Türkmen'],
|
169
|
+
'tl' => ['Tagalog', 'Wikang Tagalog'],
|
170
|
+
'tn' => ['Tswana', 'Setswana'],
|
171
|
+
'to' => ['Tonga', 'faka Tonga'],
|
172
|
+
'tr' => ['Turkish', 'Türkçe'],
|
173
|
+
'ts' => ['Tsonga', 'Xitsonga'],
|
174
|
+
'tt' => ['Tatar', 'татар теле'],
|
175
|
+
'tw' => ['Twi', 'Twi'],
|
176
|
+
'ty' => ['Tahitian', 'Reo Tahiti'],
|
177
|
+
'ug' => ['Uighur', 'ئۇيغۇرچە'],
|
178
|
+
'uk' => ['Ukrainian', 'українська мова'],
|
179
|
+
'ur' => ['Urdu', 'اردو'],
|
180
|
+
'uz' => ['Uzbek', 'Oʻzbek'],
|
181
|
+
've' => ['Venda', 'Tshivenḓa'],
|
182
|
+
'vi' => ['Vietnamese', 'Tiếng Việt'],
|
183
|
+
'vo' => ['Volapük', 'Volapük'],
|
184
|
+
'wa' => ['Walloon', 'walon'],
|
185
|
+
'wo' => ['Wolof', 'Wollof'],
|
186
|
+
'xh' => ['Xhosa', 'isiXhosa'],
|
187
|
+
'yi' => ['Yiddish', 'ייִדיש'],
|
188
|
+
'yo' => ['Yoruba', 'Yorùbá'],
|
189
|
+
'za' => ['Zhuang', 'Saɯ cueŋƅ'],
|
190
|
+
'zh' => ['Chinese', '中文'],
|
191
|
+
'zu' => ['Zulu', 'isiZulu']
|
192
|
+
}
|
193
|
+
|
194
|
+
def initialize(tag_name, markup, tokens)
|
195
|
+
super
|
196
|
+
@markup = markup.strip
|
197
|
+
end
|
198
|
+
|
199
|
+
def render(context)
|
200
|
+
# Parse arguments that can be quoted or unquoted
|
201
|
+
parts = parse_arguments(@markup)
|
202
|
+
iso_code_input = parts[0]
|
203
|
+
output_type = parts[1] || 'english' # default to english
|
204
|
+
|
205
|
+
# Check if the input was originally quoted (literal string)
|
206
|
+
is_quoted = @markup.strip.match(/^['"]/)
|
207
|
+
|
208
|
+
# If quoted, use as literal. Otherwise, try to resolve as variable
|
209
|
+
if is_quoted
|
210
|
+
iso_code = iso_code_input
|
211
|
+
else
|
212
|
+
# Try to resolve as a variable
|
213
|
+
iso_code = resolve_variable(context, iso_code_input)
|
214
|
+
# If it didn't resolve to a string, use the input as literal
|
215
|
+
iso_code = iso_code_input if iso_code.nil? || !iso_code.is_a?(String)
|
216
|
+
end
|
217
|
+
|
218
|
+
# Strip quotes from resolved iso code if present
|
219
|
+
if iso_code.is_a?(String) && iso_code.match(/^['"].*['"]$/)
|
220
|
+
iso_code = iso_code[1..-2]
|
221
|
+
end
|
222
|
+
|
223
|
+
# Strip quotes from output type if present
|
224
|
+
if output_type.is_a?(String) && output_type.match(/^['"].*['"]$/)
|
225
|
+
output_type = output_type[1..-2]
|
226
|
+
end
|
227
|
+
|
228
|
+
# Convert to lowercase for lookup
|
229
|
+
iso_code = iso_code.to_s.downcase
|
230
|
+
output_type = output_type.to_s.downcase
|
231
|
+
|
232
|
+
# Look up the language
|
233
|
+
language_data = LANGUAGE_MAPPINGS[iso_code]
|
234
|
+
return iso_code if language_data.nil? # Return original code if not found
|
235
|
+
|
236
|
+
# Return appropriate language name based on output type
|
237
|
+
case output_type
|
238
|
+
when 'native'
|
239
|
+
language_data[1] # Native name
|
240
|
+
else
|
241
|
+
language_data[0] # English name (default)
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
private
|
246
|
+
|
247
|
+
def parse_arguments(markup)
|
248
|
+
# Parse arguments that can be quoted or unquoted
|
249
|
+
# Examples: de, english OR 'de', 'english' OR myVar, "native"
|
250
|
+
args = []
|
251
|
+
current_arg = ''
|
252
|
+
in_quotes = false
|
253
|
+
quote_char = nil
|
254
|
+
|
255
|
+
markup.each_char.with_index do |char, i|
|
256
|
+
if !in_quotes && (char == '"' || char == "'")
|
257
|
+
# Start of quoted string
|
258
|
+
in_quotes = true
|
259
|
+
quote_char = char
|
260
|
+
elsif in_quotes && char == quote_char
|
261
|
+
# End of quoted string
|
262
|
+
in_quotes = false
|
263
|
+
quote_char = nil
|
264
|
+
elsif !in_quotes && char == ','
|
265
|
+
# Argument separator
|
266
|
+
args << current_arg.strip
|
267
|
+
current_arg = ''
|
268
|
+
else
|
269
|
+
# Regular character
|
270
|
+
current_arg += char
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
# Add the last argument
|
275
|
+
args << current_arg.strip if current_arg.strip.length > 0
|
276
|
+
|
277
|
+
args
|
278
|
+
end
|
279
|
+
|
280
|
+
def resolve_variable(context, variable_name)
|
281
|
+
# Handle nested variable access like page.language
|
282
|
+
parts = variable_name.split('.')
|
283
|
+
current = context
|
284
|
+
|
285
|
+
parts.each do |part|
|
286
|
+
if current.respond_to?(:[])
|
287
|
+
current = current[part]
|
288
|
+
elsif current.respond_to?(:key?) && current.key?(part)
|
289
|
+
current = current[part]
|
290
|
+
else
|
291
|
+
return nil
|
292
|
+
end
|
293
|
+
return nil if current.nil?
|
294
|
+
end
|
295
|
+
|
296
|
+
current
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
Liquid::Template.register_tag('uj_language', Jekyll::UJLanguageTag)
|