mirror of
https://github.com/fooflington/selfdefined.git
synced 2025-04-22 09:09:09 +00:00
177 lines
4.8 KiB
JavaScript
177 lines
4.8 KiB
JavaScript
const fs = require("fs-extra");
|
||
|
||
const TemplatePath = require("./TemplatePath");
|
||
const config = require("./Config");
|
||
const debug = require("debug")("EleventyServe");
|
||
|
||
class EleventyServe {
|
||
constructor() {}
|
||
|
||
get config() {
|
||
return this.configOverride || config.getConfig();
|
||
}
|
||
set config(config) {
|
||
this.configOverride = config;
|
||
}
|
||
|
||
setOutputDir(outputDir) {
|
||
this.outputDir = outputDir;
|
||
}
|
||
|
||
getPathPrefix() {
|
||
return this.config.pathPrefix || "/";
|
||
}
|
||
|
||
getRedirectDir(dirName) {
|
||
return TemplatePath.join(this.outputDir, dirName);
|
||
}
|
||
getRedirectDirOverride() {
|
||
// has a pathPrefix, add a /index.html template to redirect to /pathPrefix/
|
||
if (this.getPathPrefix() !== "/") {
|
||
return "_eleventy_redirect";
|
||
}
|
||
}
|
||
|
||
getRedirectFilename(dirName) {
|
||
return TemplatePath.join(this.getRedirectDir(dirName), "index.html");
|
||
}
|
||
|
||
getOptions(port) {
|
||
let pathPrefix = this.getPathPrefix();
|
||
|
||
// TODO customize this in Configuration API?
|
||
let serverConfig = {
|
||
baseDir: this.outputDir
|
||
};
|
||
|
||
let redirectDirName = this.getRedirectDirOverride();
|
||
// has a pathPrefix, add a /index.html template to redirect to /pathPrefix/
|
||
if (redirectDirName) {
|
||
serverConfig.baseDir = this.getRedirectDir(redirectDirName);
|
||
serverConfig.routes = {};
|
||
serverConfig.routes[pathPrefix] = this.outputDir;
|
||
|
||
// if has a savedPathPrefix, use the /savedPathPrefix/index.html template to redirect to /pathPrefix/
|
||
if (this.savedPathPrefix) {
|
||
serverConfig.routes[this.savedPathPrefix] = TemplatePath.join(
|
||
this.outputDir,
|
||
this.savedPathPrefix
|
||
);
|
||
}
|
||
}
|
||
|
||
return Object.assign(
|
||
{
|
||
server: serverConfig,
|
||
port: port || 8080,
|
||
ignore: ["node_modules"],
|
||
watch: false,
|
||
open: false,
|
||
notify: false,
|
||
index: "index.html"
|
||
},
|
||
this.config.browserSyncConfig
|
||
);
|
||
}
|
||
|
||
cleanupRedirect(dirName) {
|
||
if (dirName && dirName !== "/") {
|
||
let savedPathFilename = this.getRedirectFilename(dirName);
|
||
|
||
setTimeout(function() {
|
||
if (!fs.existsSync(savedPathFilename)) {
|
||
debug(`Cleanup redirect: Could not find ${savedPathFilename}`);
|
||
return;
|
||
}
|
||
|
||
let savedPathContent = fs.readFileSync(savedPathFilename, "utf-8");
|
||
if (
|
||
savedPathContent.indexOf("Browsersync pathPrefix Redirect") === -1
|
||
) {
|
||
debug(
|
||
`Cleanup redirect: Found ${savedPathFilename} but it wasn’t an eleventy redirect.`
|
||
);
|
||
return;
|
||
}
|
||
|
||
fs.unlink(savedPathFilename, err => {
|
||
if (!err) {
|
||
debug(`Cleanup redirect: Deleted ${savedPathFilename}`);
|
||
}
|
||
});
|
||
}, 2000);
|
||
}
|
||
}
|
||
|
||
serveRedirect(dirName) {
|
||
fs.outputFile(
|
||
this.getRedirectFilename(dirName),
|
||
`<!doctype html>
|
||
<meta http-equiv="refresh" content="0; url=${this.config.pathPrefix}">
|
||
<title>Browsersync pathPrefix Redirect</title>
|
||
<a href="${this.config.pathPrefix}">Go to ${this.config.pathPrefix}</a>`
|
||
);
|
||
}
|
||
|
||
serve(port) {
|
||
// only load on serve—this is pretty expensive
|
||
const browserSync = require("browser-sync");
|
||
this.server = browserSync.create();
|
||
|
||
let pathPrefix = this.getPathPrefix();
|
||
|
||
if (this.savedPathPrefix && pathPrefix !== this.savedPathPrefix) {
|
||
let redirectFilename = this.getRedirectFilename(this.savedPathPrefix);
|
||
if (!fs.existsSync(redirectFilename)) {
|
||
debug(
|
||
`Redirecting BrowserSync from ${
|
||
this.savedPathPrefix
|
||
} to ${pathPrefix}`
|
||
);
|
||
this.serveRedirect(this.savedPathPrefix);
|
||
} else {
|
||
debug(
|
||
`Config updated with a new pathPrefix. Tried to set up a transparent redirect but found a template already existing at ${redirectFilename}. You’ll have to navigate manually.`
|
||
);
|
||
}
|
||
}
|
||
|
||
let redirectDirName = this.getRedirectDirOverride();
|
||
// has a pathPrefix, add a /index.html template to redirect to /pathPrefix/
|
||
if (redirectDirName) {
|
||
this.serveRedirect(redirectDirName);
|
||
}
|
||
|
||
this.cleanupRedirect(this.savedPathPrefix);
|
||
this.server.init(this.getOptions(port));
|
||
|
||
// this needs to happen after `.getOptions`
|
||
this.savedPathPrefix = pathPrefix;
|
||
}
|
||
|
||
close() {
|
||
if (this.server) {
|
||
this.server.exit();
|
||
}
|
||
}
|
||
|
||
reload(path, isInclude) {
|
||
if (this.server) {
|
||
if (this.getPathPrefix() !== this.savedPathPrefix) {
|
||
this.server.exit();
|
||
this.serve();
|
||
} else {
|
||
// Is a CSS input file and is not in the includes folder
|
||
// TODO check output path file extension of this template (not input path)
|
||
if (path && path.split(".").pop() === "css" && !isInclude) {
|
||
this.server.reload("*.css");
|
||
} else {
|
||
this.server.reload();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
module.exports = EleventyServe;
|