@techdocs/cli
Version:
Utility CLI for managing TechDocs sites in Backstage.
96 lines (90 loc) • 3.96 kB
JavaScript
;
var httpProxy = require('http-proxy');
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
var httpProxy__default = /*#__PURE__*/_interopDefaultCompat(httpProxy);
const LIVE_RELOAD_ELEMENT = "live-reload";
const LIVE_RELOAD_ATTR_EPOCH = "live-reload-epoch";
const LIVE_RELOAD_ATTR_REQUEST_ID = "live-reload-request-id";
const CLI_LIVERELOAD_PATH = "/.livereload";
const MKDOCS_LIVERELOAD_PATH = "/livereload";
const CONTENT_TYPE_HTML = "text/html";
const HEADER_CONTENT_LENGTH = "content-length";
const BODY_START_RE = /<body\b[^>]*>/;
const MKDOCS_LIVERELOAD_CALL_RE = /livereload\(\s*(\d+)\s*,\s*(\d+)\s*\)\s*;?/;
function injectLivereloadParameters(html) {
const livereloadMatch = html.match(MKDOCS_LIVERELOAD_CALL_RE);
if (!livereloadMatch) {
return html;
}
const [, epoch, requestId] = livereloadMatch;
const liveReloadTag = `<${LIVE_RELOAD_ELEMENT} ${LIVE_RELOAD_ATTR_EPOCH}="${epoch}" ${LIVE_RELOAD_ATTR_REQUEST_ID}="${requestId}"></${LIVE_RELOAD_ELEMENT}>`;
const bodyStart = html.match(BODY_START_RE);
const bodyStartIndex = bodyStart?.index ?? 0;
const bodyStartLength = bodyStart?.[0]?.length ?? 0;
if (bodyStartIndex === 0 || bodyStartLength === 0) {
return html;
}
const bodyEndIndex = bodyStartIndex + bodyStartLength;
return html.slice(0, bodyEndIndex) + liveReloadTag + html.slice(bodyEndIndex);
}
function setCorsHeaders(response) {
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS");
}
function proxyHtmlWithLivereloadInjection(options) {
const { request, response, mkdocsTargetAddress, proxyEndpoint, onError } = options;
const htmlProxy = httpProxy__default.default.createProxyServer({
target: mkdocsTargetAddress,
selfHandleResponse: true
});
htmlProxy.on("error", onError);
htmlProxy.on("proxyRes", (proxyRes, _req, res) => {
const contentType = proxyRes.headers["content-type"];
const contentEncoding = proxyRes.headers["content-encoding"];
const isHtml = contentType && typeof contentType === "string" && contentType.startsWith(CONTENT_TYPE_HTML);
if (isHtml && !contentEncoding) {
const chunks = [];
proxyRes.on("data", (chunk) => {
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
});
proxyRes.on("end", () => {
const body = Buffer.concat(chunks).toString("utf8");
const modifiedHtml = injectLivereloadParameters(body);
res.statusCode = proxyRes.statusCode ?? 200;
Object.keys(proxyRes.headers).forEach((key) => {
if (key.toLowerCase() !== HEADER_CONTENT_LENGTH) {
res.setHeader(key, proxyRes.headers[key]);
}
});
setCorsHeaders(res);
res.end(modifiedHtml);
});
} else {
res.statusCode = proxyRes.statusCode ?? 200;
Object.keys(proxyRes.headers).forEach((key) => {
res.setHeader(key, proxyRes.headers[key]);
});
setCorsHeaders(res);
proxyRes.pipe(res);
}
});
const forwardPath = request.url?.replace(new RegExp(`^${proxyEndpoint}`, "i"), "") || "";
request.url = forwardPath;
htmlProxy.web(request, response);
}
function proxyMkdocsLivereload(options) {
const { request, response, mkdocsTargetAddress, onError } = options;
const proxy = httpProxy__default.default.createProxyServer({ target: mkdocsTargetAddress });
proxy.on("error", onError);
setCorsHeaders(response);
response.setHeader("Access-Control-Allow-Headers", "Content-Type");
request.url = request.url?.replace(
CLI_LIVERELOAD_PATH,
MKDOCS_LIVERELOAD_PATH
);
proxy.web(request, response);
}
exports.injectLivereloadParameters = injectLivereloadParameters;
exports.proxyHtmlWithLivereloadInjection = proxyHtmlWithLivereloadInjection;
exports.proxyMkdocsLivereload = proxyMkdocsLivereload;
//# sourceMappingURL=livereload.cjs.js.map