ultimate-jekyll-manager 1.1.9 → 1.1.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/CHANGELOG.md CHANGED
@@ -14,6 +14,24 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
14
14
  - `Fixed` for any bug fixes.
15
15
  - `Security` in case of vulnerabilities.
16
16
 
17
+ ---
18
+ ## [1.1.10] - 2026-05-10
19
+ ### Removed
20
+ - `through2` dependency. Replaced with native `node:stream` `Transform` across 6 gulp task files (`defaults.js`, `distribute.js`, `jsonToHtml.js`, `minifyHtml.js`, `sass.js`, `utils/template-transform.js`). through2@5 became ESM-only with no `require` condition in its exports, breaking CJS require; the built-in `Transform` is a drop-in replacement
21
+
22
+ ### Changed
23
+ - Bumped `@babel/preset-env` from ^7.29.2 to ^7.29.5
24
+ - Bumped `dompurify` from ^3.3.3 to ^3.4.2
25
+ - Bumped `dotenv` from ^17.4.1 to ^17.4.2
26
+ - Bumped `fast-xml-parser` from ^5.5.11 to ^5.7.3
27
+ - Bumped `gulp-filter` from ^9.0.1 to ^10.0.0 (Node 22 ESM-CJS interop keeps `require('gulp-filter').default` working)
28
+ - Bumped `html-validate` from ^10.11.3 to ^10.16.0
29
+ - Bumped `libsodium-wrappers` from ^0.8.3 to ^0.8.4
30
+ - Bumped `postcss` from ^8.5.9 to ^8.5.14
31
+ - Bumped `prettier` from ^3.8.2 to ^3.8.3
32
+ - Bumped `web-manager` from ^4.1.40 to ^4.1.41
33
+ - Bumped `webpack` from ^5.106.1 to ^5.106.2
34
+
17
35
  ---
18
36
  ## [1.1.9] - 2026-04-23
19
37
  ### Added
@@ -2,7 +2,7 @@
2
2
  const Manager = new (require('../../build.js'));
3
3
  const logger = Manager.logger('defaults');
4
4
  const { src, dest, watch, series } = require('gulp');
5
- const through2 = require('through2');
5
+ const { Transform } = require('node:stream');
6
6
  const jetpack = require('fs-jetpack');
7
7
  const path = require('path');
8
8
  const { minimatch } = require('minimatch');
@@ -406,7 +406,9 @@ function defaults(complete, changedFile) {
406
406
  }
407
407
 
