ultimate-jekyll-manager 0.0.1 → 0.0.3

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.
@@ -0,0 +1,82 @@
1
+ // Libraries
2
+ const path = require('path');
3
+ const jetpack = require('fs-jetpack');
4
+ const { series, parallel, watch } = require('gulp');
5
+ const Manager = new (require('../index.js'));
6
+ const logger = Manager.logger('main');
7
+
8
+ // Load tasks
9
+ const tasks = jetpack.list(path.join(__dirname, 'tasks'));
10
+
11
+ // Log
12
+ // logger.log('---tasks 1', path.join(__dirname, 'tasks'));
13
+ // logger.log('---tasks 2', tasks);
14
+
15
+ // Init global
16
+ global.tasks = {};
17
+ global.browserSync = null;
18
+
19
+ // Load tasks
20
+ tasks.forEach((file) => {
21
+ const name = file.replace('.js', '');
22
+
23
+ // Log
24
+ // logger.log('Loading task:', name);
25
+
26
+ // Export task
27
+ exports[name] = require(path.join(__dirname, 'tasks', file));
28
+ });
29
+
30
+ // Log tasks
31
+ // logger.log('exports:', exports);
32
+
33
+ // Set global variable to access tasks in other files
34
+ global.tasks = exports;
35
+
36
+ // Define build process
37
+ exports.build = series(
38
+ parallel(exports.sass, exports.webpack, exports.imagemin),
39
+ exports.jekyll,
40
+ );
41
+
42
+ // Watch for changes
43
+ exports.watcher = function watcher() {
44
+ watch(
45
+ [
46
+ // Files to include
47
+ 'site/**/*',
48
+ // '**/*.html',
49
+ // '**/*.md',
50
+ // '**/*.yml',
51
+ // '**/*.scss',
52
+ // '**/*.js',
53
+
54
+ // Files to exclude
55
+ '!_site/**',
56
+ '!site/.jekyll-cache/**',
57
+ '!site/.jekyll-metadata',
58
+ // '!site/compiled/**',
59
+ // '!./node_modules/**/*',
60
+ ],
61
+ { delay: 500 },
62
+ series(exports.jekyll, (complete) => {
63
+ // Log
64
+ logger.log('Reloading browser...');
65
+
66
+ // Reload
67
+ global.browserSync.notify('Rebuilt Jekyll');
68
+ global.browserSync.reload();
69
+
70
+ // Complete
71
+ return complete();
72
+ })
73
+ );
74
+ }
75
+
76
+ // Compose task scheduler
77
+ exports.default = series(
78
+ exports.build,
79
+ exports.serve,
80
+ exports.watcher,
81
+ );
82
+
@@ -0,0 +1,110 @@
1
+ // Libraries
2
+ const path = require('path');
3
+ const { src, dest, watch, series } = require('gulp');
4
+ const glob = require('glob').globSync;
5
+ const responsive = require('gulp-responsive-modern');
6
+ const Manager = new (require('../../index.js'));
7
+ const logger = Manager.logger('imagemin');
8
+
9
+ // Glob
10
+ const input = [
11
+ // Files to include
12
+ 'site/assets/images/**/*.{jpg,jpeg,png}',
13
+
14
+ // Files to exclude
15
+ // '!site/compiled/**',
16
+ ];
17
+ const output = 'site/compiled/images';
18
+
19
+ // IMAGES Processing Task
20
+ function imagemin(complete) {
21
+ // Log
22
+ logger.log('Starting image processing...');
23
+
24
+ // Use glob to get file count for msdtching files
25
+ const files = glob(input);
26
+
27
+ // If there's no files, complete
28
+ if (files.length === 0) {
29
+ // Log
30
+ logger.log('No images to process');
31
+
32
+ // Complete
33
+ return complete();
34
+ }
35
+
36
+ // Process images: resize and convert to webp
37
+ return src(input)
38
+ .pipe(
39
+ responsive({
40
+ '**/*.{jpg,jpeg,png}': [
41
+ // 1024 resized version in original format
42
+ {
43
+ width: 1024,
44
+ rename: { suffix: '-1024px' }
45
+ },
46
+ // 1024 resized webp version
47
+ {
48
+ width: 1024,
49
+ format: 'webp',
50
+ rename: { suffix: '-1024px' }
51
+ },
52
+ // Mobile resized version (e.g., 640px wide) in original format
53
+ {
54
+ width: 425,
55
+ rename: { suffix: '-425px' }
56
+ },
57
+ // Mobile resized webp version
58
+ {
59
+ width: 425,
60
+ format: 'webp',
61
+ rename: { suffix: '-425px' }
62
+ },
63
+ // Original size webp version
64
+ {
65
+ format: 'webp',
66
+ rename: { suffix: '' }
67
+ },
68
+ // Original size in original format
69
+ {
70
+ rename: { suffix: '' }
71
+ }
72
+ ]
73
+ }, {
74
+ quality: 80,
75
+ progressive: true,
76
+ withMetadata: false,
77
+ withoutEnlargement: false,
78
+ skipOnEnlargement: false,
79
+ })
80
+ )
81
+ .pipe(dest(output))
82
+ .on('end', () => {
83
+ // Log
84
+ logger.log('Finished image processing!');
85
+
86
+ // Complete
87
+ return complete();
88
+ });
89
+ }
90
+
91
+ // Watcher Task
92
+ function imageminWatcher(complete) {
93
+ // Quit if in build mode
94
+ if (process.env.UJ_BUILD_MODE === 'true') {
95
+ logger.log('Skipping image watcher in build mode');
96
+ return complete();
97
+ }
98
+
99
+ // Log
100
+ logger.log('Watching for image changes...');
101
+
102
+ // Watch for changes
103
+ watch(input, { delay: 250 }, imagemin);
104
+
105
+ // Complete
106
+ return complete();
107
+ }
108
+
109
+ // Default Task
110
+ module.exports = series(imagemin, imageminWatcher);
@@ -0,0 +1,82 @@
1
+ // Libraries
2
+ const path = require('path');
3
+ const { execute } = require('node-powertools');
4
+ const jetpack = require('fs-jetpack');
5
+ const Manager = new (require('../../index.js'));
6
+ const logger = Manager.logger('jekyll');
7
+
8
+ // Set index
9
+ let index = -1;
10
+
11
+ // Hooks
12
+ const hooks = {
13
+ prebuild: loadHook('prebuild'),
14
+ postbuild: loadHook('postbuild'),
15
+ }
16
+
17
+ // Task
18
+ module.exports = async function jekyll(complete) {
19
+ // Log
20
+ logger.log('Starting Jekyll build...');
21
+
22
+ // Increment index
23
+ index++;
24
+
25
+ // Clean if on index 0
26
+ if (index === 0) {
27
+ await execute('npx uj clean', {log: true});
28
+ }
29
+
30
+ // Wait 5 seconds
31
+ // await new Promise((resolve) => setTimeout(resolve, 5000));
32
+
33
+ // Run prebuild hook
34
+ await hooks.prebuild(index);
35
+
36
+ // Build Jekyll
37
+ const command = [
38
+ 'bundle exec jekyll build',
39
+ '--source site',
40
+ '--config ./node_modules/ultimate-jekyll-manager/dist/config/_config_main.yml,site/_config.yml,.temp/_config_browsersync.yml',
41
+ '--incremental',
42
+ ]
43
+
44
+ // Log command
45
+ logger.log(`Running command: ${logger.format.gray(command.join(' '))}`);
46
+
47
+ // Build Jekyll
48
+ await execute(command.join(' '), {log: true});
49
+
50
+ // Run postbuild hook
51
+ await hooks.postbuild(index);
52
+
53
+ // Log
54
+ logger.log('Finished Jekyll build!');
55
+
56
+ // Complete
57
+ return complete();
58
+ };
59
+
60
+
61
+ function loadHook(file) {
62
+ // Full path
63
+ const fullPath = path.join(process.cwd(), 'hooks', `${file}.js`);
64
+
65
+ // Log
66
+ // logger.log(`Loading hook: ${fullPath}`);
67
+
68
+ try {
69
+ // Check if it exists
70
+ if (!jetpack.exists(fullPath)) {
71
+ throw new Error('Hook not found');
72
+ }
73
+
74
+ return require(fullPath);
75
+ } catch (e) {
76
+ // Log
77
+ logger.error(`Error executing hook: ${fullPath}`, e);
78
+
79
+ // Return a noop function
80
+ return () => {};
81
+ }
82
+ }
@@ -0,0 +1,57 @@
1
+ // Libraries
2
+ const path = require('path');
3
+ const { src, dest, watch, series } = require('gulp');
4
+ const compiler = require('gulp-sass')(require('sass'));
5
+ const cleanCSS = require('gulp-clean-css');
6
+ const Manager = new (require('../../index.js'));
7
+ const logger = Manager.logger('sass');
8
+
9
+ // Glob
10
+ const input = [
11
+ // Files to include
12
+ 'site/assets/css/**/*.{css,scss,sass}',
13
+
14
+ // Files to exclude
15
+ // '!site/compiled/**',
16
+ ];
17
+ const output = 'site/compiled/css';
18
+
19
+ // SASS Compilation Task
20
+ function sass(complete) {
21
+ // Log
22
+ logger.log('Starting SASS compilation...');
23
+
24
+ // Compile
25
+ return src(input)
26
+ .pipe(compiler({ outputStyle: 'compressed' }).on('error', compiler.logError))
27
+ .pipe(cleanCSS())
28
+ .pipe(dest(output))
29
+ .on('end', () => {
30
+ // Log
31
+ logger.log('Finished SASS compilation');
32
+
33
+ // Complete
34
+ return complete();
35
+ });
36
+ }
37
+
38
+ // Watcher Task
39
+ function sassWatcher(complete) {
40
+ // Quit if in build mode
41
+ if (process.env.UJ_BUILD_MODE === 'true') {
42
+ logger.log('Skipping SASS watcher in build mode');
43
+ return complete();
44
+ }
45
+
46
+ // Log
47
+ logger.log('Watching for SASS changes...');
48
+
49
+ // Watch for changes
50
+ watch(input, { delay: 250 }, sass);
51
+
52
+ // Complete
53
+ return complete();
54
+ }
55
+
56
+ // Default Task
57
+ module.exports = series(sass, sassWatcher);
@@ -0,0 +1,179 @@
1
+ // Libraries
2
+ const path = require('path');
3
+ const { watch, series } = require('gulp');
4
+ const browserSync = require('browser-sync').create();
5
+ const jetpack = require('fs-jetpack');
6
+ const Manager = new (require('../../index.js'));
7
+ const logger = Manager.logger('serve');
8
+
9
+ // Local URL
10
+ let localUrl;
11
+ let externalUrl;
12
+
13
+ // BrowserSync settings
14
+ const settings = {
15
+ port: 4000,
16
+ browser: 'default',
17
+ cors: true,
18
+ open: 'external',
19
+ ghostMode: false,
20
+ server: {
21
+ baseDir: '_site',
22
+ middleware: async function (req, res, next) {
23
+ const url = new URL(`${localUrl}${req.url}`);
24
+ const pathname = url.pathname;
25
+
26
+ // Set the query object
27
+ req.query = {};
28
+ req.body = {};
29
+
30
+ // If the file has no ext, log it
31
+ if (!path.extname(pathname)) {
32
+ logger.log(`Serving ${pathname}`);
33
+ }
34
+
35
+ // Process the post request
36
+ if (pathname.match(/\/_process/)) {
37
+ const qsUrl = url.searchParams.get('url');
38
+ let lib;
39
+
40
+ // Set query
41
+ url.searchParams.forEach((value, key) => {
42
+ req.query[key] = value;
43
+ })
44
+
45
+ // Set body
46
+ if (req.method === 'POST') {
47
+ req.body = await receiveRequestBody(req);
48
+ }
49
+
50
+ // Try to load the library
51
+ try {
52
+ // Clear the cache
53
+ delete require.cache[require.resolve(`../${qsUrl}`)];
54
+
55
+ // Load the library
56
+ lib = require(`../${qsUrl}`);
57
+ } catch (e) {
58
+ // Log the error
59
+ logger.error(`Error processing ${qsUrl}`);
60
+
61
+ // Set the status code
62
+ res.statusCode = 500;
63
+
64
+ // Return an error
65
+ return res.write(`Cannot find ${qsUrl}`);
66
+ }
67
+
68
+ // Log
69
+ logger.log(`Processing ${qsUrl}`);
70
+
71
+ // Process the library
72
+ return await lib({
73
+ req: req,
74
+ res: res,
75
+ })
76
+ .then((r) => {
77
+ // Set the status code
78
+ res.statusCode = 200;
79
+
80
+ // Write the response (if it's JSON, set the content type)
81
+ try {
82
+ r = JSON.stringify(r);
83
+ res.setHeader('Content-Type', 'application/json');
84
+ } catch (e) {
85
+ }
86
+
87
+ // End the response
88
+ res.write(r);
89
+ res.end();
90
+ })
91
+ .catch((e) => {
92
+ // Set the status code
93
+ res.statusCode = 500;
94
+
95
+ // Write the error
96
+ res.write(`Error processing ${qsUrl}: ${e}`);
97
+ res.end();
98
+ });
99
+ }
100
+
101
+ // Check if the URL is missing a trailing slash and does not have an extension
102
+ if (!pathname.endsWith('/') && !path.extname(pathname)) {
103
+ // Get the new URL
104
+ const newURL = `${pathname}.html`;
105
+
106
+ // Log
107
+ // logger.log(`Rewriting ${pathname} to ${newURL}`);
108
+
109
+ // Rewrite it to serve the .html extension
110
+ req.url = newURL;
111
+ }
112
+
113
+ // Special case: Rewrite /blog/ to blog.html since Jekyll fucks it up locally
114
+ if (pathname === '/blog/') {
115
+ req.url = '/blog.html';
116
+ }
117
+
118
+ // Continue
119
+ return next();
120
+ },
121
+ },
122
+ }
123
+
124
+ // Task
125
+ module.exports = function serve(complete) {
126
+ // Log
127
+ logger.log('Starting server setup...');
128
+
129
+ // Initialize browserSync
130
+ browserSync.init(settings, async (e, instance) => {
131
+ if (e) {
132
+ return logger.error(e);
133
+ }
134
+
135
+ // Get URLs
136
+ localUrl = instance.options.get('urls').get('local');
137
+ externalUrl = instance.options.get('urls').get('external');
138
+
139
+ // Write the config file
140
+ jetpack.write('.temp/_config_browsersync.yml', `url: ${externalUrl}`);
141
+
142
+ // Set global variable to access browserSync in other files
143
+ global.browserSync = browserSync;
144
+
145
+ // Log
146
+ logger.log('Finished server setup!');
147
+
148
+ // Complete
149
+ return complete();
150
+ });
151
+ };
152
+
153
+ function receiveRequestBody(req) {
154
+ return new Promise((resolve, reject) => {
155
+ let body = [];
156
+
157
+ // Listen for data
158
+ req.on('data', (chunk) => {
159
+ body.push(chunk.toString());
160
+ });
161
+
162
+ // Listen for errors
163
+ req.on('error', (err) => {
164
+ return reject(err);
165
+ });
166
+
167
+ // Listen for the end of the request
168
+ req.on('end', () => {
169
+ body = body.join('');
170
+
171
+ // Attempt to parse the body as JSON
172
+ try {
173
+ return resolve(JSON.parse(body));
174
+ } catch (e) {
175
+ return resolve(body);
176
+ }
177
+ });
178
+ });
179
+ }
@@ -0,0 +1,12 @@
1
+ // Libraries
2
+ const Manager = new (require('../../index.js'));
3
+ const logger = Manager.logger('test');
4
+
5
+ // Task
6
+ module.exports = function test(complete) {
7
+ // Log
8
+ console.log('Starting test...');
9
+
10
+ // Complete
11
+ return complete();
12
+ }
@@ -0,0 +1,77 @@
1
+ // Libraries
2
+ const path = require('path');
3
+ const wp = require('webpack');
4
+ const Manager = new (require('../../index.js'));
5
+ const logger = Manager.logger('webpack');
6
+
7
+ // console.log('======', path.resolve(__dirname, 'node_modules', 'babel-loader', 'lib', 'index.js'));
8
+
9
+ // Settings
10
+ const MINIFY = false;
11
+ const settings = {
12
+ mode: 'production',
13
+ entry: {
14
+ // default: './src/js/default.js', // Common scripts
15
+ default: './site/assets/js/test.js', // Common scripts
16
+ // pricing: './src/js/pricing.js', // Page-specific script
17
+ // about: './src/js/about.js'
18
+ },
19
+ output: {
20
+ filename: '[name].bundle.js',
21
+ // path: path.resolve(process.cwd(), 'site/assets/js'),
22
+ path: path.resolve(process.cwd(), 'site/compiled/js'),
23
+ },
24
+ resolveLoader: {
25
+ modules: [
26
+ path.resolve(process.cwd(), 'node_modules', 'ultimate-jekyll-manager', 'node_modules'), // Path to your helper module's node_modules
27
+ path.resolve(process.cwd(), 'node_modules'), // Default project node_modules
28
+ 'node_modules', // Fallback to global
29
+ ]
30
+ },
31
+ module: {
32
+ rules: [
33
+ {
34
+ test: /\.js$/,
35
+ exclude: /node_modules/,
36
+ use: {
37
+ loader: 'babel-loader',
38
+ options: {
39
+ // presets: ['@babel/preset-env'],
40
+ presets: [
41
+ require.resolve('@babel/preset-env', {
42
+ paths: [path.resolve(process.cwd(), 'node_modules', 'ultimate-jekyll-manager', 'node_modules')]
43
+ })
44
+ ],
45
+ compact: MINIFY,
46
+ }
47
+ }
48
+ }
49
+ ]
50
+ },
51
+ optimization: {
52
+ minimize: MINIFY,
53
+ },
54
+ watch: process.env.UJ_BUILD_MODE !== 'true',
55
+ }
56
+
57
+ // Task
58
+ module.exports = function webpack(complete) {
59
+ // Log
60
+ logger.log('Starting webpack compilation...');
61
+
62
+ // Compiler
63
+ const compiler = wp(settings, (e, stats) => {
64
+ // Log
65
+ logger.log('Finished webpack compilation!');
66
+
67
+ // Error
68
+ if (e) {
69
+ logger.error(e);
70
+ } else {
71
+ logger.log('Stats:\n', stats.toString({ colors: true }));
72
+ }
73
+
74
+ // Complete
75
+ return complete(e);
76
+ });
77
+ }
package/dist/index.js ADDED
@@ -0,0 +1,33 @@
1
+ // Class
2
+ function Manager() {
3
+ const self = this;
4
+
5
+ // Properties
6
+ self._logger = null;
7
+
8
+ // Return
9
+ return self;
10
+ }
11
+
12
+ // Initialize
13
+ Manager.prototype.initialize = function () {
14
+ console.log('initialize:');
15
+ };
16
+
17
+ // Initialize
18
+ Manager.prototype.logger = function (name) {
19
+ // Create logger
20
+ if (!this._logger) {
21
+ this._logger = new (require('./lib/logger'))(name);
22
+ }
23
+
24
+ return this._logger;
25
+ };
26
+
27
+ // Require
28
+ Manager.require = function (path) {
29
+ return require(path);
30
+ };
31
+
32
+ // Export
33
+ module.exports = Manager;
@@ -0,0 +1,56 @@
1
+ // Libraries
2
+ const chalk = require('chalk');
3
+
4
+ // Logger class
5
+ function Logger(name) {
6
+ const self = this;
7
+
8
+ // Properties
9
+ self.name = name;
10
+ }
11
+
12
+ // Loop through log, error, warn, and info and make methods that log to console with the name and time [xx:xx:xx] name: message
13
+ ['log', 'error', 'warn', 'info'].forEach((method) => {
14
+ Logger.prototype[method] = function () {
15
+ // Get time
16
+ const time = new Date().toLocaleTimeString('en-US', {
17
+ hour12: false,
18
+ hour: '2-digit',
19
+ minute: '2-digit',
20
+ second: '2-digit'
21
+ });
22
+
23
+ // Determine color based on method
24
+ let color;
25
+ switch (method) {
26
+ case 'warn':
27
+ color = chalk.yellow;
28
+ break;
29
+ case 'error':
30
+ color = chalk.red;
31
+ break;
32
+ default:
33
+ color = (text) => text; // No color
34
+ }
35
+
36
+ // Convert arguments to array and prepend time and name
37
+ const args = [`[${chalk.magenta(time)}] '${chalk.cyan(this.name)}':`, ...Array.from(arguments).map(arg => {
38
+ return typeof arg === 'string'
39
+ ? color(arg)
40
+ : (
41
+ arg instanceof Error
42
+ ? color(arg.stack)
43
+ : arg
44
+ );
45
+ })];
46
+
47
+ // Log
48
+ console[method].apply(console, args);
49
+ };
50
+ });
51
+
52
+ // Export chalk as color
53
+ Logger.prototype.format = chalk;
54
+
55
+ // Export
56
+ module.exports = Logger;