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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4457cc2876947bfe080aa15d492f502208e3dd64573c71e11eb3735cf6a6a6b7
|
4
|
+
data.tar.gz: d8cbd12fcdccc5aedad51ded42d41d03a86cbc92610b722705b16ceafffc50c9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9e6058f9e42984ad01939d759cc706daaf1af6a88bea81d33fd30815ca34ba05a48e2491f5b40abb8548990f11122f60bf190b1cdc6daae8b2a2a0d4d9d526b3
|
7
|
+
data.tar.gz: 80348c6d1d507ae4301cf48e4b862e8687d404260edd9c0fbeb34633c7c23993a18dbde89d54e5d3dcf83052fd88563cec6b76a7e1637bb6573c5647f469f48a
|
data/README.md
CHANGED
@@ -70,6 +70,33 @@ Convert a string to title case.
|
|
70
70
|
{{ "hello world" | uj_title_case }}
|
71
71
|
```
|
72
72
|
|
73
|
+
### `uj_content_format` Filter
|
74
|
+
Process content with Liquid templating and Markdown conversion, automatically transforming markdown images to responsive `uj_image` tags.
|
75
|
+
|
76
|
+
```liquid
|
77
|
+
{{ post.content | uj_content_format }}
|
78
|
+
```
|
79
|
+
|
80
|
+
This filter:
|
81
|
+
- Transforms markdown images `` to `{% uj_image "url", alt="alt", class="..." %}`
|
82
|
+
- Automatically pulls image class from `page.resolved.theme.blog.image.class`
|
83
|
+
- Processes Liquid tags in the content
|
84
|
+
- Converts Markdown to HTML (for .md files)
|
85
|
+
|
86
|
+
If no class is specified in frontmatter, the `uj_image` tag will be rendered without a class attribute.
|
87
|
+
|
88
|
+
#### Frontmatter Configuration Example
|
89
|
+
```yaml
|
90
|
+
---
|
91
|
+
theme:
|
92
|
+
blog:
|
93
|
+
image:
|
94
|
+
class: "img-fluid rounded-3 shadow"
|
95
|
+
---
|
96
|
+
```
|
97
|
+
|
98
|
+
With this frontmatter, all markdown images in the post will automatically use the specified class.
|
99
|
+
|
73
100
|
## Global Variables
|
74
101
|
### `site.uj.cache_breaker` Variable
|
75
102
|
Use the `site.uj.cache_breaker` variable to append a cache-busting query parameter to your assets.
|
@@ -78,7 +105,7 @@ Use the `site.uj.cache_breaker` variable to append a cache-busting query paramet
|
|
78
105
|
<link rel="stylesheet" href="{{ "/assets/css/style.css" | prepend: site.baseurl }}?v={{ site.uj.cache_breaker }}">
|
79
106
|
```
|
80
107
|
|
81
|
-
|
108
|
+
## Page Variables
|
82
109
|
### `page.random_id` Variable
|
83
110
|
Generate a random ID for each page, useful for sorting randomly or for unique identifiers.
|
84
111
|
|
@@ -126,6 +153,91 @@ Resolves the site, layout, and page data into a single object, which can be usef
|
|
126
153
|
{{ page.my.variable | default: layout.my.variable | default: site.my.variable }}
|
127
154
|
```
|
128
155
|
|
156
|
+
## Tags
|
157
|
+
### `iftruthy` Tag
|
158
|
+
A custom Liquid tag that checks if a variable is truthy (not nil, not false, not empty string, not 0) and renders the content inside the tag if it is truthy.
|
159
|
+
```liquid
|
160
|
+
{% iftruthy my_variable %}
|
161
|
+
<p>This content will only be rendered if my_variable is truthy.</p>
|
162
|
+
{% endiftruthy %}
|
163
|
+
```
|
164
|
+
|
165
|
+
### `iffalsy` Tag
|
166
|
+
A custom Liquid tag that checks if a variable is falsy (nil, false, empty string, or 0) and renders the content inside the tag if it is falsy.
|
167
|
+
```liquid
|
168
|
+
{% iffalsy my_variable %}
|
169
|
+
<p>This content will only be rendered if my_variable is falsy.</p>
|
170
|
+
{% endifalsy %}
|
171
|
+
```
|
172
|
+
|
173
|
+
### `uj_icon` Tag
|
174
|
+
A custom Liquid tag that renders a Font Awesome icon with the specified style and name. It supports `name` and `class` parameters.
|
175
|
+
```liquid
|
176
|
+
{% uj_icon "rocket", "fa-lg me-2" %}
|
177
|
+
```
|
178
|
+
|
179
|
+
### `uj_fake_comments` Tag
|
180
|
+
Generates a fake comment count based on content word count for demonstration purposes.
|
181
|
+
```liquid
|
182
|
+
{% uj_fake_comments %}
|
183
|
+
{% uj_fake_comments page.content %}
|
184
|
+
```
|
185
|
+
|
186
|
+
### `uj_image` Tag
|
187
|
+
Renders responsive images with WebP support and lazy loading.
|
188
|
+
```liquid
|
189
|
+
{% uj_image "/assets/images/hero.jpg", max_width="1024", alt="Hero image" %}
|
190
|
+
{% uj_image page.featured_image, class="img-fluid", webp="false" %}
|
191
|
+
```
|
192
|
+
|
193
|
+
### `uj_language` Tag
|
194
|
+
Converts ISO language codes to language names in English or native format.
|
195
|
+
```liquid
|
196
|
+
{% uj_language "es" %}
|
197
|
+
{% uj_language page.language, "native" %}
|
198
|
+
```
|
199
|
+
|
200
|
+
### `uj_member` Tag
|
201
|
+
Retrieves member information from site team collection.
|
202
|
+
```liquid
|
203
|
+
{% uj_member "john-doe", "name" %}
|
204
|
+
{% uj_member page.author, "url" %}
|
205
|
+
{% uj_member member_id, "image" %}
|
206
|
+
{% uj_member "john-doe", "image-tag", max_width="640", class="team-photo" %}
|
207
|
+
```
|
208
|
+
|
209
|
+
The `image-tag` property renders a responsive image using the `uj_image` tag with all its features (WebP, lazy loading, responsive sizes). You can pass any `uj_image` options as additional parameters.
|
210
|
+
|
211
|
+
### `uj_post` Tag
|
212
|
+
Fetches post data from site collections.
|
213
|
+
```liquid
|
214
|
+
{% uj_post "my-post-slug", "title" %}
|
215
|
+
{% uj_post post.id, "description" %}
|
216
|
+
{% uj_post current_post, "image-url" %}
|
217
|
+
```
|
218
|
+
|
219
|
+
### `uj_readtime` Tag
|
220
|
+
Calculates estimated reading time based on content (200 words per minute).
|
221
|
+
```liquid
|
222
|
+
{% uj_readtime %}
|
223
|
+
{% uj_readtime page.content %}
|
224
|
+
```
|
225
|
+
|
226
|
+
### `uj_social` Tag
|
227
|
+
Generates social media URLs from platform handles.
|
228
|
+
```liquid
|
229
|
+
{% uj_social "twitter" %}
|
230
|
+
{% uj_social "github" %}
|
231
|
+
```
|
232
|
+
|
233
|
+
### `uj_translation_url` Tag
|
234
|
+
Creates language-specific URLs for multilingual sites.
|
235
|
+
```liquid
|
236
|
+
{% uj_translation_url "es", page.url %}
|
237
|
+
{% uj_translation_url target_lang, "/pricing" %}
|
238
|
+
```
|
239
|
+
|
240
|
+
## Final notes
|
129
241
|
These examples show how you can use the features of `jekyll-uj-powertools` in your Jekyll site.
|
130
242
|
|
131
243
|
## 🔧 Development
|
@@ -133,9 +245,6 @@ After checking out the repo, run `bin/setup` to install dependencies. You can al
|
|
133
245
|
|
134
246
|
To install this gem onto your local machine, run `bundle exec rake install`.
|
135
247
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
248
|
## ⚠️ Testing
|
140
249
|
Run the tests
|
141
250
|
```shell
|
@@ -5,7 +5,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
# Gem info
|
7
7
|
spec.name = "jekyll-uj-powertools"
|
8
|
-
spec.version = "1.
|
8
|
+
spec.version = "1.6.1"
|
9
9
|
|
10
10
|
# Author info
|
11
11
|
spec.authors = ["ITW Creative Works"]
|
@@ -30,6 +30,7 @@ Gem::Specification.new do |spec|
|
|
30
30
|
spec.add_development_dependency "bundler"
|
31
31
|
spec.add_development_dependency "rake"
|
32
32
|
spec.add_development_dependency "rspec"
|
33
|
+
spec.add_development_dependency "simplecov"
|
33
34
|
|
34
35
|
# Translation and HTML manipulation requires Nokogiri
|
35
36
|
spec.add_runtime_dependency 'nokogiri', '>= 1.17'
|
data/lib/filters/main.rb
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
# Libraries
|
2
2
|
require "jekyll"
|
3
|
+
require "json"
|
3
4
|
|
4
|
-
#
|
5
|
+
# Filters
|
5
6
|
module Jekyll
|
6
7
|
module UJPowertools
|
7
|
-
# Initialize a timestamp that will remain consistent across calls
|
8
|
-
@cache_timestamp = Time.now.to_i.to_s
|
8
|
+
# Initialize a timestamp that will remain consistent across calls (with milliseconds)
|
9
|
+
@cache_timestamp = (Time.now.to_f * 1000).to_i.to_s
|
9
10
|
|
10
11
|
# Strip ads from the input
|
11
12
|
def uj_strip_ads(input)
|
@@ -48,11 +49,6 @@ module Jekyll
|
|
48
49
|
rand(input)
|
49
50
|
end
|
50
51
|
|
51
|
-
# Return the current year
|
52
|
-
def uj_year(input)
|
53
|
-
Time.now.year
|
54
|
-
end
|
55
|
-
|
56
52
|
# Title case
|
57
53
|
def uj_title_case(input)
|
58
54
|
input.split(' ').map(&:capitalize).join(' ')
|
@@ -79,11 +75,18 @@ module Jekyll
|
|
79
75
|
|
80
76
|
# Format content based on file extension - apply liquify and markdownify for .md files
|
81
77
|
def uj_content_format(input)
|
78
|
+
# Return empty string if input is nil
|
79
|
+
return '' unless input
|
80
|
+
|
82
81
|
# Get the current page from context
|
83
82
|
page = @context.registers[:page] if @context.respond_to?(:registers)
|
84
83
|
page ||= @context[:registers][:page] if @context.is_a?(Hash)
|
84
|
+
|
85
|
+
# Get site from context
|
86
|
+
site = @context.registers[:site] if @context.respond_to?(:registers)
|
87
|
+
site ||= @context[:registers][:site] if @context.is_a?(Hash)
|
85
88
|
|
86
|
-
#
|
89
|
+
# Simply apply liquify first (markdown images are already converted to uj_image tags by the hook)
|
87
90
|
liquified = if @context.respond_to?(:registers)
|
88
91
|
Liquid::Template.parse(input).render(@context)
|
89
92
|
else
|
@@ -91,22 +94,37 @@ module Jekyll
|
|
91
94
|
end
|
92
95
|
|
93
96
|
# Check if the page extension is .md
|
94
|
-
if page && page['extension'] == '.md'
|
97
|
+
if page && page['extension'] == '.md' && site
|
95
98
|
# Apply markdownify for markdown files
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
if site
|
100
|
-
converter = site.find_converter_instance(Jekyll::Converters::Markdown)
|
101
|
-
converter.convert(liquified)
|
102
|
-
else
|
103
|
-
liquified
|
104
|
-
end
|
99
|
+
converter = site.find_converter_instance(Jekyll::Converters::Markdown)
|
100
|
+
converter.convert(liquified)
|
105
101
|
else
|
106
102
|
# Return just liquified content for non-markdown files
|
107
103
|
liquified
|
108
104
|
end
|
109
105
|
end
|
106
|
+
|
107
|
+
# Pretty print JSON with configurable indentation (default 2 spaces)
|
108
|
+
def uj_jsonify(input, indent_size = 2)
|
109
|
+
indent_string = ' ' * indent_size.to_i
|
110
|
+
JSON.pretty_generate(input, indent: indent_string)
|
111
|
+
end
|
112
|
+
|
113
|
+
private
|
114
|
+
|
115
|
+
# Helper method to safely dig through nested hashes
|
116
|
+
def dig_value(hash, *keys)
|
117
|
+
return nil unless hash
|
118
|
+
|
119
|
+
value = hash
|
120
|
+
keys.each do |key|
|
121
|
+
return nil unless value.is_a?(Hash)
|
122
|
+
value = value[key]
|
123
|
+
return nil if value.nil?
|
124
|
+
end
|
125
|
+
|
126
|
+
value
|
127
|
+
end
|
110
128
|
end
|
111
129
|
end
|
112
130
|
|
@@ -1,9 +1,9 @@
|
|
1
1
|
# Libraries
|
2
2
|
# ...
|
3
3
|
|
4
|
-
#
|
4
|
+
# Generator
|
5
5
|
module Jekyll
|
6
|
-
class
|
6
|
+
class InjectProperties < Generator
|
7
7
|
safe true
|
8
8
|
priority :low
|
9
9
|
|
@@ -75,16 +75,16 @@ module Jekyll
|
|
75
75
|
def get_layout_chain(layout_name, site)
|
76
76
|
chain = []
|
77
77
|
current_layout_name = layout_name
|
78
|
-
|
78
|
+
|
79
79
|
# Traverse up the layout hierarchy
|
80
80
|
while current_layout_name
|
81
81
|
layout = site.layouts[current_layout_name]
|
82
82
|
break unless layout
|
83
|
-
|
83
|
+
|
84
84
|
chain.unshift(layout) # Add to beginning to maintain parent->child order
|
85
85
|
current_layout_name = layout.data['layout']
|
86
86
|
end
|
87
|
-
|
87
|
+
|
88
88
|
chain
|
89
89
|
end
|
90
90
|
|
@@ -95,13 +95,13 @@ module Jekyll
|
|
95
95
|
'path', 'relative_path', 'collection', 'type', 'id', 'url',
|
96
96
|
'next', 'previous', 'draft', 'ext', 'excerpt', 'output'
|
97
97
|
]
|
98
|
-
|
98
|
+
|
99
99
|
filtered = {}
|
100
100
|
data.each do |key, value|
|
101
101
|
next if jekyll_internals.include?(key)
|
102
102
|
filtered[key] = value
|
103
103
|
end
|
104
|
-
|
104
|
+
|
105
105
|
filtered
|
106
106
|
end
|
107
107
|
|
@@ -114,6 +114,27 @@ module Jekyll
|
|
114
114
|
item.data['extension'] = File.extname(item.path)
|
115
115
|
end
|
116
116
|
|
117
|
+
|
118
|
+
# Inject canonical URL
|
119
|
+
if item.respond_to?(:url)
|
120
|
+
page_url_stripped = item.url.sub(/index\.html$/, '')
|
121
|
+
page_url_stripped = '' if page_url_stripped == '/'
|
122
|
+
site_url = site.config['url'] || ''
|
123
|
+
item.data['canonical'] = {
|
124
|
+
'url' => site_url + page_url_stripped,
|
125
|
+
'path' => page_url_stripped.empty? ? '/' : page_url_stripped
|
126
|
+
}
|
127
|
+
end
|
128
|
+
|
129
|
+
# Inject page type based on post or member properties
|
130
|
+
if item.data['post']
|
131
|
+
item.data['type'] = 'post'
|
132
|
+
elsif item.data['member']
|
133
|
+
item.data['type'] = 'member'
|
134
|
+
else
|
135
|
+
item.data['type'] = 'basic'
|
136
|
+
end
|
137
|
+
|
117
138
|
# Set resolved data for site, layout, and page
|
118
139
|
# Create a deep merge of site -> child layouts -> parent layouts -> page data
|
119
140
|
# Priority: page (highest) -> parent layouts -> child layouts -> site (lowest)
|
@@ -155,5 +176,6 @@ module Jekyll
|
|
155
176
|
# Add the resolved data to the item
|
156
177
|
item.data['resolved'] = resolved
|
157
178
|
end
|
179
|
+
|
158
180
|
end
|
159
181
|
end
|
@@ -3,6 +3,16 @@
|
|
3
3
|
|
4
4
|
# Hook
|
5
5
|
Jekyll::Hooks.register :site, :pre_render do |site|
|
6
|
+
# Ensure uj config exists
|
6
7
|
site.config['uj'] ||= {}
|
8
|
+
|
9
|
+
# Set cache breaker
|
7
10
|
site.config['uj']['cache_breaker'] = Jekyll::UJPowertools.cache_timestamp
|
11
|
+
|
12
|
+
# Add date properties
|
13
|
+
site.config['uj']['date'] ||= {}
|
14
|
+
now = Time.now
|
15
|
+
site.config['uj']['date']['year'] = now.year
|
16
|
+
site.config['uj']['date']['month'] = now.month
|
17
|
+
site.config['uj']['date']['day'] = now.day
|
8
18
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# Libraries
|
2
|
+
require "jekyll"
|
3
|
+
|
4
|
+
module Jekyll
|
5
|
+
# Hook into the pre_render phase to transform markdown images before conversion
|
6
|
+
Jekyll::Hooks.register [:posts, :pages, :documents], :pre_render do |doc|
|
7
|
+
# Only process markdown files
|
8
|
+
if doc.extname == ".md"
|
9
|
+
# Get image class from resolved data if available
|
10
|
+
image_class = nil
|
11
|
+
if doc.data['resolved'] && doc.data['resolved']['theme']
|
12
|
+
theme = doc.data['resolved']['theme']
|
13
|
+
if theme['post'] && theme['post']['image'] && theme['post']['image']['class']
|
14
|
+
image_class = theme['post']['image']['class']
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Transform markdown images by parsing and rendering Liquid template
|
19
|
+
doc.content = doc.content.gsub(/!\[([^\]]*)\]\(([^)]+)\)/) do
|
20
|
+
alt_text = $1
|
21
|
+
image_path = $2
|
22
|
+
|
23
|
+
# Build the Liquid tag string
|
24
|
+
if image_class
|
25
|
+
liquid_tag = "{% uj_image \"#{image_path}\", alt=\"#{alt_text}\", class=\"#{image_class}\" %}"
|
26
|
+
else
|
27
|
+
liquid_tag = "{% uj_image \"#{image_path}\", alt=\"#{alt_text}\" %}"
|
28
|
+
end
|
29
|
+
|
30
|
+
# Parse and render the Liquid template immediately
|
31
|
+
template = Liquid::Template.parse(liquid_tag)
|
32
|
+
context = doc.site.site_payload.merge({'page' => doc.to_liquid})
|
33
|
+
result = template.render(Liquid::Context.new(context))
|
34
|
+
|
35
|
+
# Return the HTML with blank lines to ensure markdown treats it as raw HTML
|
36
|
+
"\n\n#{result}\n\n"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/jekyll-uj-powertools.rb
CHANGED
@@ -10,7 +10,18 @@ module Jekyll
|
|
10
10
|
|
11
11
|
# Load Hooks
|
12
12
|
require_relative "hooks/inject-properties"
|
13
|
+
require_relative "hooks/markdown-images"
|
13
14
|
|
14
15
|
# Load Tags
|
15
|
-
|
16
|
+
require_relative "tags/iftruthy"
|
17
|
+
require_relative "tags/iffalsy"
|
18
|
+
require_relative "tags/icon"
|
19
|
+
require_relative "tags/social"
|
20
|
+
require_relative "tags/readtime"
|
21
|
+
require_relative "tags/fake_comments"
|
22
|
+
require_relative "tags/member"
|
23
|
+
require_relative "tags/image"
|
24
|
+
require_relative "tags/post"
|
25
|
+
require_relative "tags/language"
|
26
|
+
require_relative "tags/translation_url"
|
16
27
|
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# Libraries
|
2
|
+
require "jekyll"
|
3
|
+
|
4
|
+
module Jekyll
|
5
|
+
class UJCommentsTag < Liquid::Tag
|
6
|
+
def initialize(tag_name, markup, tokens)
|
7
|
+
super
|
8
|
+
@markup = markup.strip
|
9
|
+
end
|
10
|
+
|
11
|
+
def render(context)
|
12
|
+
# Get the content to analyze
|
13
|
+
content = resolve_content(context)
|
14
|
+
return '0' unless content
|
15
|
+
|
16
|
+
# Strip HTML tags
|
17
|
+
stripped_content = strip_html(content)
|
18
|
+
|
19
|
+
# Count words
|
20
|
+
words = count_words(stripped_content)
|
21
|
+
|
22
|
+
# Generate comment count based on word count modulo 13
|
23
|
+
comments = words % 13
|
24
|
+
|
25
|
+
comments.to_s
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def resolve_content(context)
|
31
|
+
if @markup.empty?
|
32
|
+
# No argument, use page content
|
33
|
+
page = context['page']
|
34
|
+
return nil unless page
|
35
|
+
page['content']
|
36
|
+
else
|
37
|
+
# Resolve the variable name
|
38
|
+
resolve_variable(context, @markup)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def resolve_variable(context, variable_name)
|
43
|
+
# Handle nested variable access like page.content or include.content
|
44
|
+
parts = variable_name.split('.')
|
45
|
+
current = context
|
46
|
+
|
47
|
+
parts.each do |part|
|
48
|
+
return nil unless current.respond_to?(:[]) || current.is_a?(Hash)
|
49
|
+
current = current[part]
|
50
|
+
return nil if current.nil?
|
51
|
+
end
|
52
|
+
|
53
|
+
current
|
54
|
+
end
|
55
|
+
|
56
|
+
def strip_html(content)
|
57
|
+
# Remove HTML tags
|
58
|
+
content = content.to_s.gsub(/<script.*?<\/script>/m, '')
|
59
|
+
content = content.gsub(/<style.*?<\/style>/m, '')
|
60
|
+
content = content.gsub(/<[^>]+>/, ' ')
|
61
|
+
content = content.gsub(/\s+/, ' ')
|
62
|
+
content.strip
|
63
|
+
end
|
64
|
+
|
65
|
+
def count_words(text)
|
66
|
+
# Count words (split by whitespace)
|
67
|
+
text.split(/\s+/).length
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
Liquid::Template.register_tag('uj_fake_comments', Jekyll::UJCommentsTag)
|