ultimate-jekyll-manager 1.9.8 → 1.9.10
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.
- package/CLAUDE.md +1 -0
- package/dist/defaults/dist/_includes/core/foot.html +1 -1
- package/dist/defaults/dist/_includes/core/head.html +10 -10
- package/dist/defaults/dist/_includes/modules/adunits/adsense.html +1 -1
- package/dist/defaults/dist/_includes/modules/adunits/promo-server.html +1 -1
- package/dist/defaults/dist/_includes/themes/classy/backend/sections/sidebar.html +2 -2
- package/dist/defaults/dist/_includes/themes/classy/frontend/sections/nav.html +2 -2
- package/dist/defaults/dist/_layouts/modules/utilities/redirect.html +2 -2
- package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/account/index.html +3 -3
- package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/app.html +1 -1
- package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/auth/oauth2.html +1 -1
- package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/auth/reset.html +1 -1
- package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/auth/signin.html +2 -2
- package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/auth/signup.html +2 -2
- package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/auth/token.html +1 -1
- package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/feedback.html +6 -6
- package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/payment/checkout.html +1 -1
- package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/portal/email-preferences.html +1 -1
- package/docs/common-mistakes.md +1 -0
- package/docs/jekyll-plugin.md +27 -1
- package/package.json +1 -1
package/CLAUDE.md
CHANGED
|
@@ -193,6 +193,7 @@ All `npm install` calls in CLI commands (`npx mgr i`, `npx mgr setup`) route thr
|
|
|
193
193
|
- **No backwards compatibility** unless explicitly requested.
|
|
194
194
|
- **Don't add `?.` paranoia.** Framework internals (`manager.config`, `manager.webManager`) deref directly. `?.` belongs only on user-supplied config sub-fields, optional return values from regex matches, caught exceptions, and pre-init state.
|
|
195
195
|
- **Use `process.cwd()` (not hardcoded paths) for consumer-project resolution** in gulp tasks + commands. UJM runs inside the consumer's working directory.
|
|
196
|
+
- **All `<img src>` tags MUST have a cachebreaker** — append `?cb={{ site.uj.cache_breaker }}` to image `src` attributes in includes and layouts. This applies to logos, brandmarks, rating images, and any other image rendered via Liquid variables. External third-party URLs (YouTube embeds, analytics pixels, placeholder services) are exempt. `data-lazy="@src"` is handled at the JS layer, not here. See [docs/common-mistakes.md](docs/common-mistakes.md).
|
|
196
197
|
|
|
197
198
|
## Doc-update parity
|
|
198
199
|
|
|
@@ -107,7 +107,7 @@
|
|
|
107
107
|
</script>
|
|
108
108
|
|
|
109
109
|
<!-- JS Bundle -->
|
|
110
|
-
<script type="text/javascript" src="{{ site.url
|
|
110
|
+
<script type="text/javascript" src="{{ site.url | append: '/assets/js/main.bundle.js' | uj_cachebreak }}" async></script>
|
|
111
111
|
|
|
112
112
|
<!-- Script to quickly handle nav user state -->
|
|
113
113
|
<script type="text/javascript">
|
|
@@ -172,13 +172,13 @@
|
|
|
172
172
|
<link rel="alternate" href="{{ page.canonical.url }}" hreflang="{{ page-translation-default }}"/>
|
|
173
173
|
|
|
174
174
|
<!-- Favicon -->
|
|
175
|
-
<link rel="apple-touch-icon" sizes="180x180" href="{{ favicon-path
|
|
176
|
-
<link rel="icon" type="image/png" sizes="32x32" href="{{ favicon-path
|
|
177
|
-
<link rel="icon" type="image/png" sizes="16x16" href="{{ favicon-path
|
|
178
|
-
<link rel="mask-icon" href="{{ favicon-path
|
|
179
|
-
<link rel="shortcut icon" type="image/x-icon" href="{{ favicon-path
|
|
175
|
+
<link rel="apple-touch-icon" sizes="180x180" href="{{ favicon-path | append: '/apple-touch-icon.png' | uj_cachebreak }}"/>
|
|
176
|
+
<link rel="icon" type="image/png" sizes="32x32" href="{{ favicon-path | append: '/favicon-32x32.png' | uj_cachebreak }}"/>
|
|
177
|
+
<link rel="icon" type="image/png" sizes="16x16" href="{{ favicon-path | append: '/favicon-16x16.png' | uj_cachebreak }}"/>
|
|
178
|
+
<link rel="mask-icon" href="{{ favicon-path | append: '/safari-pinned-tab.svg' | uj_cachebreak }}" color="{{ page.resolved.favicon.safari-pinned-tab }}"/>
|
|
179
|
+
<link rel="shortcut icon" type="image/x-icon" href="{{ favicon-path | append: '/favicon.ico' | uj_cachebreak }}"/>
|
|
180
180
|
<meta name="msapplication-TileColor" content="{{ page.resolved.favicon.msapp-tile-color }}"/>
|
|
181
|
-
<meta name="msapplication-config" content="{{ favicon-path
|
|
181
|
+
<meta name="msapplication-config" content="{{ favicon-path | append: '/browserconfig.xml' | uj_cachebreak }}"/>
|
|
182
182
|
<meta name="theme-color" content="{{ page.resolved.favicon.theme-color }}"/>
|
|
183
183
|
|
|
184
184
|
<!-- Browser Support -->
|
|
@@ -193,17 +193,17 @@
|
|
|
193
193
|
<!-- Note: media="print" onload="this.media='all'" does NOT improve performance -->
|
|
194
194
|
<!-- Fetch specific bundle if it's requested -->
|
|
195
195
|
{% iftruthy page.resolved.theme.css.bundle %}
|
|
196
|
-
<link rel="stylesheet" type="text/css" href="{{ site.url
|
|
196
|
+
<link rel="stylesheet" type="text/css" href="{{ site.url | append: '/assets/css/' | append: page.resolved.theme.css.bundle | append: '.bundle.css' | uj_cachebreak }}"/>
|
|
197
197
|
{% endiftruthy %}
|
|
198
198
|
|
|
199
199
|
<!-- Otherwise, fetch main bundle -->
|
|
200
200
|
{% iffalsy page.resolved.theme.css.bundle %}
|
|
201
|
-
<link rel="stylesheet" type="text/css" href="{{ site.url
|
|
201
|
+
<link rel="stylesheet" type="text/css" href="{{ site.url | append: '/assets/css/main.bundle.css' | uj_cachebreak }}"/>
|
|
202
202
|
{% endiffalsy %}
|
|
203
203
|
|
|
204
204
|
<!-- Then, fetch any page specific bundles -->
|
|
205
205
|
{% iffile page-css-path %}
|
|
206
|
-
<link rel="stylesheet" type="text/css" href="{{ site.url
|
|
206
|
+
<link rel="stylesheet" type="text/css" href="{{ site.url | append: page-css-path | uj_cachebreak }}"/>
|
|
207
207
|
|
|
208
208
|
<!-- Dev log -->
|
|
209
209
|
{% if jekyll.environment == "development" %}
|
|
@@ -217,7 +217,7 @@
|
|
|
217
217
|
Only present when the theme ships page CSS for this path — otherwise nothing loads
|
|
218
218
|
and the theme's component/general styles handle the page. No fallback needed. -->
|
|
219
219
|
{% iffile page-css-theme-path %}
|
|
220
|
-
<link rel="stylesheet" type="text/css" href="{{ site.url
|
|
220
|
+
<link rel="stylesheet" type="text/css" href="{{ site.url | append: page-css-theme-path | uj_cachebreak }}"/>
|
|
221
221
|
|
|
222
222
|
<!-- Dev log -->
|
|
223
223
|
{% if jekyll.environment == "development" %}
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
<!-- Inject Ad -->
|
|
48
48
|
{%- iftruthy page-adsense-client -%}
|
|
49
49
|
<div data-lazy='@script {
|
|
50
|
-
"src": "{{ site.url
|
|
50
|
+
"src": "{{ site.url | append: '/assets/js/modules/vert.bundle.js' | uj_cachebreak }}",
|
|
51
51
|
"attributes": {
|
|
52
52
|
"data-ad-client": "{{ page-adsense-client }}",
|
|
53
53
|
"data-ad-type": "{{ type }}",
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
{% assign vert-style = include.style | default: "" %}
|
|
7
7
|
|
|
8
8
|
<div data-lazy='@script {
|
|
9
|
-
"src": "{{ site.url
|
|
9
|
+
"src": "{{ site.url | append: '/assets/js/modules/vert.bundle.js' | uj_cachebreak }}",
|
|
10
10
|
"attributes": {
|
|
11
11
|
"data-ad-type": "custom",
|
|
12
12
|
"data-ad-size": "{{ vert-size }}",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
<a href="{{ logo_href }}" class="d-flex align-items-center text-decoration-none text-body">
|
|
11
11
|
{% iftruthy logo_src %}
|
|
12
12
|
<div class="avatar avatar-md me-2 {{ logo_class }}">
|
|
13
|
-
<img src="{{ logo_src }}" alt="{{ logo_text }} Logo"/>
|
|
13
|
+
<img src="{{ logo_src | uj_cachebreak }}" alt="{{ logo_text }} Logo"/>
|
|
14
14
|
</div>
|
|
15
15
|
{% endiftruthy %}
|
|
16
16
|
{% iftruthy logo_text %}
|
|
@@ -186,7 +186,7 @@
|
|
|
186
186
|
<h5 class="offcanvas-title d-flex align-items-center" id="mobileSidebarLabel">
|
|
187
187
|
{% iftruthy logo_src %}
|
|
188
188
|
<div class="avatar avatar-md me-2">
|
|
189
|
-
<img src="{{ logo_src }}" alt="{{ logo_text }} Logo"/>
|
|
189
|
+
<img src="{{ logo_src | uj_cachebreak }}" alt="{{ logo_text }} Logo"/>
|
|
190
190
|
</div>
|
|
191
191
|
{% endiftruthy %}
|
|
192
192
|
{% iftruthy logo_text %}
|
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
<a class="navbar-brand d-inline-flex align-items-center py-0" href="{{ logo_href }}">
|
|
10
10
|
{% iftruthy logo_src %}
|
|
11
11
|
{% if data.logo.type == 'wordmark' %}
|
|
12
|
-
<img src="{{ logo_src }}" alt="{{ logo_text }} Logo" class="{{ logo_class }}" style="height: 2rem; width: auto;"/>
|
|
12
|
+
<img src="{{ logo_src | uj_cachebreak }}" alt="{{ logo_text }} Logo" class="{{ logo_class }}" style="height: 2rem; width: auto;"/>
|
|
13
13
|
{% else %}
|
|
14
14
|
<div class="avatar avatar-md me-2 {{ logo_class }}">
|
|
15
|
-
<img src="{{ logo_src }}" alt="{{ logo_text }} Logo"/>
|
|
15
|
+
<img src="{{ logo_src | uj_cachebreak }}" alt="{{ logo_text }} Logo"/>
|
|
16
16
|
</div>
|
|
17
17
|
{% endif %}
|
|
18
18
|
{% endiftruthy %}
|
|
@@ -20,7 +20,7 @@ meta:
|
|
|
20
20
|
<div class="text-center mb-3">
|
|
21
21
|
<a href="{{ site.url }}">
|
|
22
22
|
<div class="avatar avatar-xl">
|
|
23
|
-
<img src="{{ site.brand.images.brandmark
|
|
23
|
+
<img src="{{ site.brand.images.brandmark | uj_cachebreak }}" alt="{{ site.brand.name }}"/>
|
|
24
24
|
</div>
|
|
25
25
|
</a>
|
|
26
26
|
</div>
|
|
@@ -69,4 +69,4 @@ meta:
|
|
|
69
69
|
</div>
|
|
70
70
|
|
|
71
71
|
<!-- Load redirect module script -->
|
|
72
|
-
<script type="text/javascript" src="{{ site.url
|
|
72
|
+
<script type="text/javascript" src="{{ site.url | append: '/assets/js/modules/redirect.bundle.js' | uj_cachebreak }}" async></script>
|
|
@@ -151,7 +151,7 @@ badges:
|
|
|
151
151
|
<!-- Left: Brand -->
|
|
152
152
|
<a href="/" class="d-flex align-items-center text-decoration-none text-body">
|
|
153
153
|
<span class="avatar avatar-md me-3 filter-adaptive">
|
|
154
|
-
<img src="{{ site.brand.images.brandmark
|
|
154
|
+
<img src="{{ site.brand.images.brandmark | uj_cachebreak }}" alt="{{ site.brand.name }}"/>
|
|
155
155
|
</span>
|
|
156
156
|
<h1 class="h5 mb-0 fw-semibold">{{ site.brand.name }} Account</h1>
|
|
157
157
|
</a>
|
|
@@ -790,7 +790,7 @@ badges:
|
|
|
790
790
|
{% uj_icon method.icon, "fa-3xl" %}
|
|
791
791
|
{% endiftruthy %}
|
|
792
792
|
{% iftruthy method.logo %}
|
|
793
|
-
<img src="{{ method.logo
|
|
793
|
+
<img src="{{ method.logo | uj_cachebreak }}" class="object-fit-contain" alt="{{ method.name }} Logo"/>
|
|
794
794
|
{% endiftruthy %}
|
|
795
795
|
</div>
|
|
796
796
|
<div>
|
|
@@ -958,7 +958,7 @@ badges:
|
|
|
958
958
|
<div class="d-flex flex-column flex-sm-row align-items-stretch align-items-sm-center justify-content-between gap-3">
|
|
959
959
|
<div class="d-flex align-items-center">
|
|
960
960
|
<div class="d-flex align-items-center justify-content-center me-3 flex-shrink-0 fa fa-3xl">
|
|
961
|
-
<img src="{{ connection.logo
|
|
961
|
+
<img src="{{ connection.logo | uj_cachebreak }}" class="object-fit-contain" alt="{{ connection.name }} Logo"/>
|
|
962
962
|
</div>
|
|
963
963
|
<div>
|
|
964
964
|
<h6 class="mb-0">{{ connection.name }}</h6>
|
|
@@ -15,7 +15,7 @@ app:
|
|
|
15
15
|
<!-- Logo -->
|
|
16
16
|
<div class="text-center mb-3">
|
|
17
17
|
<div class="avatar avatar-xl">
|
|
18
|
-
<img src="{{ site.brand.images.brandmark
|
|
18
|
+
<img src="{{ site.brand.images.brandmark | uj_cachebreak }}" alt="{{ site.brand.name }} Logo"/>
|
|
19
19
|
</div>
|
|
20
20
|
</div>
|
|
21
21
|
|
|
@@ -11,7 +11,7 @@ layout: themes/[ site.theme.id ]/frontend/core/cover
|
|
|
11
11
|
<!-- Logo -->
|
|
12
12
|
<div class="text-center mb-3">
|
|
13
13
|
<div class="avatar avatar-xl">
|
|
14
|
-
<img src="{{ site.brand.images.brandmark
|
|
14
|
+
<img src="{{ site.brand.images.brandmark | uj_cachebreak }}" class="filter-adaptive" alt="{{ site.brand.name }} Logo"/>
|
|
15
15
|
</div>
|
|
16
16
|
</div>
|
|
17
17
|
|
|
@@ -11,7 +11,7 @@ layout: themes/[ site.theme.id ]/frontend/core/cover
|
|
|
11
11
|
<!-- Logo -->
|
|
12
12
|
<div class="text-center mb-3">
|
|
13
13
|
<div class="avatar avatar-xl">
|
|
14
|
-
<img src="{{ site.brand.images.brandmark
|
|
14
|
+
<img src="{{ site.brand.images.brandmark | uj_cachebreak }}" class="filter-adaptive" alt="{{ site.brand.name }} Logo"/>
|
|
15
15
|
</div>
|
|
16
16
|
</div>
|
|
17
17
|
|
|
@@ -26,7 +26,7 @@ social_signin:
|
|
|
26
26
|
<!-- Logo -->
|
|
27
27
|
<div class="text-center mb-3">
|
|
28
28
|
<div class="avatar avatar-xl">
|
|
29
|
-
<img src="{{ site.brand.images.brandmark
|
|
29
|
+
<img src="{{ site.brand.images.brandmark | uj_cachebreak }}" class="filter-adaptive" alt="{{ site.brand.name }} Logo"/>
|
|
30
30
|
</div>
|
|
31
31
|
</div>
|
|
32
32
|
|
|
@@ -50,7 +50,7 @@ social_signin:
|
|
|
50
50
|
<button type="submit" class="btn btn-adaptive _btn-lg w-100 mb-3 d-flex align-items-center justify-content-center" data-provider="{{ provider.id }}">
|
|
51
51
|
{{ initializing_spinner }}
|
|
52
52
|
<span class="avatar avatar-xs me-2">
|
|
53
|
-
<img src="{{ provider.logo
|
|
53
|
+
<img src="{{ provider.logo | uj_cachebreak }}" class="object-fit-contain" alt="{{ provider.name }} Logo"/>
|
|
54
54
|
</span>
|
|
55
55
|
<span class="button-text">Continue with {{ provider.name }}</span>
|
|
56
56
|
</button>
|
|
@@ -26,7 +26,7 @@ social_signup:
|
|
|
26
26
|
<!-- Logo -->
|
|
27
27
|
<div class="text-center mb-3">
|
|
28
28
|
<div class="avatar avatar-xl">
|
|
29
|
-
<img src="{{ site.brand.images.brandmark
|
|
29
|
+
<img src="{{ site.brand.images.brandmark | uj_cachebreak }}" class="filter-adaptive" alt="{{ site.brand.name }} Logo"/>
|
|
30
30
|
</div>
|
|
31
31
|
</div>
|
|
32
32
|
|
|
@@ -50,7 +50,7 @@ social_signup:
|
|
|
50
50
|
<button type="submit" class="btn btn-adaptive _btn-lg w-100 mb-3 d-flex align-items-center justify-content-center" data-provider="{{ provider.id }}">
|
|
51
51
|
{{ initializing_spinner }}
|
|
52
52
|
<span class="avatar avatar-xs me-2">
|
|
53
|
-
<img src="{{ provider.logo
|
|
53
|
+
<img src="{{ provider.logo | uj_cachebreak }}" class="object-fit-contain" alt="{{ provider.name }} Logo"/>
|
|
54
54
|
</span>
|
|
55
55
|
<span class="button-text">Sign up with {{ provider.name }}</span>
|
|
56
56
|
</button>
|
|
@@ -9,7 +9,7 @@ layout: themes/[ site.theme.id ]/frontend/core/cover
|
|
|
9
9
|
<!-- Logo -->
|
|
10
10
|
<div class="text-center mb-3">
|
|
11
11
|
<div class="avatar avatar-xl">
|
|
12
|
-
<img src="{{ site.brand.images.brandmark
|
|
12
|
+
<img src="{{ site.brand.images.brandmark | uj_cachebreak }}" class="filter-adaptive" alt="{{ site.brand.name }} Logo"/>
|
|
13
13
|
</div>
|
|
14
14
|
</div>
|
|
15
15
|
|
|
@@ -20,16 +20,16 @@ feedback_form:
|
|
|
20
20
|
ratings:
|
|
21
21
|
- id: "dislike"
|
|
22
22
|
label: "Poor"
|
|
23
|
-
image: "https://cdn.itwcreativeworks.com/assets/general/images/feedback/dislike.png
|
|
23
|
+
image: "https://cdn.itwcreativeworks.com/assets/general/images/feedback/dislike.png"
|
|
24
24
|
- id: "neutral"
|
|
25
25
|
label: "Okay"
|
|
26
|
-
image: "https://cdn.itwcreativeworks.com/assets/general/images/feedback/neutral.png
|
|
26
|
+
image: "https://cdn.itwcreativeworks.com/assets/general/images/feedback/neutral.png"
|
|
27
27
|
- id: "like"
|
|
28
28
|
label: "Good"
|
|
29
|
-
image: "https://cdn.itwcreativeworks.com/assets/general/images/feedback/like.png
|
|
29
|
+
image: "https://cdn.itwcreativeworks.com/assets/general/images/feedback/like.png"
|
|
30
30
|
- id: "love"
|
|
31
31
|
label: "Excellent"
|
|
32
|
-
image: "https://cdn.itwcreativeworks.com/assets/general/images/feedback/love.png
|
|
32
|
+
image: "https://cdn.itwcreativeworks.com/assets/general/images/feedback/love.png"
|
|
33
33
|
|
|
34
34
|
# Prerender icons for JS
|
|
35
35
|
prerender_icons:
|
|
@@ -92,7 +92,7 @@ prerender_icons:
|
|
|
92
92
|
{% for rating in page.resolved.feedback_form.ratings %}
|
|
93
93
|
<div class="col-6 col-sm-3">
|
|
94
94
|
<button type="button" class="feedback-rating-btn w-100 border rounded-3 bg-body text-center" data-rating="{{ rating.id }}">
|
|
95
|
-
<img src="{{ rating.image }}" alt="{{ rating.label }}" class="feedback-rating-img mb-2" width="64" height="64" loading="eager">
|
|
95
|
+
<img src="{{ rating.image | uj_cachebreak }}" alt="{{ rating.label }}" class="feedback-rating-img mb-2" width="64" height="64" loading="eager">
|
|
96
96
|
<span class="d-block small fw-semibold text-muted">{{ rating.label }}</span>
|
|
97
97
|
</button>
|
|
98
98
|
</div>
|
|
@@ -164,7 +164,7 @@ prerender_icons:
|
|
|
164
164
|
<div class="modal-content border-0 shadow-lg">
|
|
165
165
|
<div class="modal-body text-center p-5">
|
|
166
166
|
<div class="mb-4">
|
|
167
|
-
<img src="https://cdn.itwcreativeworks.com/assets/general/images/feedback/love.png
|
|
167
|
+
<img src="{{ 'https://cdn.itwcreativeworks.com/assets/general/images/feedback/love.png' | uj_cachebreak }}" alt="Thank you" width="80" height="80">
|
|
168
168
|
</div>
|
|
169
169
|
<h3 class="mb-3" id="review-modal-label">You're awesome!</h3>
|
|
170
170
|
<p class="text-muted mb-3">
|
|
@@ -379,7 +379,7 @@ web_manager:
|
|
|
379
379
|
<div class="d-flex align-items-center wm-binding-skeleton" data-wm-bind="@show checkout">
|
|
380
380
|
<div class="position-relative me-3">
|
|
381
381
|
<div class="product-thumbnail bg-light rounded-3 d-flex align-items-center justify-content-center">
|
|
382
|
-
<img src="{{ site.brand.images.brandmark
|
|
382
|
+
<img src="{{ site.brand.images.brandmark | uj_cachebreak }}" class="img-fluid p-2" alt="{{ site.brand.name }} Plan Icon"/>
|
|
383
383
|
</div>
|
|
384
384
|
<span class="quantity-badge position-absolute top-0 start-100 translate-middle badge rounded-circle bg-primary">
|
|
385
385
|
1
|
package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/portal/email-preferences.html
CHANGED
|
@@ -14,7 +14,7 @@ prerender_icons:
|
|
|
14
14
|
<!-- Logo -->
|
|
15
15
|
<div class="text-center mb-3">
|
|
16
16
|
<div class="avatar avatar-xl">
|
|
17
|
-
<img src="{{ site.brand.images.brandmark
|
|
17
|
+
<img src="{{ site.brand.images.brandmark | uj_cachebreak }}" alt="{{ site.brand.name }} Logo"/>
|
|
18
18
|
</div>
|
|
19
19
|
</div>
|
|
20
20
|
|
package/docs/common-mistakes.md
CHANGED
|
@@ -13,3 +13,4 @@
|
|
|
13
13
|
11. **Using native fetch** — always use `wonderful-fetch` or `authorized-fetch`.
|
|
14
14
|
12. **XSS — unescaped dynamic data in innerHTML** — Use `webManager.utilities().escapeHTML()`. Dynamic URLs in `href`/`src`/`action`/`window.location`/`window.open` ALSO need `webManager.utilities().sanitizeURL()` — `escapeHTML` alone lets `javascript:` execute. See [xss-prevention.md](xss-prevention.md).
|
|
15
15
|
13. **Leaving Liquid `{{ }}` or `{% %}` inside moved JS modules** — Jekyll does NOT process `src/assets/js/**/*.js`. Use `data-*` attribute bridges or `<template>` cloning.
|
|
16
|
+
14. **🚫 `<img src>` without cachebreakers** — every `<img src>` in includes/layouts MUST append `?cb={{ site.uj.cache_breaker }}` to the URL. This applies to logos, brandmarks, rating images — any image rendered via a Liquid variable. Without it, browsers serve stale cached versions indefinitely when the image file changes on the CDN. External third-party URLs are exempt. `data-lazy="@src"` is handled at the JS layer, not in the HTML.
|
package/docs/jekyll-plugin.md
CHANGED
|
@@ -6,7 +6,7 @@ Ultimate Jekyll uses the `jekyll-uj-powertools` gem for custom Liquid functional
|
|
|
6
6
|
|
|
7
7
|
## Available Features
|
|
8
8
|
|
|
9
|
-
- **Filters:** `uj_strip_ads`, `uj_json_escape`, `uj_title_case`, `uj_content_format`, `uj_hash`
|
|
9
|
+
- **Filters:** `uj_strip_ads`, `uj_json_escape`, `uj_title_case`, `uj_content_format`, `uj_hash`, `uj_append_param`, `uj_cachebreak`
|
|
10
10
|
- **Tags:** `iftruthy`, `iffalsy`, `uj_icon`, `uj_logo`, `uj_image`, `uj_member`, `uj_post`, `uj_readtime`, `uj_social`, `uj_translation_url`, `uj_fake_comments`, `uj_language`
|
|
11
11
|
- **Global Variables:** `site.uj.cache_breaker`
|
|
12
12
|
- **Page Variables:** `page.random_id`, `page.extension`, `page.layout_data`, `page.resolved`
|
|
@@ -28,6 +28,30 @@ Returns a deterministic number between 0 and max (exclusive) based on the input
|
|
|
28
28
|
{{ site.url | uj_hash: 2 }} => 0 or 1
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
+
### `uj_append_param`
|
|
32
|
+
|
|
33
|
+
Intelligently appends a query parameter to a URL, using `?` or `&` depending on whether the URL already has a query string.
|
|
34
|
+
|
|
35
|
+
```liquid
|
|
36
|
+
{{ "https://example.com/img.png" | uj_append_param: "cb", "123" }}
|
|
37
|
+
<!-- Output: https://example.com/img.png?cb=123 -->
|
|
38
|
+
|
|
39
|
+
{{ "https://example.com/img.png?w=200" | uj_append_param: "cb", "123" }}
|
|
40
|
+
<!-- Output: https://example.com/img.png?w=200&cb=123 -->
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### `uj_cachebreak`
|
|
44
|
+
|
|
45
|
+
Appends a cache-busting `cb=<timestamp>` query parameter to any URL. Uses the same consistent timestamp as `site.uj.cache_breaker`. Handles URLs with or without existing query strings.
|
|
46
|
+
|
|
47
|
+
```liquid
|
|
48
|
+
{{ site.brand.images.brandmark | uj_cachebreak }}
|
|
49
|
+
<!-- Output: https://cdn.example.com/logo.svg?cb=1234567890 -->
|
|
50
|
+
|
|
51
|
+
{{ "/assets/css/main.bundle.css" | uj_cachebreak }}
|
|
52
|
+
<!-- Output: /assets/css/main.bundle.css?cb=1234567890 -->
|
|
53
|
+
```
|
|
54
|
+
|
|
31
55
|
### `iftruthy` / `iffalsy`
|
|
32
56
|
|
|
33
57
|
Custom tags that check JavaScript truthiness (not null, undefined, or empty string).
|
|
@@ -67,3 +91,5 @@ asset_path: blog/post
|
|
|
67
91
|
```
|
|
68
92
|
|
|
69
93
|
Uses `/assets/css/pages/{{ asset_path }}.bundle.css` instead of deriving from `page.canonical.path`. Useful when multiple pages share assets (e.g., all blog posts). See also [docs/layouts-and-pages.md](layouts-and-pages.md).
|
|
94
|
+
|
|
95
|
+
**⚠️ Only set `asset_path` when sharing a module between pages.** Without it, the loader resolves `<pagePath>/index.js` automatically — that's the correct default for pages whose JS lives at `src/assets/js/pages/<pagePath>/index.js`. Setting `asset_path` overrides this to look for an **exact file** (`<asset_path>.js`), NOT a directory's `index.js`. A wrong `asset_path` fails **silently** — the page renders but the module never loads.
|