2025-05-12 05:38:44 +09:00

194 lines
6.8 KiB
JavaScript

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const tiny_lr_1 = __importDefault(require("tiny-lr"));
const open_1 = __importDefault(require("open"));
const immutable_1 = __importDefault(require("immutable"));
const parse_1 = __importDefault(require("../parse"));
const output_1 = __importDefault(require("../output"));
const modifiers_1 = __importDefault(require("../modifiers"));
const promise_1 = __importDefault(require("../utils/promise"));
const options_1 = __importDefault(require("./options"));
const getBook_1 = __importDefault(require("./getBook"));
const getOutputFolder_1 = __importDefault(require("./getOutputFolder"));
const server_1 = __importDefault(require("./server"));
const watch_1 = __importDefault(require("./watch"));
const page_cache_1 = require("../output/page-cache");
const fs_1 = __importDefault(require("fs"));
let server, lrServer, lrPath;
function waitForCtrlC() {
const d = promise_1.default.defer();
process.on("SIGINT", () => {
d.resolve();
});
return d.promise;
}
function startServer(args, kwargs) {
const outputFolder = (0, getOutputFolder_1.default)(args);
const port = kwargs.port;
const browser = kwargs["browser"];
const book = (0, getBook_1.default)(args, kwargs);
const hasWatch = kwargs["watch"];
const hasOpen = kwargs["open"];
const hasLiveReloading = kwargs["live"];
const reload = kwargs["reload"];
const Generator = output_1.default.getGenerator(kwargs.format);
const logger = book.getLogger();
logger.info.ok("Starting server ...");
let lastOutput = null;
return promise_1.default.all([
server.start(outputFolder, port),
generateBook({
book,
outputFolder,
hasLiveReloading,
Generator,
reload
}).then((output) => {
lastOutput = output;
return output;
})
])
.then(() => {
console.log(`Serving book on http://localhost:${port}`);
if (hasOpen) {
(0, open_1.default)(`http://localhost:${port}`, { app: browser });
}
})
.then(() => {
if (!hasWatch) {
return waitForCtrlC();
}
// update book immutably. does not use book again
return (0, watch_1.default)(book.getRoot(), (error, filepath) => {
if (error) {
console.error(error);
return;
}
// If the file does not exist in file system, show a warning and skip
// Probably, the file has been deleted
if (!fs_1.default.existsSync(filepath)) {
logger.warn.ok(`${filepath} does not exist in file system.`);
return;
}
// set livereload path
lrPath = filepath;
// TODO: use parse extension
// Incremental update for pages
if (lastOutput && filepath.endsWith(".md")) {
logger.warn.ok("Rebuild " + filepath);
const changedOutput = lastOutput.reloadPage(lastOutput.book.getContentRoot(), filepath).merge({
incrementalChangeFileSet: immutable_1.default.Set([filepath])
});
return incrementalBuild({
output: changedOutput,
Generator
}).then(() => {
if (lrPath && hasLiveReloading) {
// trigger livereload
lrServer.changed({
body: {
files: [lrPath]
}
});
}
});
}
// Asciidoc files are not supported for incremental build
logger.info.ok("Rebuild " + filepath);
return generateBook({
book,
outputFolder,
hasLiveReloading,
Generator,
reload
}).then((output) => {
lastOutput = output;
});
});
});
}
function generateBook({ book, outputFolder, hasLiveReloading, Generator, reload }) {
// Stop server if running
if (reload) {
book.getLogger().info.ok(`Clear cache`);
(0, page_cache_1.clearCache)();
}
return parse_1.default.parseBook(book).then((resultBook) => {
if (hasLiveReloading) {
// Enable livereload plugin
let config = resultBook.getConfig();
// @ts-expect-error ts-migrate(2554) FIXME: Expected 3 arguments, but got 2.
config = modifiers_1.default.Config.addPlugin(config, "livereload");
resultBook = resultBook.set("config", config);
}
return output_1.default.generate(Generator, resultBook, {
root: outputFolder
});
});
}
function incrementalBuild({ output, Generator }) {
return output_1.default.incrementalBuild(Generator, output);
}
exports.default = {
name: "serve [book] [output]",
description: "serve the book as a website for testing",
options: [
{
name: "port",
description: "Port for server to listen on",
defaults: 4000
},
{
name: "lrport",
description: "Port for livereload server to listen on",
defaults: 35729
},
{
name: "watch",
description: "Enable file watcher and live reloading",
defaults: true
},
{
name: "live",
description: "Enable live reloading",
defaults: true
},
{
name: "open",
description: "Enable opening book in browser",
defaults: false
},
{
name: "browser",
description: "Specify browser for opening book",
defaults: ""
},
options_1.default.log,
options_1.default.format,
options_1.default.reload
],
exec: function (args, kwargs) {
server = new server_1.default();
const hasWatch = kwargs["watch"];
const hasLiveReloading = kwargs["live"];
return (0, promise_1.default)()
.then(() => {
if (!hasWatch || !hasLiveReloading) {
return;
}
lrServer = (0, tiny_lr_1.default)({});
return promise_1.default.nfcall(lrServer.listen.bind(lrServer), kwargs.lrport).then(() => {
console.log("Live reload server started on port:", kwargs.lrport);
console.log("Press CTRL+C to quit ...");
console.log("");
});
})
.then(() => {
return startServer(args, kwargs);
});
}
};