ultimate-jekyll-manager 1.2.0 → 1.2.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.
package/docs/assets.md ADDED
@@ -0,0 +1,314 @@
1
+ # Asset Organization
2
+
3
+ This document covers UJM's asset layout, consuming-project overrides, the JSON-driven section configuration system (nav, footer, account dropdown), frontmatter-driven page customization, webpack aliases, and the page module pattern.
4
+
5
+ ## Ultimate Jekyll Manager Files (THIS project)
6
+
7
+ **CSS:**
8
+ - `src/assets/css/ultimate-jekyll-manager.scss` — Main UJ stylesheet (provides core styles)
9
+ - `src/assets/css/global/` — Global UJ styles
10
+ - `src/assets/css/pages/` — Page-specific styles provided by UJ
11
+ - Format: `src/assets/css/pages/[page-name]/index.scss`
12
+ - Example: `src/assets/css/pages/download/index.scss`
13
+
14
+ **JavaScript:**
15
+ - `src/assets/js/ultimate-jekyll-manager.js` — Main UJ JavaScript entry point (provides core functionality)
16
+ - `src/assets/js/core/` — Core UJ modules
17
+ - `src/assets/js/pages/` — Page-specific JavaScript provided by UJ
18
+ - Format: `src/assets/js/pages/[page-name]/index.js`
19
+ - Example: `src/assets/js/pages/download/index.js`
20
+ - `src/assets/js/libs/` — UJ library modules (prerendered-icons, form-manager, authorized-fetch, etc.)
21
+
22
+ **Default Pages & Layouts:**
23
+
24
+ UJ provides default page templates and layouts in `src/defaults/dist/` that are copied to consuming projects. These are NOT meant to be edited by users.
25
+
26
+ - Format: `src/defaults/dist/_layouts/themes/[theme-id]/frontend/pages/[page-name].html`
27
+ - Examples:
28
+ - `src/defaults/dist/_layouts/themes/classy/frontend/pages/download.html`
29
+ - `src/defaults/dist/_layouts/themes/classy/frontend/pages/pricing.html`
30
+ - `src/defaults/dist/_layouts/themes/classy/frontend/pages/payment/checkout.html`
31
+ - `src/defaults/dist/_layouts/themes/classy/frontend/pages/payment/confirmation.html`
32
+ - `src/defaults/dist/_layouts/themes/classy/frontend/pages/contact.html`
33
+ - Core layouts:
34
+ - `src/defaults/dist/_layouts/core/root.html` — Root HTML wrapper
35
+ - `src/defaults/dist/_layouts/themes/[theme-id]/frontend/core/base.html` — Theme base layout
36
+
37
+ **Complete UJ Page Example:**
38
+ - **HTML:** `src/defaults/dist/_layouts/themes/classy/frontend/pages/download.html`
39
+ - **CSS:** `src/assets/css/pages/download/index.scss`
40
+ - **JS:** `src/assets/js/pages/download/index.js`
41
+
42
+ These files serve as blueprints and reference implementations. When building custom pages in consuming projects, reference these for patterns and best practices.
43
+
44
+ **IMPORTANT:** Consuming projects CAN create files with the same paths in their own `src/` directory to override UJ defaults, but this should ONLY be done when absolutely necessary. Prefer using `src/pages/` and `src/_layouts/` for custom pages instead of overriding UJ default files.
45
+
46
+ ## Consuming Project Files
47
+
48
+ **CSS:**
49
+ - `src/assets/css/main.scss` — Site-wide custom styles (runs on every page, edits by consuming project)
50
+ - `src/assets/css/pages/` — Page-specific custom styles
51
+ - Format: `src/assets/css/pages/[page-name]/index.scss`
52
+
53
+ **JavaScript:**
54
+ - `src/assets/js/main.js` — Site-wide custom JavaScript (runs on every page, edits by consuming project)
55
+ - `src/assets/js/pages/` — Page-specific custom JavaScript
56
+ - Format: `src/assets/js/pages/[page-name]/index.js`
57
+
58
+ **Pages & Layouts:**
59
+ - `src/pages/` — Individual page HTML/Markdown files
60
+ - `src/_layouts/` — Custom layouts for the consuming project
61
+
62
+ **Asset Loading:** Page-specific CSS/JS files are automatically included based on the page's canonical path. Override with `asset_path` frontmatter.
63
+
64
+ ## Section Configuration Files (JSON)
65
+
66
+ UJ provides JSON configuration files for common sections like navigation and footer. These JSON files are consumed by corresponding HTML templates during the build process.
67
+
68
+ **Configuration Files:**
69
+ - `src/defaults/src/_includes/frontend/sections/nav.json` — Navigation configuration
70
+ - `src/defaults/src/_includes/frontend/sections/footer.json` — Footer configuration
71
+ - `src/defaults/src/_includes/global/sections/account.json` — Account dropdown configuration (shared across frontend nav, backend topbar, admin topbar)
72
+
73
+ **How It Works:**
74
+ 1. JSON files contain structured data (links, labels, settings)
75
+ 2. HTML templates in `src/defaults/dist/_includes/themes/[theme-id]/` read and render this data
76
+ 3. The build process converts `.json` → data loaded by `.html` templates
77
+
78
+ **Customizing Navigation/Footer:**
79
+
80
+ Consuming projects should create their own JSON files in `src/_includes/frontend/sections/`:
81
+ - `src/_includes/frontend/sections/nav.json`
82
+ - `src/_includes/frontend/sections/footer.json`
83
+
84
+ **Example: Footer Configuration**
85
+
86
+ ```json
87
+ {
88
+ logo: {
89
+ href: '/',
90
+ class: 'filter-adaptive',
91
+ text: '{{ site.brand.name }}',
92
+ description: '{{ site.meta.description }}',
93
+ },
94
+ links: [
95
+ {
96
+ label: 'Company',
97
+ href: null,
98
+ links: [
99
+ {
100
+ label: 'About Us',
101
+ href: '/about',
102
+ },
103
+ {
104
+ label: 'Pricing',
105
+ href: '/pricing',
106
+ },
107
+ ],
108
+ },
109
+ ],
110
+ socials: {
111
+ enabled: true,
112
+ },
113
+ copyright: {
114
+ enabled: true,
115
+ text: null,
116
+ },
117
+ }
118
+ ```
119
+
120
+ **Note:** These are JSON5 files (support comments, trailing commas, unquoted keys). The corresponding HTML templates automatically process these files during the build.
121
+
122
+ ## Account Dropdown (Shared Component)
123
+
124
+ The account dropdown (avatar + user info + menu items) is a shared component used across the frontend nav, backend topbar, and admin topbar. It is defined once and included everywhere.
125
+
126
+ **Data Source:** `src/defaults/src/_includes/global/sections/account.json`
127
+
128
+ This is the single source of truth for account dropdown menu items. Consuming projects can override it by creating `src/_includes/global/sections/account.json`.
129
+
130
+ **Example: account.json**
131
+
132
+ ```json5
133
+ {
134
+ dropdown: [
135
+ { label: 'Account', href: '/account#profile', icon: 'user-gear' },
136
+ { label: 'Dashboard', href: '/dashboard', icon: 'gauge-high' },
137
+ { divider: true, attributes: [['data-wm-bind', '@show auth.account.roles.admin']] },
138
+ { label: 'Admin Panel', href: '/admin/dashboard', icon: 'shield-halved', attributes: [['data-wm-bind', '@show auth.account.roles.admin']] },
139
+ { divider: true },
140
+ { label: 'Sign Out', icon: 'arrow-right-from-bracket', class: 'auth-signout-btn text-danger' }
141
+ ]
142
+ }
143
+ ```
144
+
145
+ **Include:** `src/defaults/dist/_includes/themes/classy/global/sections/account.html`
146
+
147
+ This renders the full account dropdown: avatar button with profile photo, user info header (displayName + email), and the menu items from `account.json`.
148
+
149
+ **Parameters:**
150
+
151
+ | Parameter | Default | Description |
152
+ |-----------|---------|-------------|
153
+ | `size` | `md` | Avatar size class (`sm`, `md`, `lg`) |
154
+ | `attributes` | none | Array of `[name, value]` attribute pairs for the dropdown wrapper |
155
+
156
+ **Usage in templates:**
157
+
158
+ ```liquid
159
+ {% include themes/classy/global/sections/account.html size="md" attributes=action.attributes %}
160
+ ```
161
+
162
+ **How it's wired into nav/topbar:**
163
+
164
+ In `nav.json` or `topbar.json`, set `type: 'account'` on an action — the rendering templates detect this type and include the shared account dropdown automatically. No `dropdown` array is needed on the action:
165
+
166
+ ```json5
167
+ {
168
+ type: 'account',
169
+ attributes: [
170
+ ['data-wm-bind', '@show auth.user'],
171
+ ['hidden', '']
172
+ ],
173
+ }
174
+ ```
175
+
176
+ **File Locations:**
177
+
178
+ | Purpose | Path |
179
+ |---------|------|
180
+ | Account data (SSOT) | `src/defaults/src/_includes/global/sections/account.json` |
181
+ | Account include | `src/defaults/dist/_includes/themes/classy/global/sections/account.html` |
182
+ | Frontend nav (uses include) | `src/defaults/dist/_includes/themes/classy/frontend/sections/nav.html` |
183
+ | Backend topbar (uses include) | `src/defaults/dist/_includes/themes/classy/backend/sections/topbar.html` |
184
+ | Admin topbar (wraps backend) | `src/defaults/dist/_includes/themes/classy/admin/sections/topbar.html` |
185
+
186
+ ## Customizing Default Pages via Frontmatter
187
+
188
+ **BEST PRACTICE:** UJ default pages are designed to be customized through frontmatter WITHOUT writing any HTML. Consuming projects can create a simple page that includes ONLY frontmatter to configure the default page's behavior.
189
+
190
+ **How It Works:**
191
+ 1. UJ default pages use `page.resolved` to access merged frontmatter (site → layout → page)
192
+ 2. **IMPORTANT:** Before customizing, READ the UJ default page in `src/defaults/dist/_layouts/` to understand available frontmatter options and how they're used
193
+ 3. Consuming projects create a page in `src/pages/` with custom frontmatter
194
+ 4. The page uses a UJ layout (e.g., `blueprint/pricing`)
195
+ 5. Frontmatter overrides default values without any HTML
196
+
197
+ **Example: Customizing the Pricing Page**
198
+
199
+ **Step 1:** Read the UJ default pricing page to see available frontmatter options:
200
+ - File: `src/defaults/dist/_layouts/themes/classy/frontend/pages/pricing.html`
201
+ - Look for frontmatter at the top and how `page.resolved.pricing` is used in the HTML
202
+
203
+ **Step 2:** In consuming project, create `src/pages/pricing.html`:
204
+
205
+ ```yaml
206
+ ---
207
+ ### ALL PAGES ###
208
+ layout: blueprint/pricing
209
+ permalink: /pricing
210
+
211
+ ### PAGE CONFIG ###
212
+ pricing:
213
+ price_per_unit:
214
+ enabled: true
215
+ feature_id: "credits"
216
+ label: "credit"
217
+ plans:
218
+ - id: "basic"
219
+ name: "Basic"
220
+ tagline: "best for getting started"
221
+ url: "/download"
222
+ pricing:
223
+ monthly: 0
224
+ annually: 0
225
+ features:
226
+ - id: "credits"
227
+ name: "Credits"
228
+ value: 1
229
+ icon: "sparkles"
230
+ ...
231
+ ---
232
+ ```
233
+
234
+ That's it! No HTML needed. The UJ pricing layout reads `page.resolved.pricing` and renders the plans accordingly.
235
+
236
+ **When to Use Frontmatter Customization:**
237
+ - ✅ Customizing UJ default pages (pricing, contact, download, etc.)
238
+ - ✅ Changing configuration without touching HTML
239
+ - ✅ Maintaining upgradability when UJ updates
240
+
241
+ **When to Create Custom Pages:**
242
+ - ❌ Building entirely new page types
243
+ - ❌ Needing custom HTML structure
244
+ - ❌ Pages with unique layouts not provided by UJ
245
+
246
+ ## Webpack Import Aliases
247
+
248
+ UJM defines two webpack aliases (in `src/gulp/tasks/webpack.js`) for importing assets in JavaScript:
249
+
250
+ | Alias | Resolves To | Purpose |
251
+ |-------|------------|---------|
252
+ | `__main_assets__` | `[UJM package]/dist/assets` | UJM's own built-in assets (core modules, libraries, pages) |
253
+ | `__project_assets__` | `[consuming project]/src/assets` | The consuming project's custom assets |
254
+
255
+ > A third alias, `__theme__`, resolves to the project's theme if one exists, else UJM's theme. See [CLAUDE.md → Frontend Manager](../CLAUDE.md#frontend-manager-srcindexjs).
256
+
257
+ **`__main_assets__`** — Import UJM libraries and core modules:
258
+
259
+ ```javascript
260
+ import { FormManager } from '__main_assets__/js/libs/form-manager.js';
261
+ import authorizedFetch from '__main_assets__/js/libs/authorized-fetch.js';
262
+ import { getPrerenderedIcon } from '__main_assets__/js/libs/prerendered-icons.js';
263
+ ```
264
+
265
+ **`__project_assets__`** — Import consuming project's own assets:
266
+
267
+ ```javascript
268
+ // Used in src/index.js to load project-specific page modules
269
+ import(`__project_assets__/js/pages/${pageModulePath}`)
270
+ ```
271
+
272
+ **How they work together:** `src/index.js` loads page modules from both aliases — first from `__main_assets__` (UJM defaults), then from `__project_assets__` (project overrides/extensions). If a project module doesn't exist, it gracefully skips. This enables a layered system where UJM provides defaults and consuming projects can extend or override page behavior.
273
+
274
+ **When to use which:**
275
+ - **`__main_assets__`** — When importing UJM-provided libraries, core modules, or referencing UJM's built-in page scripts
276
+ - **`__project_assets__`** — When a consuming project needs to import its own custom assets from within UJM-managed code
277
+
278
+ ## Page Module Structure
279
+
280
+ All page modules must follow this standardized pattern:
281
+
282
+ ```javascript
283
+ /**
284
+ * [Page Name] Page JavaScript
285
+ */
286
+
287
+ // Libraries
288
+ import webManager from 'web-manager';
289
+
290
+ // Module
291
+ export default () => {
292
+ return new Promise(async function (resolve) {
293
+ // Initialize when DOM is ready
294
+ await webManager.dom().ready();
295
+
296
+ // Page initialization logic
297
+ helper1();
298
+
299
+ // Resolve after initialization
300
+ return resolve();
301
+ });
302
+ };
303
+
304
+ // Helper functions
305
+ function helper1() {
306
+ // Helper implementation
307
+ }
308
+ ```
309
+
310
+ **Key Points:**
311
+ - `web-manager` is a singleton — `import webManager from 'web-manager'` returns the same initialized instance everywhere. No need to receive it via params or store in module-level variables.
312
+ - Helpers are defined outside the main export function
313
+ - Always wait for DOM ready before manipulating elements
314
+ - Use `webManager.utilities().escapeHTML()` for XSS prevention — do NOT write your own escape function. See [docs/xss-prevention.md](xss-prevention.md).
package/docs/audit.md ADDED
@@ -0,0 +1,11 @@
1
+ # Audit Workflow
2
+
3
+ When fixing issues identified by the audit task (`src/gulp/tasks/audit.js`):
4
+
5
+ 1. Review the audit file location provided
6
+ 2. Create a TODO list for each audit category
7
+ 3. Read the ENTIRE audit file and plan fixes for each category
8
+ 4. Tackle issues incrementally — DO NOT attempt to fix everything at once
9
+ 5. Work through one category at a time
10
+
11
+ **Remember:** Audit files are large. Systematic, incremental fixes prevent errors and ensure thoroughness.
package/docs/css.md ADDED
@@ -0,0 +1,73 @@
1
+ # CSS Guidelines
2
+
3
+ ## Section Padding in Custom Pages
4
+
5
+ **DO NOT add padding classes to sections in custom frontend pages.**
6
+
7
+ UJ handles section padding automatically via the theme's layout system. When creating or editing custom frontend pages:
8
+
9
+ - ❌ DO NOT use `py-5`, `py-4`, `pt-5`, `pb-5`, `p-5`, etc. on `<section>` elements
10
+ - ❌ DO NOT add vertical padding to sections manually
11
+ - ✅ Let the UJ theme handle section spacing automatically
12
+
13
+ **The ONLY exception:** Add padding if the user EXPLICITLY requests it for a specific section.
14
+
15
+ ## Theme-Adaptive Classes
16
+
17
+ **DO NOT USE:** `bg-light`, `bg-dark`, `text-light`, `text-dark`
18
+
19
+ Ultimate Jekyll supports both light and dark modes. Use adaptive classes instead:
20
+
21
+ **Backgrounds:**
22
+ - `bg-body` — Primary background
23
+ - `bg-body-secondary` — Secondary background
24
+ - `bg-body-tertiary` — Tertiary background
25
+
26
+ **Text:**
27
+ - `text-body` — Body text color
28
+
29
+ **Buttons:**
30
+ - `btn-adaptive` — Adaptive button
31
+ - `btn-outline-adaptive` — Adaptive outline button
32
+
33
+ These classes automatically adapt to the current theme mode. See [docs/appearance.md](appearance.md) for the dark/light mode switching system.
34
+
35
+ ## Cards Inside Colored Sections
36
+
37
+ When placing cards inside sections with `bg-body-secondary` or `bg-body-tertiary`, cards will blend in because they share the same background color by default.
38
+
39
+ **Solution:** Add `bg-body` to cards to create visual contrast:
40
+
41
+ ```html
42
+ <!-- ❌ WRONG - Card blends with section background -->
43
+ <section class="bg-body-secondary">
44
+ <div class="card">...</div>
45
+ </section>
46
+
47
+ <!-- ✅ CORRECT - Card stands out with contrasting background -->
48
+ <section class="bg-body-secondary">
49
+ <div class="card bg-body">...</div>
50
+ </section>
51
+ ```
52
+
53
+ **Rule:** When a section uses `bg-body-secondary` or `bg-body-tertiary`, always add `bg-body` to child cards to ensure proper visual hierarchy.
54
+
55
+ ## HTML Element Attributes
56
+
57
+ The `<html>` element has data attributes for JavaScript/CSS targeting:
58
+
59
+ | Attribute | Values |
60
+ |-----------|--------|
61
+ | `data-theme-id` | Theme ID (e.g., `classy`) |
62
+ | `data-theme-target` | `frontend`, `backend`, `docs` |
63
+ | `data-bs-theme` | `light`, `dark` |
64
+ | `data-page-path` | Page permalink (e.g., `/about`) |
65
+ | `data-asset-path` | Custom asset path or empty |
66
+ | `data-environment` | `development`, `production` |
67
+ | `data-platform` | `windows`, `mac`, `linux`, `ios`, `android`, `chromeos`, `unknown` |
68
+ | `data-browser` | `chrome`, `firefox`, `safari`, `edge`, `opera`, `brave` |
69
+ | `data-device` | `mobile` (<768px), `tablet` (768-1199px), `desktop` (>=1200px) |
70
+ | `data-runtime` | `web`, `browser-extension`, `electron`, `node` |
71
+ | `aria-busy` | `true` (loading), `false` (ready) |
72
+
73
+ **Detection source:** `web-manager/src/modules/utilities.js`
package/docs/icons.md ADDED
@@ -0,0 +1,125 @@
1
+ # Icon System
2
+
3
+ Ultimate Jekyll uses Font Awesome icons but does NOT include the Font Awesome JavaScript or CSS library. All icons must be rendered server-side using Jekyll's `{% uj_icon %}` tag.
4
+
5
+ ## Available Icons
6
+
7
+ UJM ships with the **full Font Awesome Pro solid icon set** (4,600+ icons) at `assets/icons/font-awesome/solid/`, plus brand icons at `assets/icons/font-awesome/brands/`. Any Pro or Free solid/brand icon name can be used with `{% uj_icon %}` and prerendered icons. The icon style defaults to `solid` and can be configured via `site.config.icons.style`.
8
+
9
+ Browse available icons at: https://fontawesome.com/icons
10
+
11
+ ## When to Use `{% uj_icon %}` vs Prerendered Icons
12
+
13
+ **IMPORTANT:** Use the correct method based on WHERE the icon will be used:
14
+
15
+ ### Use `{% uj_icon %}` in HTML/Liquid Templates
16
+
17
+ When icons are part of the static HTML template, use `{% uj_icon %}` directly:
18
+
19
+ ```liquid
20
+ <!-- Alerts -->
21
+ <div class="alert alert-success">
22
+ {% uj_icon "circle-check", "fa-sm" %} Success message
23
+ </div>
24
+
25
+ <!-- Buttons -->
26
+ <button class="btn btn-primary">
27
+ {% uj_icon "paper-plane", "fa-md me-2" %}
28
+ Send
29
+ </button>
30
+
31
+ <!-- Labels -->
32
+ <label>
33
+ {% uj_icon "envelope", "fa-sm me-1 text-info" %}
34
+ Email
35
+ </label>
36
+ ```
37
+
38
+ **Use this when:**
39
+ - The icon is in a Jekyll template (.html file)
40
+ - The icon is static and known at build time
41
+ - The icon is part of the page structure
42
+
43
+ **Parameters:**
44
+ 1. Icon name (string or variable, without "fa-" prefix)
45
+ 2. CSS classes (optional, defaults to "fa-3xl")
46
+
47
+ ### Available Icon Sizes
48
+
49
+ - `fa-2xs` — Extra extra small
50
+ - `fa-xs` — Extra small
51
+ - `fa-sm` — Small
52
+ - `fa-md` — Medium (default base size)
53
+ - `fa-lg` — Large
54
+ - `fa-xl` — Extra large
55
+ - `fa-2xl` — 2x extra large
56
+ - `fa-3xl` — 3x extra large
57
+ - `fa-4xl` — 4x extra large
58
+ - `fa-5xl` — 5x extra large
59
+
60
+ **Size Examples:**
61
+
62
+ ```liquid
63
+ {% uj_icon "check", "fa-sm" %} <!-- Small inline icon -->
64
+ {% uj_icon "star", "fa-lg" %} <!-- Slightly larger -->
65
+ {% uj_icon "rocket", "fa-2xl" %} <!-- Hero/feature icons -->
66
+ {% uj_icon "chart-pie", "fa-4xl" %}<!-- Large placeholder icons -->
67
+ ```
68
+
69
+ ### Use Prerendered Icons in JavaScript
70
+
71
+ When icons need to be dynamically inserted via JavaScript, pre-render them in frontmatter and access them via the library:
72
+
73
+ **1. Add icons to page frontmatter (names only, no classes):**
74
+
75
+ ```yaml
76
+ ---
77
+ prerender_icons:
78
+ - name: "mobile"
79
+ - name: "envelope"
80
+ - name: "bell"
81
+ ---
82
+ ```
83
+
84
+ **2. Import the library in JavaScript:**
85
+
86
+ ```javascript
87
+ import { getPrerenderedIcon } from '__main_assets__/js/libs/prerendered-icons.js';
88
+ ```
89
+
90
+ **3. Use in your code (second argument works like uj_icon's second argument):**
91
+
92
+ ```javascript
93
+ // With size + classes (same as {% uj_icon "mobile", "fa-sm me-1" %})
94
+ $badge.innerHTML = `${getPrerenderedIcon('mobile', 'fa-sm me-1')} Push Notification`;
95
+
96
+ // Without classes (no size class on the <i> wrapper)
97
+ $el.innerHTML = getPrerenderedIcon('bell');
98
+ ```
99
+
100
+ **Use this when:**
101
+ - Icons are dynamically inserted via JavaScript
102
+ - Icons are part of dynamically generated content
103
+ - Icons are added to elements created with `document.createElement()`
104
+
105
+ ## What NOT to Do
106
+
107
+ **NEVER use manual icon HTML in JavaScript:**
108
+
109
+ ```javascript
110
+ // ❌ WRONG - Bootstrap Icons (we don't use Bootstrap Icons)
111
+ $el.innerHTML = '<i class="bi bi-check-circle"></i> Text';
112
+
113
+ // ❌ WRONG - Manual Font Awesome (we don't have FA JS/CSS)
114
+ $el.innerHTML = '<i class="fa-solid fa-check"></i> Text';
115
+
116
+ // ✅ CORRECT - Use prerendered icons
117
+ $el.innerHTML = `${getPrerenderedIcon('circle-check', 'fa-sm me-1')} Text`;
118
+ ```
119
+
120
+ ## Benefits
121
+
122
+ - Icons are rendered server-side with proper Font Awesome classes
123
+ - No client-side icon generation overhead
124
+ - Consistent icon styling across the application
125
+ - No Font Awesome JavaScript/CSS library needed
package/docs/images.md ADDED
@@ -0,0 +1,42 @@
1
+ # Blog Post Images
2
+
3
+ ## Inline Images with `@post/` Shortcut
4
+
5
+ Blog posts use standard markdown syntax for inline images. The `@post/` prefix provides a shortcut to reference images in the post's own image directory:
6
+
7
+ ```markdown
8
+ ![Alt text](@post/my-image.jpg)
9
+ ```
10
+
11
+ This resolves at build time to `/assets/images/blog/post-{id}/my-image.jpg`, where `{id}` comes from the post's `post.id` frontmatter value.
12
+
13
+ **All image types work:**
14
+
15
+ | Syntax | Result |
16
+ |--------|--------|
17
+ | `![alt](@post/file.jpg)` | Local post image (shortcut) |
18
+ | `![alt](/assets/images/other.jpg)` | Absolute path (any image) |
19
+ | `![alt](https://example.com/img.jpg)` | External URL |
20
+
21
+ **How it works:** The `markdown-images.rb` hook in `jekyll-uj-powertools` intercepts `![alt](url)` patterns during `pre_render`, resolves `@post/` prefixes, then converts each image to a responsive `<picture>` element with WebP sources and lazy loading via `{% uj_image %}`.
22
+
23
+ **Image directory structure:** Images for post ID `42` live at `src/assets/images/blog/post-42/`.
24
+
25
+ **Image class customization:** Set via frontmatter:
26
+
27
+ ```yaml
28
+ ---
29
+ theme:
30
+ post:
31
+ image:
32
+ class: "img-fluid rounded-3 shadow my-5"
33
+ ---
34
+ ```
35
+
36
+ ## BEM `admin/post` Image Handling
37
+
38
+ When posts are created via BEM's `POST /admin/post` endpoint:
39
+ 1. External image URLs in the markdown body (e.g., Unsplash) are downloaded
40
+ 2. Images are uploaded to `src/assets/images/blog/post-{id}/` on GitHub
41
+ 3. The body is rewritten to use `@post/{filename}` format
42
+ 4. Failed downloads are skipped (original external URL preserved)