gulp-server-io
Version:
A local static server, plus livereload and a socket.io debugger for your SPA development with gulp
180 lines (150 loc) • 3.74 kB
JavaScript
/* eslint no-useless-escape: 0, no-negated-condition: 0 */
module.exports = function(opt = {}) {
// Options
const ignore = opt.ignore ||
opt.excludeList || ['.js', '.css', '.svg', '.ico', '.woff', '.png', '.jpg', '.jpeg'];
const prepend = (w, s) => s + w;
// Append is useless
// const append = (w, s) => w + s;
const isHtml = str => {
if (!str) {
return false;
}
return /<[:_-\w\s\!\/\=\"\']+>/i.test(str);
};
const html = opt.html || isHtml;
const rules = opt.rules || [
{
match: /<\/head>/,
fn: prepend
},
{
match: /<\/body>/,
fn: prepend
}
];
const snippetBuilder = snippet => {
if (snippet) {
if (snippet instanceof Array) {
return snippet.join('');
}
return snippet;
}
return '';
};
const snippet = snippetBuilder(opt.snippet);
// Still not sure how this work at all
const runAll = opt.runAll || false;
// Helper functions
// this is necessary to wrap in a fn
const regex = (function() {
const matches = rules
.map(function(item) {
return item.match.source;
})
.join('|');
return new RegExp(matches);
})();
const exists = body => {
if (!body) {
return false;
}
return regex.test(body);
};
// This is wrong!
const snip = body => {
if (!body) {
return false;
}
return body.lastIndexOf(snippet) !== -1;
};
// This is problematic
// we need to normalise all the rules into an array
// and run through it regardless
const snap = body => {
var _body = body;
rules.some(function(rule) {
if (rule.match.test(_body)) {
_body = _body.replace(rule.match, function(w) {
return rule.fn(w, rule.snippet || snippet);
});
if (runAll === false) {
return true;
}
return false; // Is this not needed?
}
return false;
});
return _body;
};
const accept = req => {
var ha = req.headers.accept;
if (!ha) {
return false;
}
return ha.indexOf('html') !== -1;
};
const leave = req => {
const url = req.url;
let ignored = false;
if (!url) {
return true;
}
ignore.forEach(function(item) {
if (url.indexOf(item) !== -1) {
ignored = true;
}
});
return ignored;
};
// Middleware
return function(req, res, next) {
if (res.inject) {
return next();
}
const writeHead = res.writeHead;
const write = res.write;
const end = res.end;
if (!accept(req) || leave(req)) {
return next();
}
const restore = () => {
res.writeHead = writeHead;
res.write = write;
res.end = end;
};
res.push = function(chunk) {
res.data = (res.data || '') + chunk;
};
res.write = (string, encoding) => {
if (string !== undefined) {
var body = string instanceof Buffer ? string.toString(encoding) : string;
if (exists(body) && !snip(res.data)) {
res.push(snap(body));
return true;
}
if (html(body) || html(res.data)) {
res.push(body);
return true;
}
restore();
return write.call(res, string, encoding);
}
return true;
};
res.inject = res.write;
res.writeHead = () => {};
res.end = (string, encoding) => {
restore();
var result = res.inject(string, encoding);
if (!result) {
return end.call(res, string, encoding);
}
if (res.data !== undefined && !res._header) {
res.setHeader('content-length', Buffer.byteLength(res.data, encoding));
}
res.end(res.data, encoding);
};
next();
};
};