five-server
Version:
Development Server with Live Reload Capability. (Maintained Fork of Live Server)
130 lines • 5.03 kB
JavaScript
;
/**
* @author Yannick Deubel (https://github.com/yandeu)
* @copyright Copyright (c) 2021 Yannick Deubel
* @license {@link https://github.com/yandeu/five-server/blob/main/LICENSE LICENSE}
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.injectCode = exports.code = exports.Inject = void 0;
const fs_1 = require("fs");
const path_1 = require("path");
const stream_1 = require("stream");
const zlib_1 = require("zlib");
const url_1 = __importDefault(require("url"));
/**
* unzip: Decompress either a Gzip- or Deflate-compressed stream by auto-detecting the header.
* https://nodejs.org/api/zlib.html#zlib_class_zlib_unzip
*/
const unzip = (buffer) => {
return new Promise((resolve, reject) => {
(0, zlib_1.unzip)(buffer, (err, buffer) => {
if (err)
return reject(err);
return resolve(buffer.toString());
});
});
};
class Inject extends stream_1.Writable {
constructor(tags, code) {
super();
this.tags = tags;
this.code = code;
this.size = 0;
this.chunks = [];
this.data = '';
this.injectTag = '';
}
doInjection(data) {
const injectCandidates = [new RegExp('</head>', 'i'), new RegExp('</html>', 'i'), new RegExp('</body>', 'i')];
let match;
for (let i = 0; i < injectCandidates.length; ++i) {
match = injectCandidates[i].exec(data);
if (match) {
this.injectTag = match[0];
break;
}
}
if (this.injectTag && typeof this.injectTag === 'string') {
data = data.replace(this.injectTag, this.code + this.injectTag);
}
// inject the code at the bottom of the file,
// if there are at least some html tags
else if (/<[a-z]\w+>/gm.test(data)) {
this.injectTag = true;
data = `${data}\n${this.code}`;
}
// convert cache to [src|href]="/.cache/.."
const replacer = (match, p1, p2, _offset, _string) => match.replace(p1, '').replace(p2, `/.cache/${p2.replace(/^\//, '')}`);
data = data.replace(/<[^>]*(cache.)[^>]*[src|href]="(\S+)"[^>]*>/gm, replacer);
this.data = data;
}
_write(chunk, encoding, callback) {
this.chunks.push(chunk);
callback();
}
async _final(callback) {
const buffer = Buffer.concat(this.chunks);
this.data = buffer.toString();
const raw = await unzip(buffer).catch(() => { });
if (raw)
this.data = raw;
this.doInjection(this.data);
callback();
}
}
exports.Inject = Inject;
const code = (filePath, baseURL, injectBodyOptions) => {
const a = injectBodyOptions ? ' data-inject-body="true"' : '';
return `<!-- Code injected by Five-server -->
<script async data-id="five-server" data-file="${filePath}"${a} type="application/javascript" src="${baseURL}fiveserver.js"></script>
`;
};
exports.code = code;
/** Injects the five-server script into the html page and converts the cache attributes. */
const injectCode = (root, baseURL, PHP, injectBodyOptions) => {
return async (req, res, next) => {
const { pathname } = url_1.default.parse(req.url);
if (pathname &&
(pathname === '/' ||
(0, path_1.extname)(pathname) === '.html' ||
(0, path_1.extname)(pathname) === '.htm' ||
(0, path_1.extname)(pathname) === '.php')) {
let filePath = (0, path_1.resolve)((0, path_1.join)(root + pathname));
filePath = decodeURI(filePath);
if (!(0, fs_1.existsSync)(filePath))
return next();
if (!(0, fs_1.statSync)(filePath).isFile())
return next();
const inject = new Inject(['</head>', '</html>', '</body>'], (0, exports.code)(filePath, baseURL, injectBodyOptions));
if ((0, path_1.extname)(pathname) === '.php') {
const html = await PHP.parseFile(filePath, res);
inject.doInjection(html);
res.type('html');
res.setHeader('Content-Length', inject.data.length);
return res.send(inject.data);
}
(0, fs_1.createReadStream)(filePath)
.pipe(inject)
.on('finish', () => {
if (!inject.injectTag)
return next();
else {
res.type('html');
res.setHeader('Content-Length', inject.data.length);
res.send(inject.data);
}
})
.on('error', () => {
return next();
});
}
else {
return next();
}
};
};
exports.injectCode = injectCode;
//# sourceMappingURL=injectCode.js.map