ultimate-jekyll-manager 0.0.86 ā 0.0.88
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/README.md +1 -1
- package/dist/commands/blogify.js +5 -5
- package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/blog/post.html +2 -2
- package/dist/defaults/hooks/middleware:request.js +12 -0
- package/dist/gulp/tasks/imagemin.js +2 -2
- package/dist/gulp/tasks/jekyll.js +3 -0
- package/dist/gulp/tasks/serve.js +48 -2
- package/dist/gulp/tasks/translation.js +10 -10
- package/firebase-debug.log +32 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -115,7 +115,7 @@ npx uj imagemin
|
|
|
115
115
|
The imagemin task will:
|
|
116
116
|
- Process images from `src/assets/images/**/*.{jpg,jpeg,png}`
|
|
117
117
|
- Generate multiple sizes (1024px, 425px) and WebP formats
|
|
118
|
-
- Cache processed images in `
|
|
118
|
+
- Cache processed images in `cache-imagemin` branch (when using GitHub cache)
|
|
119
119
|
- Skip already processed images on subsequent runs
|
|
120
120
|
|
|
121
121
|
<!-- Developing -->
|
package/dist/commands/blogify.js
CHANGED
|
@@ -106,18 +106,18 @@ function getRandomElement(array) {
|
|
|
106
106
|
function getRandomCategories() {
|
|
107
107
|
// Determine how many categories (1-3)
|
|
108
108
|
const numCategories = 1 + Math.floor(Math.random() * 3);
|
|
109
|
-
|
|
109
|
+
|
|
110
110
|
// Copy array to avoid modifying original
|
|
111
111
|
const availableCategories = [...blogCategories];
|
|
112
112
|
const selectedCategories = [];
|
|
113
|
-
|
|
113
|
+
|
|
114
114
|
// Select random categories without duplicates
|
|
115
115
|
for (let i = 0; i < numCategories && availableCategories.length > 0; i++) {
|
|
116
116
|
const index = Math.floor(Math.random() * availableCategories.length);
|
|
117
117
|
selectedCategories.push(availableCategories[index]);
|
|
118
118
|
availableCategories.splice(index, 1); // Remove selected to avoid duplicates
|
|
119
119
|
}
|
|
120
|
-
|
|
120
|
+
|
|
121
121
|
return selectedCategories;
|
|
122
122
|
}
|
|
123
123
|
|
|
@@ -177,7 +177,7 @@ async function generatePostImages(postId, titleSuffix) {
|
|
|
177
177
|
try {
|
|
178
178
|
await downloadImage(imageUrl, imagePath);
|
|
179
179
|
downloadedImages.push({
|
|
180
|
-
path: `/assets/images/blog/post-${postId}/${randomName}.jpg`,
|
|
180
|
+
path: `/assets/images/blog/posts/post-${postId}/${randomName}.jpg`,
|
|
181
181
|
alt: `${randomName.replace(/-/g, ' ')} image`
|
|
182
182
|
});
|
|
183
183
|
logger.log(` Downloaded image ${i}: ${randomName}.jpg`);
|
|
@@ -297,7 +297,7 @@ module.exports = async function (options) {
|
|
|
297
297
|
// Generate random description
|
|
298
298
|
const wordCount = 10 + Math.floor(Math.random() * 11); // 10-20 words
|
|
299
299
|
const randomWords = getRandomWords(wordCount);
|
|
300
|
-
|
|
300
|
+
|
|
301
301
|
// Generate random categories (1-3 from 5 possible)
|
|
302
302
|
const postCategories = getRandomCategories();
|
|
303
303
|
|
|
@@ -64,7 +64,7 @@ newsletter:
|
|
|
64
64
|
<time datetime="{{ page.date | date_to_xmlschema }}" class="text-muted small d-block">
|
|
65
65
|
{{ page.date | date: "%b %d, %Y" }}
|
|
66
66
|
</time>
|
|
67
|
-
<div class="badge bg-primary">{% uj_readtime
|
|
67
|
+
<div class="badge bg-primary">{% uj_readtime content %} min read</div>
|
|
68
68
|
</div>
|
|
69
69
|
</div>
|
|
70
70
|
</div>
|
|
@@ -72,7 +72,7 @@ newsletter:
|
|
|
72
72
|
|
|
73
73
|
<div class="row justify-content-center">
|
|
74
74
|
<div class="col-xl-10 col-lg-10 col-md-12 col-12 mb-5" data-lazy="@class animation-slide-up">
|
|
75
|
-
{%- uj_post page.post.id, "image-tag", class="img-fluid rounded-3 w-100 blog-post-image"
|
|
75
|
+
{%- uj_post page.post.id, "image-tag", class="img-fluid rounded-3 w-100 blog-post-image" -%}
|
|
76
76
|
</div>
|
|
77
77
|
</div>
|
|
78
78
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Libraries
|
|
2
|
+
const Manager = new (require('ultimate-jekyll-manager/build'));
|
|
3
|
+
const logger = Manager.logger('middleware:request');
|
|
4
|
+
|
|
5
|
+
// Hook
|
|
6
|
+
module.exports = async (context) => {
|
|
7
|
+
// Destructure context
|
|
8
|
+
const { req, res, pathname } = context;
|
|
9
|
+
|
|
10
|
+
// Log
|
|
11
|
+
// logger.log(`Processing request for ${pathname}`);
|
|
12
|
+
}
|
|
@@ -12,8 +12,8 @@ const GitHubCache = require('./utils/github-cache');
|
|
|
12
12
|
const rootPathProject = Manager.getRootPath('project');
|
|
13
13
|
|
|
14
14
|
// Settings
|
|
15
|
-
const CACHE_DIR = '.temp/imagemin';
|
|
16
|
-
const CACHE_BRANCH = 'uj-imagemin';
|
|
15
|
+
const CACHE_DIR = '.temp/cache/imagemin';
|
|
16
|
+
const CACHE_BRANCH = 'cache-uj-imagemin';
|
|
17
17
|
|
|
18
18
|
// Variables
|
|
19
19
|
let githubCache;
|
|
@@ -42,6 +42,9 @@ const input = [
|
|
|
42
42
|
// Include plugin so we can live-reload it
|
|
43
43
|
`${rootPathPackage}/../jekyll-uj-powertools/**/*`,
|
|
44
44
|
|
|
45
|
+
// Project hooks
|
|
46
|
+
`${rootPathProject}/hooks/**/*.js`,
|
|
47
|
+
|
|
45
48
|
// Files to exclude
|
|
46
49
|
'!dist/.jekyll-cache/**',
|
|
47
50
|
'!dist/.jekyll-metadata',
|
package/dist/gulp/tasks/serve.js
CHANGED
|
@@ -197,6 +197,9 @@ async function processRequestMiddleware(req, res, next) {
|
|
|
197
197
|
logger.log(`Serving ${pathname}`);
|
|
198
198
|
}
|
|
199
199
|
|
|
200
|
+
// Run middleware:request hook to allow custom URL rewriting
|
|
201
|
+
await hook('middleware:request', { req, res, pathname });
|
|
202
|
+
|
|
200
203
|
// Process the post request
|
|
201
204
|
if (pathname.match(/\/_process/)) {
|
|
202
205
|
const qsUrl = url.searchParams.get('url');
|
|
@@ -264,9 +267,14 @@ async function processRequestMiddleware(req, res, next) {
|
|
|
264
267
|
}
|
|
265
268
|
|
|
266
269
|
// Check if the URL is missing a trailing slash and does not have an extension
|
|
267
|
-
|
|
270
|
+
// console.log('---URL 1', req.url);
|
|
271
|
+
if (
|
|
272
|
+
(!pathname.endsWith('/') || pathname.endsWith('/blog/'))
|
|
273
|
+
&& !path.extname(pathname)
|
|
274
|
+
) {
|
|
268
275
|
// Get the new URL
|
|
269
|
-
const
|
|
276
|
+
const strippedPath = pathname.replace(/\/$/, '');
|
|
277
|
+
const newURL = `${strippedPath}.html`;
|
|
270
278
|
|
|
271
279
|
// Log
|
|
272
280
|
// logger.log(`Rewriting ${pathname} to ${newURL}`);
|
|
@@ -274,6 +282,7 @@ async function processRequestMiddleware(req, res, next) {
|
|
|
274
282
|
// Rewrite it to serve the .html extension
|
|
275
283
|
req.url = newURL;
|
|
276
284
|
}
|
|
285
|
+
// console.log('---URL 2', req.url);
|
|
277
286
|
|
|
278
287
|
// Special LOCAL case: Rewrite /blog to blog.html since Jekyll fucks it up locally (probably due to pagination)
|
|
279
288
|
// Disaboed because we moved it to the jekyll task
|
|
@@ -292,6 +301,9 @@ async function processRequestMiddleware(req, res, next) {
|
|
|
292
301
|
req.url = '/404.html';
|
|
293
302
|
}
|
|
294
303
|
|
|
304
|
+
// LOG REQUEST
|
|
305
|
+
// logger.log(`Serving file: ${req.url}`);
|
|
306
|
+
|
|
295
307
|
// Continue
|
|
296
308
|
return next();
|
|
297
309
|
}
|
|
@@ -323,3 +335,37 @@ function receiveRequestBody(req) {
|
|
|
323
335
|
});
|
|
324
336
|
});
|
|
325
337
|
}
|
|
338
|
+
|
|
339
|
+
// Run hooks
|
|
340
|
+
async function hook(file, context) {
|
|
341
|
+
// Full path
|
|
342
|
+
const fullPath = path.join(process.cwd(), 'hooks', `${file}.js`);
|
|
343
|
+
|
|
344
|
+
// Check if it exists
|
|
345
|
+
if (!jetpack.exists(fullPath)) {
|
|
346
|
+
// Silently skip if hook doesn't exist (it's optional)
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// Log
|
|
351
|
+
// logger.log(`Running hook: ${fullPath}`);
|
|
352
|
+
|
|
353
|
+
// Load hook
|
|
354
|
+
let hookFn;
|
|
355
|
+
try {
|
|
356
|
+
// Clear the cache to allow live reloading of hooks during development
|
|
357
|
+
delete require.cache[require.resolve(fullPath)];
|
|
358
|
+
|
|
359
|
+
// Load the hook
|
|
360
|
+
hookFn = require(fullPath);
|
|
361
|
+
} catch (e) {
|
|
362
|
+
throw new Error(`Error loading hook: ${fullPath} ${e.stack}`);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// Execute hook
|
|
366
|
+
try {
|
|
367
|
+
return await hookFn(context);
|
|
368
|
+
} catch (e) {
|
|
369
|
+
throw new Error(`Error running hook: ${fullPath} ${e.stack}`);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
@@ -24,12 +24,12 @@ const rootPathPackage = Manager.getRootPath('main');
|
|
|
24
24
|
const rootPathProject = Manager.getRootPath('project');
|
|
25
25
|
|
|
26
26
|
// Check if BEM env variable is set
|
|
27
|
-
// get cached translations JSON (only once per run, so keep track of how many times this has run) from branch
|
|
27
|
+
// get cached translations JSON (only once per run, so keep track of how many times this has run) from branch cache-translation
|
|
28
28
|
// loop thru all html and md pages in pages/ dir (main and project)
|
|
29
29
|
// SKIP files in _translations dir
|
|
30
30
|
// if there is no translation (or translation is too old), send to AI @ itw
|
|
31
31
|
// save the translation into the cache (file path, date) and write the file to _translations/{code}/{original file path + name}
|
|
32
|
-
// push the updated translation JSON to the branch
|
|
32
|
+
// push the updated translation JSON to the branch cache-translation
|
|
33
33
|
|
|
34
34
|
// Settings
|
|
35
35
|
const AI = {
|
|
@@ -37,8 +37,8 @@ const AI = {
|
|
|
37
37
|
inputCost: 0.40, // $0.40 per 1M tokens
|
|
38
38
|
outputCost: 1.60, // $1.60 per 1M tokens
|
|
39
39
|
}
|
|
40
|
-
const CACHE_DIR = '.temp/translation';
|
|
41
|
-
const CACHE_BRANCH = 'uj-translation';
|
|
40
|
+
const CACHE_DIR = '.temp/cache/translation';
|
|
41
|
+
const CACHE_BRANCH = 'cache-uj-translation';
|
|
42
42
|
const RECHECK_DAYS = 0;
|
|
43
43
|
// const LOUD = false;
|
|
44
44
|
const LOUD = Manager.isServer() || process.env.UJ_LOUD_LOGS === 'true';
|
|
@@ -161,7 +161,7 @@ async function processTranslation() {
|
|
|
161
161
|
const enabled = config?.translation?.enabled !== false;
|
|
162
162
|
const languages = config?.translation?.languages || [];
|
|
163
163
|
const updatedFiles = new Set();
|
|
164
|
-
|
|
164
|
+
|
|
165
165
|
// Track timing
|
|
166
166
|
const startTime = Date.now();
|
|
167
167
|
|
|
@@ -509,7 +509,7 @@ async function processTranslation() {
|
|
|
509
509
|
const elapsedMs = endTime - startTime;
|
|
510
510
|
const elapsedSeconds = Math.floor(elapsedMs / 1000);
|
|
511
511
|
const elapsedMinutes = Math.floor(elapsedSeconds / 60);
|
|
512
|
-
const elapsedFormatted = elapsedMinutes > 0
|
|
512
|
+
const elapsedFormatted = elapsedMinutes > 0
|
|
513
513
|
? `${elapsedMinutes}m ${elapsedSeconds % 60}s`
|
|
514
514
|
: `${elapsedSeconds}s`;
|
|
515
515
|
|
|
@@ -521,13 +521,13 @@ async function processTranslation() {
|
|
|
521
521
|
// Log detailed statistics
|
|
522
522
|
logger.log('\nš Translation Statistics:');
|
|
523
523
|
logger.log('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā');
|
|
524
|
-
|
|
524
|
+
|
|
525
525
|
// Timing
|
|
526
526
|
logger.log('ā±ļø Timing:');
|
|
527
527
|
logger.log(` Start time: ${new Date(startTime).toLocaleTimeString()}`);
|
|
528
528
|
logger.log(` End time: ${new Date(endTime).toLocaleTimeString()}`);
|
|
529
529
|
logger.log(` Total elapsed: ${elapsedFormatted}`);
|
|
530
|
-
|
|
530
|
+
|
|
531
531
|
// File processing stats
|
|
532
532
|
logger.log('\nš File Processing:');
|
|
533
533
|
logger.log(` Total processed: ${stats.totalProcessed}`);
|
|
@@ -550,13 +550,13 @@ async function processTranslation() {
|
|
|
550
550
|
logger.log(` Output cost: $${outputCost.toFixed(4)}`);
|
|
551
551
|
logger.log(` Total cost: $${totalCost.toFixed(4)}`);
|
|
552
552
|
}
|
|
553
|
-
|
|
553
|
+
|
|
554
554
|
logger.log('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n');
|
|
555
555
|
|
|
556
556
|
// Push updated translation cache back to cache branch
|
|
557
557
|
if (githubCache && githubCache.hasCredentials()) {
|
|
558
558
|
logger.log(`š Updating translation cache README with latest statistics...`);
|
|
559
|
-
|
|
559
|
+
|
|
560
560
|
// Collect all cache files to push
|
|
561
561
|
const allCacheFiles = glob(path.join(CACHE_DIR, '**/*'), { nodir: true });
|
|
562
562
|
|
package/firebase-debug.log
CHANGED
|
@@ -6,3 +6,35 @@
|
|
|
6
6
|
[debug] [2025-10-20T10:34:24.966Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
7
7
|
[debug] [2025-10-20T10:34:24.966Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
8
8
|
[debug] [2025-10-20T10:34:24.966Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
9
|
+
[debug] [2025-10-20T22:22:09.824Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
10
|
+
[debug] [2025-10-20T22:22:09.824Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
11
|
+
[debug] [2025-10-20T22:22:09.827Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
12
|
+
[debug] [2025-10-20T22:22:09.827Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
13
|
+
[debug] [2025-10-20T22:22:09.827Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
14
|
+
[debug] [2025-10-20T22:22:09.827Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
15
|
+
[debug] [2025-10-20T22:22:09.827Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
16
|
+
[debug] [2025-10-20T22:22:09.827Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
17
|
+
[debug] [2025-10-20T22:22:28.418Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
18
|
+
[debug] [2025-10-20T22:22:28.420Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
19
|
+
[debug] [2025-10-20T22:22:28.420Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
20
|
+
[debug] [2025-10-20T22:22:28.420Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
21
|
+
[debug] [2025-10-20T22:22:28.421Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
22
|
+
[debug] [2025-10-20T22:22:28.425Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
23
|
+
[debug] [2025-10-20T22:22:28.425Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
24
|
+
[debug] [2025-10-20T22:22:28.425Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
25
|
+
[debug] [2025-10-20T22:36:23.096Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
26
|
+
[debug] [2025-10-20T22:36:23.097Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
27
|
+
[debug] [2025-10-20T22:36:23.099Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
28
|
+
[debug] [2025-10-20T22:36:23.099Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
29
|
+
[debug] [2025-10-20T22:36:23.099Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
30
|
+
[debug] [2025-10-20T22:36:23.099Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
31
|
+
[debug] [2025-10-20T22:36:23.099Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
32
|
+
[debug] [2025-10-20T22:36:23.099Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
33
|
+
[debug] [2025-10-21T00:37:54.667Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
34
|
+
[debug] [2025-10-21T00:37:54.669Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
35
|
+
[debug] [2025-10-21T00:37:54.670Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
36
|
+
[debug] [2025-10-21T00:37:54.670Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
37
|
+
[debug] [2025-10-21T00:37:54.668Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
38
|
+
[debug] [2025-10-21T00:37:54.671Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|
|
39
|
+
[debug] [2025-10-21T00:37:54.672Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
|
40
|
+
[debug] [2025-10-21T00:37:54.672Z] > authorizing via signed-in user (ian.wiedenman@gmail.com)
|