ultimate-jekyll-manager
Version:
Ultimate Jekyll dependency manager
179 lines (145 loc) • 4.23 kB
JavaScript
// Libraries
const Manager = new (require('../../build.js'));
const logger = Manager.logger('serve');
const path = require('path');
const browserSync = require('browser-sync').create();
const jetpack = require('fs-jetpack');
// Local URL
let localUrl;
let externalUrl;
// BrowserSync settings
const settings = {
port: 4000,
browser: 'default',
cors: true,
open: false,
ghostMode: false,
server: {
baseDir: '_site',
middleware: async function (req, res, next) {
const url = new URL(`${localUrl}${req.url}`);
const pathname = url.pathname;
// Set the query object
req.query = {};
req.body = {};
// If the file has no ext, log it
if (!path.extname(pathname)) {
logger.log(`Serving ${pathname}`);
}
// Process the post request
if (pathname.match(/\/_process/)) {
const qsUrl = url.searchParams.get('url');
let lib;
// Set query
url.searchParams.forEach((value, key) => {
req.query[key] = value;
})
// Set body
if (req.method === 'POST') {
req.body = await receiveRequestBody(req);
}
// Try to load the library
try {
// Clear the cache
delete require.cache[require.resolve(`../${qsUrl}`)];
// Load the library
lib = require(`../${qsUrl}`);
} catch (e) {
// Log the error
logger.error(`Error processing ${qsUrl}`);
// Set the status code
res.statusCode = 500;
// Return an error
return res.write(`Cannot find ${qsUrl}`);
}
// Log
logger.log(`Processing ${qsUrl}`);
// Process the library
return await lib({
req: req,
res: res,
})
.then((r) => {
// Set the status code
res.statusCode = 200;
// Write the response (if it's JSON, set the content type)
try {
r = JSON.stringify(r);
res.setHeader('Content-Type', 'application/json');
} catch (e) {
}
// End the response
res.write(r);
res.end();
})
.catch((e) => {
// Set the status code
res.statusCode = 500;
// Write the error
res.write(`Error processing ${qsUrl}: ${e}`);
res.end();
});
}
// Check if the URL is missing a trailing slash and does not have an extension
if (!pathname.endsWith('/') && !path.extname(pathname)) {
// Get the new URL
const newURL = `${pathname}.html`;
// Log
// logger.log(`Rewriting ${pathname} to ${newURL}`);
// Rewrite it to serve the .html extension
req.url = newURL;
}
// Special case: Rewrite /blog/ to blog.html since Jekyll fucks it up locally
if (pathname === '/blog/') {
req.url = '/blog.html';
}
// Continue
return next();
},
},
}
// Task
module.exports = function serve(complete) {
// Log
logger.log('Starting...');
// Initialize browserSync
browserSync.init(settings, async (e, instance) => {
if (e) {
return logger.error(e);
}
// Get URLs
localUrl = instance.options.get('urls').get('local');
externalUrl = instance.options.get('urls').get('external');
// Write the config file
jetpack.write('.temp/_config_browsersync.yml', `url: ${externalUrl}`);
// Set global variable to access browserSync in other files
global.browserSync = browserSync;
// Log
logger.log('Finished!');
// Complete
return complete();
});
};
function receiveRequestBody(req) {
return new Promise((resolve, reject) => {
let body = [];
// Listen for data
req.on('data', (chunk) => {
body.push(chunk.toString());
});
// Listen for errors
req.on('error', (err) => {
return reject(err);
});
// Listen for the end of the request
req.on('end', () => {
body = body.join('');
// Attempt to parse the body as JSON
try {
return resolve(JSON.parse(body));
} catch (e) {
return resolve(body);
}
});
});
}