408
408
  function customTransform() {
409
- return through2.obj(function (file, _, callback) {
409
+ return new Transform({
410
+ objectMode: true,
411
+ transform(file, _, callback) {
410
412
  // Skip if it's a directory
411
413
  if (file.isDirectory()) {
412
414
  return callback(null, file);
@@ -539,6 +541,7 @@ function customTransform() {
539
541
 
540
542
  // Complete
541
543
  return callback();
544
+ },
542
545
  });
543
546
  }
544
547
  function defaultsWatcher(complete) {
@@ -2,7 +2,7 @@
2
2
  const Manager = new (require('../../build.js'));
3
3
  const logger = Manager.logger('distribute');
4
4
  const { src, dest, watch, series } = require('gulp');
5
- const through2 = require('through2');
5
+ const { Transform } = require('node:stream');
6
6
  const path = require('path');
7
7
  const jetpack = require('fs-jetpack');
8
8
  const { template } = require('node-powertools');
@@ -180,38 +180,41 @@ function getFilesRecursive(dir) {
180
180
  }
181
181
 
182
182
  function customTransform() {
183
- return through2.obj(function (file, _, callback) {
184
- // Skip if it's a directory
185
- if (file.isDirectory()) {
186
- return callback(null, file);
187
- }
183
+ return new Transform({
184
+ objectMode: true,
185
+ transform(file, _, callback) {
186
+ // Skip if it's a directory
187
+ if (file.isDirectory()) {
188
+ return callback(null, file);
189
+ }
188
190
 
189
- // Get relative path from src base
190
- const relativePath = path.relative(file.base, file.path).replace(/\\/g, '/');
191
+ // Get relative path from src base
192
+ const relativePath = path.relative(file.base, file.path).replace(/\\/g, '/');
191
193
 
192
- // Log
193
- if (LOUD) {
194
- logger.log(`Processing file: ${relativePath}`);
195
- }
194
+ // Log
195
+ if (LOUD) {
196
+ logger.log(`Processing file: ${relativePath}`);
197
+ }
196
198
 
197
- // Change path if it starts with 'pages/'
198
- // if (relativePath.startsWith('pages/')) {
199
- // // Remove 'pages/' prefix
200
- // const newRelativePath = relativePath.replace(/^pages\//, '');
199
+ // Change path if it starts with 'pages/'
200
+ // if (relativePath.startsWith('pages/')) {
201
+ // // Remove 'pages/' prefix
202
+ // const newRelativePath = relativePath.replace(/^pages\//, '');
201
203
 
202
- // // Update file path to remove pages directory
203
- // // This will make src/pages/index.html -> dist/index.html
204
- // file.path = path.join(file.base, newRelativePath);
204
+ // // Update file path to remove pages directory
205
+ // // This will make src/pages/index.html -> dist/index.html
206
+ // file.path = path.join(file.base, newRelativePath);
205
207
 
206
- // // Log
207
- // logger.log(` -> Moving from pages/ to root: ${newRelativePath}`);
208
- // }
208
+ // // Log
209
+ // logger.log(` -> Moving from pages/ to root: ${newRelativePath}`);
210
+ // }
209
211
 
210
- // Push the file
211
- this.push(file);
212
+ // Push the file
213
+ this.push(file);
212
214
 
213
- // Continue
214
- callback();
215
+ // Continue
216
+ callback();
217
+ },
215
218
  });
216
219
  }
217
220
 
@@ -2,7 +2,7 @@
2
2
  const Manager = new (require('../../build.js'));
3
3
  const logger = Manager.logger('json-to-html');
4
4
  const { src, dest, watch, series } = require('gulp');
5
- const through2 = require('through2');
5
+ const { Transform } = require('node:stream');
6
6
  const path = require('path');
7
7
  const jetpack = require('fs-jetpack');
8
8
  const { template } = require('node-powertools');
@@ -42,90 +42,96 @@ function jsonToHtml(complete) {
42
42
 
43
43
  // First, copy JSON files to _data directory
44
44
  const jsonCopy = src(input)
45
- .pipe(through2.obj(function (file, _, callback) {
46
- if (file.isDirectory()) {
47
- return callback(null, file);
48
- }
49
-
50
- try {
51
- // Parse JSON5 content
52
- const json5Content = file.contents.toString();
53
- const parsedData = JSON5.parse(json5Content);
54
-
55
- // Convert to regular JSON (pretty printed for readability)
56
- const regularJson = JSON.stringify(parsedData, null, 2);
57
-
58
- // Also write to _data directory for Jekyll to pick up
59
- const relativePath = path.relative(file.base, file.path);
60
- const dataPath = path.join(dataOutput, relativePath);
61
- const dataDir = path.dirname(dataPath);
62
-
63
- // Ensure directory exists
64
- jetpack.dir(dataDir);
65
-
66
- // Write regular JSON file to _data
67
- jetpack.write(dataPath, regularJson);
68
-
69
- // Track compiled files
70
- compiled[dataPath] = true;
71
-
72
- // Update file contents with regular JSON
73
- file.contents = Buffer.from(regularJson);
74
-
75
- callback(null, file);
76
- } catch (err) {
77
- logger.error(`Error parsing JSON5 file ${file.path}: ${err.message}`);
78
- callback(err);
79
- }
45
+ .pipe(new Transform({
46
+ objectMode: true,
47
+ transform(file, _, callback) {
48
+ if (file.isDirectory()) {
49
+ return callback(null, file);
50
+ }
51
+
52
+ try {
53
+ // Parse JSON5 content
54
+ const json5Content = file.contents.toString();
55
+ const parsedData = JSON5.parse(json5Content);
56
+
57
+ // Convert to regular JSON (pretty printed for readability)
58
+ const regularJson = JSON.stringify(parsedData, null, 2);
59
+
60
+ // Also write to _data directory for Jekyll to pick up
61
+ const relativePath = path.relative(file.base, file.path);
62
+ const dataPath = path.join(dataOutput, relativePath);
63
+ const dataDir = path.dirname(dataPath);
64
+
65
+ // Ensure directory exists
66
+ jetpack.dir(dataDir);
67
+
68
+ // Write regular JSON file to _data
69
+ jetpack.write(dataPath, regularJson);
70
+
71
+ // Track compiled files
72
+ compiled[dataPath] = true;
73
+
74
+ // Update file contents with regular JSON
75
+ file.contents = Buffer.from(regularJson);
76
+
77
+ callback(null, file);
78
+ } catch (err) {
79
+ logger.error(`Error parsing JSON5 file ${file.path}: ${err.message}`);
80
+ callback(err);
81
+ }
82
+ },
80
83
  }))
81
84
  .pipe(dest(dataOutput));
82
85
 
83
86
  // Then create HTML wrapper files
84
87
  const htmlGeneration = src(input)
85
- .pipe(through2.obj(function (file, _, callback) {
86
- // Skip if it's a directory
87
- if (file.isDirectory()) {
88
- return callback(null, file);
89
- }
90
-
91
- // Get relative path from src/_includes
92
- const relativePath = path.relative(file.base, file.path);
93
- const relativeDir = path.dirname(relativePath);
94
- const basename = path.basename(file.path, '.json');
95
-
96
- // Convert path for Jekyll data reference
97
- // _includes/frontend/sections/nav.json -> _includes.frontend.sections.nav
98
- const dataPath = '_includes.' + relativePath
99
- .replace(/\\/g, '/')
100
- .replace('.json', '')
101
- .split('/')
102
- .join('.');
103
-
104
- // Determine the template path
105
- // Look for corresponding template in themes/{theme}/{target}/...
106
- const templatePath = `themes/${config.theme.id}/${relativeDir}/${basename}.html`;
107
-
108
- // Create the HTML content
109
- const htmlContent = template(INCLUDE_TEMPLATE, {
110
- dataPath: dataPath,
111
- templatePath: templatePath
112
- });
113
-
114
- // Update file contents and extension
115
- file.contents = Buffer.from(htmlContent);
116
- file.path = file.path.replace('.json', '.html');
117
-
118
- // Log transformation
119
- logger.log(`Converting: ${relativePath} -> ${path.basename(file.path)}`);
120
- logger.log(` Data path: site.data.${dataPath}`);
121
- logger.log(` Template: ${templatePath}`);
122
-
123
- // Track the full output path
124
- const fullPath = path.resolve(output, path.relative(file.base, file.path));
125
- compiled[fullPath] = true;
126
-
127
- // Continue
128
- callback(null, file);
88
+ .pipe(new Transform({
89
+ objectMode: true,
90
+ transform(file, _, callback) {
91
+ // Skip if it's a directory
92
+ if (file.isDirectory()) {
93
+ return callback(null, file);
94
+ }
95
+
96
+ // Get relative path from src/_includes
97
+ const relativePath = path.relative(file.base, file.path);
98
+ const relativeDir = path.dirname(relativePath);
99
+ const basename = path.basename(file.path, '.json');
100
+
101
+ // Convert path for Jekyll data reference
102
+ // _includes/frontend/sections/nav.json -> _includes.frontend.sections.nav
103
+ const dataPath = '_includes.' + relativePath
104
+ .replace(/\\/g, '/')
105
+ .replace('.json', '')
106
+ .split('/')
107
+ .join('.');
108
+
109
+ // Determine the template path
110
+ // Look for corresponding template in themes/{theme}/{target}/...
111
+ const templatePath = `themes/${config.theme.id}/${relativeDir}/${basename}.html`;
112
+
113
+ // Create the HTML content
114
+ const htmlContent = template(INCLUDE_TEMPLATE, {
115
+ dataPath: dataPath,
116
+ templatePath: templatePath
117
+ });
118
+
119
+ // Update file contents and extension
120
+ file.contents = Buffer.from(htmlContent);
121
+ file.path = file.path.replace('.json', '.html');
122
+
123
+ // Log transformation
124
+ logger.log(`Converting: ${relativePath} -> ${path.basename(file.path)}`);
125
+ logger.log(` Data path: site.data.${dataPath}`);
126
+ logger.log(` Template: ${templatePath}`);
127
+
128
+ // Track the full output path
129
+ const fullPath = path.resolve(output, path.relative(file.base, file.path));
130
+ compiled[fullPath] = true;
131
+
132
+ // Continue
133
+ callback(null, file);
134
+ },
129
135
  }))
130
136
  .pipe(dest(output));
131
137
 
@@ -4,7 +4,7 @@ const logger = Manager.logger('minifyHtml');
4
4
  const { src, dest, series } = require('gulp');
5
5
  const { minify: minifyRust } = require('@minify-html/node');
6
6
  const { minify: minifyJs } = require('terser');
7
- const through2 = require('through2');
7
+ const { Transform } = require('node:stream');
8
8
 
9
9
  // Load package
10
10
  const package = Manager.getPackage('main');
@@ -85,61 +85,65 @@ function minifyHtmlTask(complete) {
85
85
 
86
86
  // Process HTML files
87
87
  return src(input)
88
- .pipe(through2.obj(function(file, _enc, callback) {
89
- if (file.isBuffer()) {
90
- fileQueue.push({ file });
91
- callback();
92
- } else {
93
- callback(null, file);
94
- }
95
- }, async function(callback) {
96
- // This function is called when all files have been queued
97
- if (fileQueue.length === 0) {
98
- logger.log('No HTML files to minify');
99
- return callback();
100
- }
88
+ .pipe(new Transform({
89
+ objectMode: true,
90
+ transform(file, _enc, callback) {
91
+ if (file.isBuffer()) {
92
+ fileQueue.push({ file });
93
+ callback();
94
+ } else {
95
+ callback(null, file);
96
+ }
97
+ },
98
+ async flush(callback) {
99
+ // This function is called when all files have been queued
100
+ if (fileQueue.length === 0) {
101
+ logger.log('No HTML files to minify');
102
+ return callback();
103
+ }
101
104
 
102
- const totalFiles = fileQueue.length;
103
- logger.log(`Minifying ${totalFiles} HTML files...`);
104
-
105
- try {
106
- // Process files in batches
107
- for (let i = 0; i < fileQueue.length; i += CONCURRENCY_LIMIT) {
108
- const batch = fileQueue.slice(i, i + CONCURRENCY_LIMIT);
109
-
110
- // Process batch in parallel
111
- const processedFiles = await Promise.all(
112
- batch.map(async ({ file }) => {
113
- try {
114
- const htmlContent = file.contents.toString();
115
- const finalHtml = await minifyFileContent(htmlContent, options, file.path);
116
- file.contents = Buffer.from(finalHtml);
117
- processed.count++;
118
-
119
- // Log progress every 50 files or on last file
120
- if (processed.count % 50 === 0 || processed.count === totalFiles) {
121
- const percentage = ((processed.count / totalFiles) * 100).toFixed(1);
122
- logger.log(`Progress: ${processed.count}/${totalFiles} files (${percentage}%)`);
123
- Manager.logMemory(logger, `After ${processed.count} files`);
105
+ const totalFiles = fileQueue.length;
106
+ logger.log(`Minifying ${totalFiles} HTML files...`);
107
+
108
+ try {
109
+ // Process files in batches
110
+ for (let i = 0; i < fileQueue.length; i += CONCURRENCY_LIMIT) {
111
+ const batch = fileQueue.slice(i, i + CONCURRENCY_LIMIT);
112
+
113
+ // Process batch in parallel
114
+ const processedFiles = await Promise.all(
115
+ batch.map(async ({ file }) => {
116
+ try {
117
+ const htmlContent = file.contents.toString();
118
+ const finalHtml = await minifyFileContent(htmlContent, options, file.path);
119
+ file.contents = Buffer.from(finalHtml);
120
+ processed.count++;
121
+
122
+ // Log progress every 50 files or on last file
123
+ if (processed.count % 50 === 0 || processed.count === totalFiles) {
124
+ const percentage = ((processed.count / totalFiles) * 100).toFixed(1);
125
+ logger.log(`Progress: ${processed.count}/${totalFiles} files (${percentage}%)`);
126
+ Manager.logMemory(logger, `After ${processed.count} files`);
127
+ }
128
+
129
+ return file;
130
+ } catch (err) {
131
+ logger.error(`Error minifying ${file.path}: ${err.message}`);
132
+ return file;
124
133
  }
134
+ })
135
+ );
125
136
 
126
- return file;
127
- } catch (err) {
128
- logger.error(`Error minifying ${file.path}: ${err.message}`);
129
- return file;
130
- }
131
- })
132
- );
137
+ // Push processed files to the stream
138
+ processedFiles.forEach(file => this.push(file));
139
+ }
133
140
 
134
- // Push processed files to the stream
135
- processedFiles.forEach(file => this.push(file));
141
+ callback();
142
+ } catch (err) {
143
+ logger.error(`Batch processing error: ${err.message}`);
144
+ callback(err);
136
145
  }
137
-
138
- callback();
139
- } catch (err) {
140
- logger.error(`Batch processing error: ${err.message}`);
141
- callback(err);
142
- }
146
+ },
143
147
  }))
144
148
  .pipe(dest(output))
145
149
  .on('finish', () => {
@@ -13,7 +13,7 @@ const { template } = require('node-powertools');
13
13
  const yaml = require('js-yaml');
14
14
  const postcss = require('gulp-postcss');
15
15
  const purgeCss = require('@fullhuman/postcss-purgecss');
16
- const through2 = require('through2');
16
+ const { Transform } = require('node:stream');
17
17
 
18
18
  // Load package
19
19
  const package = Manager.getPackage('main');
@@ -324,19 +324,20 @@ function sass(complete) {
324
324
  let purgeCssLogged = false;
325
325
  stream = stream
326
326
  .pipe(postcss([purgeCssPlugin]))
327
- .pipe(through2.obj(
328
- function (file, enc, cb) {
327
+ .pipe(new Transform({
328
+ objectMode: true,
329
+ transform(file, enc, cb) {
329
330
  cb(null, file);
330
331
  },
331
- function (cb) {
332
+ flush(cb) {
332
333
  if (!purgeCssLogged) {
333
334
  purgeCssLogged = true;
334
335
  const purgeCssTime = ((performance.now() - purgeCssStartTime) / 1000).toFixed(2);
335
336
  logger.log(`PurgeCSS completed in ${purgeCssTime}s`);
336
337
  }
337
338
  cb();
338
- }
339
- ));
339
+ },
340
+ }));
340
341
  }
341
342
 
342
343
  // Process
@@ -1,49 +1,49 @@
1
1
  // Libraries
2
- const through2 = require('through2');
2
+ const { Transform } = require('node:stream');
3
3
  const { template } = require('node-powertools');
4
4
  const path = require('path');
5
5
 
6
6
  /**
7
- * Creates a through2 transform stream that processes template variables in files
7
+ * Creates a transform stream that processes template variables in files
8
8
  **/
9
9
  function createTemplateTransform(data) {
10
10
  const extensions = ['html', 'md', 'liquid', 'json']
11
11
 
12
- return through2.obj(function(file, encoding, callback) {
13
- // Skip directories
14
- if (file.isDirectory()) {
15
- return callback(null, file);
16
- }
17
-
18
- // Check if file extension matches
19
- const ext = path.extname(file.path).toLowerCase().slice(1);
20
- if (!extensions.includes(ext)) {
21
- return callback(null, file);
22
- }
23
-
24
- // Log
25
- // console.log(`Processing file: ${file.path}`);
26
-
27
- // Process the file contents
28
- try {
29
- const contents = file.contents.toString();
30
-
31
- // Process templates
32
- const templated = template(contents, data, {
33
- brackets: ['[', ']'],
34
- });
35
-
36
- // Update file contents if changed
37
- if (contents !== templated) {
38
- file.contents = Buffer.from(templated);
39
- const relativePath = file.relative || file.path;
12
+ return new Transform({
13
+ objectMode: true,
14
+ transform(file, encoding, callback) {
15
+ // Skip directories
16
+ if (file.isDirectory()) {
17
+ return callback(null, file);
40
18
  }
41
- } catch (error) {
42
- console.error(`Error processing templates in ${file.path}:`, error);
43
- }
44
19
 
45
- // Pass the file through
46
- callback(null, file);
20
+ // Check if file extension matches
21
+ const ext = path.extname(file.path).toLowerCase().slice(1);
22
+ if (!extensions.includes(ext)) {
23
+ return callback(null, file);
24
+ }
25
+
26
+ // Process the file contents
27
+ try {
28
+ const contents = file.contents.toString();
29
+
30
+ // Process templates
31
+ const templated = template(contents, data, {
32
+ brackets: ['[', ']'],
33
+ });
34
+
35
+ // Update file contents if changed
36
+ if (contents !== templated) {
37
+ file.contents = Buffer.from(templated);
38
+ const relativePath = file.relative || file.path;
39
+ }
40
+ } catch (error) {
41
+ console.error(`Error processing templates in ${file.path}:`, error);
42
+ }
43
+
44
+ // Pass the file through
45
+ callback(null, file);
46
+ },
47
47
  });
48
48
  }
49
49
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ultimate-jekyll-manager",
3
- "version": "1.1.9",
3
+ "version": "1.1.10",
4
4
  "description": "Ultimate Jekyll dependency manager",
5
5
  "main": "dist/index.js",
6
6
  "exports": {
@@ -66,7 +66,7 @@
66
66
  },
67
67
  "dependencies": {
68
68
  "@babel/core": "^7.29.0",
69
- "@babel/preset-env": "^7.29.2",
69
+ "@babel/preset-env": "^7.29.5",
70
70
  "@fullhuman/postcss-purgecss": "^8.0.0",
71
71
  "@minify-html/node": "^0.18.1",
72
72
  "@octokit/rest": "^22.0.1",
@@ -79,35 +79,34 @@
79
79
  "chart.js": "^4.5.1",
80
80
  "cheerio": "^1.2.0",
81
81
  "chrome-launcher": "^1.2.1",
82
- "dompurify": "^3.3.3",
83
- "dotenv": "^17.4.1",
84
- "fast-xml-parser": "^5.5.11",
82
+ "dompurify": "^3.4.2",
83
+ "dotenv": "^17.4.2",
84
+ "fast-xml-parser": "^5.7.3",
85
85
  "fs-jetpack": "^5.1.0",
86
86
  "glob": "^13.0.6",
87
87
  "gulp-clean-css": "^4.3.0",
88
- "gulp-filter": "^9.0.1",
88
+ "gulp-filter": "^10.0.0",
89
89
  "gulp-postcss": "^10.0.0",
90
90
  "gulp-rename": "^2.1.0",
91
91
  "gulp-responsive-modern": "^1.0.0",
92
92
  "gulp-sass": "^6.0.1",
93
93
  "html-minifier-terser": "^7.2.0",
94
- "html-validate": "^10.11.3",
94
+ "html-validate": "^10.16.0",
95
95
  "itwcw-package-analytics": "^1.0.8",
96
96
  "js-yaml": "^4.1.1",
97
97
  "json5": "^2.2.3",
98
- "libsodium-wrappers": "^0.8.3",
98
+ "libsodium-wrappers": "^0.8.4",
99
99
  "lodash": "^4.18.1",
100
100
  "markdown-it": "^14.1.1",
101
101
  "minimatch": "^10.2.5",
102
102
  "node-powertools": "^3.0.0",
103
103
  "npm-api": "^1.0.1",
104
- "postcss": "^8.5.9",
105
- "prettier": "^3.8.2",
104
+ "postcss": "^8.5.14",
105
+ "prettier": "^3.8.3",
106
106
  "sass": "^1.99.0",
107
107
  "spellchecker": "^3.7.1",
108
- "through2": "^4.0.2",
109
- "web-manager": "^4.1.39",
110
- "webpack": "^5.106.1",
108
+ "web-manager": "^4.1.41",
109
+ "webpack": "^5.106.2",
111
110
  "wonderful-fetch": "^2.0.5",
112
111
  "wonderful-version": "^1.3.2",
113
112
  "yargs": "^18.0.0"