simple-autoreload-server
Version:
Simple Web Server with live/autoreload features without browser extensions.
471 lines (469 loc) • 16.6 kB
HTML
<script type="text/javascript">
//<![CDATA[
/*
* simple-autoreload-server v0.2.15 - 2021-05-22
* <https://github.com/cytb/simple-autoreload-server>
*
* Copyright (c) 2021 cytb
*
* Licensed under the MIT License.
*/
(function(){
var AutoreloadClient, slice$ = [].slice, split$ = ''.split, join$ = [].join;
AutoreloadClient = (function(){
AutoreloadClient.displayName = 'AutoreloadClient';
var ref$, LazyQueryString, Manipulator, prototype = AutoreloadClient.prototype, constructor = AutoreloadClient;
AutoreloadClient.getDefaultOption = function(){
var x$;
x$ = {
log: false,
expose: false,
keepalive: false,
overrideOption: true,
dispatchEvent: true,
timestamp: '_tsAccessed',
location: window.location
};
x$.scan = function(it){
var i$, x$, len$, j$, ref$, len1$, tag, k$, ref1$, len2$, attribute, l$, ref2$, len3$, method, results$ = [];
for (i$ = 0, len$ = it.length; i$ < len$; ++i$) {
x$ = it[i$];
for (j$ = 0, len1$ = (ref$ = x$[0]).length; j$ < len1$; ++j$) {
tag = ref$[j$];
for (k$ = 0, len2$ = (ref1$ = x$[1]).length; k$ < len2$; ++k$) {
attribute = ref1$[k$];
for (l$ = 0, len3$ = (ref2$ = x$[2]).length; l$ < len3$; ++l$) {
method = ref2$[l$];
results$.push({
tag: tag,
attribute: attribute,
method: method
});
}
}
}
}
return results$;
}(
[[['link'], ['href'], ['update']], [['audio', 'img', 'video', 'embed', 'object'], ['src'], ['update']], [['script'], ['src'], ['replace']]]);
return x$;
};
AutoreloadClient.WebSocket = window.WebSocket || window.MozWebSocket;
AutoreloadClient.URL = (((ref$ = window.URL) != null ? ref$.prototype : void 8) != null && in$("href", window.URL.prototype) && window.URL) || (function(){
var prototype = constructor.prototype;
function constructor(uri, base){
var newBase, x$, link, i$, y$, ref$, len$;
newBase = document.createElement('base');
newBase.href = base;
x$ = document.head;
x$.insertBefore(newBase, x$.firstChild);
link = document.createElement('a');
link.href = uri;
for (i$ = 0, len$ = (ref$ = ['origin', 'protocol', 'username', 'password', 'host', 'hostname', 'port', 'pathname', 'search', 'hash', 'href']).length; i$ < len$; ++i$) {
y$ = ref$[i$];
this[y$] = link[y$] != null ? link[y$].toString() : '';
}
newBase.parentNode.removeChild(newBase);
}
prototype.toString = function(){
return this.href;
};
Object.defineProperty(prototype, 'href', {
get: function(){
var password, auth;
password = (this.password != null && ":" + this.password || '') + "";
auth = (this.username && this.username + "" + password + "@" || '') + "";
return this.protocol + "//" + auth + this.host + this.pathname + this.search + this.hash;
},
set: function(x){},
configurable: true,
enumerable: true
});
return constructor;
}());
AutoreloadClient.CustomEvent = window.CustomEvent || (function(superclass){
var prototype = extend$(import$(constructor, superclass), superclass).prototype;
function constructor(ename, arg$){
var ref$, bubbles, ref1$, cancelable, detail, x$;
ref$ = arg$ != null
? arg$
: {
bubbles: false,
cancelable: false
}, bubbles = (ref1$ = ref$.bubbles) != null ? ref1$ : false, cancelable = (ref1$ = ref$.cancelable) != null ? ref1$ : false, detail = ref$.detail;
x$ = document.createEvent('CustomEvent');
x$.initCustomEvent(ename, bubbles, cancelable, detail);
return x$;
}
return constructor;
}(window.Event));
AutoreloadClient.dispatcher = curry$(function(command, handler, data){
var eventDetail, ref$, x$;
this.log(command + "");
if (this.options.dispatchEvent) {
eventDetail = {
cancelable: true,
detail: (ref$ = import$({}, data), ref$.client = this, ref$)
};
x$ = new constructor.CustomEvent(constructor.name + "." + command, eventDetail);
if (!window.dispatchEvent(x$)) {
return;
}
}
return handler.call(this, data);
});
function AutoreloadClient(options){
this.options = options != null
? options
: constructor.getDefaultOption();
window.addEventListener('unload', bind$(this, 'onDispose'));
}
prototype.log = function(){
var args;
args = slice$.call(arguments);
if (!this.options.log) {
return;
}
return console.debug.apply(console, ["AutoreloadClient:"].concat(args));
};
prototype.resolve = function(it){
return new (constructor.URL)(it, document.baseURI);
};
prototype.urlMatches = function(a, b){
return ['origin', 'protocol', 'username', 'password', 'host', 'hostname', 'port', 'pathname'].every(function(it){
return a[it] === b[it];
});
};
prototype.addScan = function(arg$){
var tag, attribute, method, ref$, filter;
tag = arg$.tag, attribute = arg$.attribute, method = (ref$ = arg$.method) != null ? ref$ : 'update', filter = (ref$ = arg$.filter) != null
? ref$
: function(){
return true;
};
switch (false) {
case !(arguments.length > 1):
return this.addScan({
tag: arguments[0],
attribute: arguments[1],
method: arguments[2],
filter: arguments[3]
});
case !!(tag != null && (typeof attr != 'undefined' && attr !== null)):
return false;
default:
return this.options.scan.push({
tag: tag,
attribute: attribute,
method: method,
filter: filter
});
}
};
prototype.removeScan = function(tag, attribute, method){
var ref$;
method == null && (method = null);
return (ref$ = this.options).scan = ref$.scan.filter(function(it){
var key, ref$, val;
for (key in ref$ = {
tag: tag,
attribute: attribute
}) {
val = ref$[key];
if (it[key] !== val) {
return true;
}
}
return method != null && it.method !== method;
});
};
prototype.postMessage = function(type, data){
switch (false) {
case typeof type === 'string':
return this.onMessage.apply(this, arguments);
default:
return this.onMessage(import$({
type: type
}, data));
}
};
prototype.connect = function(){
return this.postMessage({
type: 'connect'
});
};
prototype.close = function(){
return this.postMessage({
type: 'close'
});
};
/* events */
prototype.onConnect = AutoreloadClient.dispatcher('connect', function(){
var x$, y$;
x$ = this.options.location;
y$ = this.websocket = new constructor.WebSocket("ws://" + x$.host + x$.pathname);
y$.onmessage = compose$(function(it){
return it.data;
}, bind$(JSON, 'parse'), bind$(this, 'onMessage'));
y$.onclose = bind$(this, 'onClose');
return x$;
});
prototype.onScan = AutoreloadClient.dispatcher('scan', function(data){
var i$, x$, ref$, len$, method, results$ = [], this$ = this;
for (i$ = 0, len$ = (ref$ = data.scan).length; i$ < len$; ++i$) {
x$ = ref$[i$];
if (typeof x$.tag !== 'string' || typeof x$.attribute !== 'string') {
continue;
}
method = constructor.Manipulator[x$.method] != null && bind$(constructor.Manipulator, x$.method) || x$.method;
if (typeof method !== 'function') {
continue;
}
results$.push(constructor.Manipulator.find(x$.tag, x$.attribute, fn$));
}
return results$;
function fn$(target, attribute, value){
var x$, ref$;
x$ = (ref$ = import$({}, data), ref$.targetUrl = this$.resolve(value), ref$.target = target, ref$.attribute = attribute, ref$.value = value, ref$.method = method, ref$);
switch (false) {
case !!this$.urlMatches(x$.targetUrl, x$.url):
return target;
case !data.reload:
this$.onReload(x$);
break;
default:
this$.onRefresh(x$);
}
return x$;
}
});
prototype.onClose = AutoreloadClient.dispatcher('close', function(){
var ref$;
if ((ref$ = this.websocket) != null) {
ref$.close();
}
if (!this.disposed && this.options.keepalive) {
return this.connect();
}
});
prototype.onOpen = AutoreloadClient.dispatcher('open', function(data){
var name;
if (this.options.overrideOption) {
import$(this.options, data.options);
}
if (name = this.options.expose) {
if (typeof name !== 'string') {
name = constructor.displayName;
}
window[name] = this;
return this.log(constructor.displayName + " instance exposed as window['" + name + "']");
}
});
prototype.onMessage = AutoreloadClient.dispatcher('message', function(data){
var handler, that, ref$;
handler = data.type.replace(/^./, function(it){
return it.toUpperCase();
});
if ((that = data.path) != null) {
data.url = this.resolve(that);
}
return this["on" + handler]((ref$ = import$({}, data), ref$.location = this.resolve(this.options.location), ref$.url = data.path && this.resolve(data.path) || null, ref$));
});
prototype.onRefresh = AutoreloadClient.dispatcher('refresh', function(data){
var newUrl, x$;
newUrl = this.resolve(data.targetUrl.href);
x$ = constructor.QueryString.parse(newUrl.search);
x$[this.options.timestamp] = Date.now();
newUrl.search = "?" + constructor.QueryString.stringify(x$);
return data.method(data.target, data.attribute, newUrl.href);
});
prototype.onReload = AutoreloadClient.dispatcher('reload', function(data){
switch (false) {
case !!data.reload:
return this.onRefresh(data);
default:
this.onDispose();
return window.location.reload();
}
});
prototype.onUpdate = AutoreloadClient.dispatcher('update', function(data){
var x$, ref$;
x$ = (ref$ = import$({}, data), ref$.url = this.resolve(data.path, {
method: function(){}
}), ref$);
if (this.urlMatches(x$.location, x$.url)) {
this.onReload((ref$ = import$({}, x$), ref$.reload = true, ref$.self = true, ref$));
} else {
this.onScan((ref$ = import$({}, x$), ref$.scan = this.options.scan.map(function(it){
return import$({}, it);
}), ref$));
}
return x$;
});
prototype.onDispose = function(){
var ref$;
this.disposed = true;
return (ref$ = this.websocket) != null ? ref$.close() : void 8;
};
/* utils */;
AutoreloadClient.QueryString = LazyQueryString = (function(){
LazyQueryString.displayName = 'LazyQueryString';
var isArray, prototype = LazyQueryString.prototype, constructor = LazyQueryString;
isArray = (function(it){
return it instanceof Array;
});
LazyQueryString.parse = function(qs){
var object, i$, x$, ref$, len$, ref1$, key, value, that;
qs == null && (qs = '');
if (typeof qs !== "string") {
qs = qs.search;
}
object = {};
for (i$ = 0, len$ = (ref$ = split$.call((/^\?*([^#]*)$/.exec(qs != null ? qs : ''))[1], '&')).length; i$ < len$; ++i$) {
x$ = ref$[i$];
ref1$ = /^([^=]*)(=(.*))?$/.exec(x$), key = ref1$[1], value = ref1$[3];
object[key] = (fn$());
}
return object;
function fn$(){
var ref$;
switch (ref$ = [object[key]], false) {
case !function(it){
return it == null;
}(ref$[0]):
return value;
case !(that = isArray(ref$[0])):
return that.concat(value);
default:
return [that];
}
}
};
LazyQueryString.stringify = function(queryobject){
var key, val;
queryobject == null && (queryobject = {});
return (function(it){
return join$.call(it, '&');
})((function(){
var ref$, results$ = [];
for (key in ref$ = queryobject) {
val = ref$[key];
switch (false) {
case !!key:
continue;
case val != null:
results$.push(key + "");
break;
case !isArray(val):
results$.push((fn$)(
val.map(fn1$)));
break;
default:
results$.push(key + "=" + val);
}
}
return results$;
function fn$(it){
return join$.call(it, '&');
}
function fn1$(it){
return key + "=" + it;
}
}()));
};
function LazyQueryString(){}
return LazyQueryString;
}());
AutoreloadClient.Manipulator = Manipulator = (function(){
Manipulator.displayName = 'Manipulator';
var prototype = Manipulator.prototype, constructor = Manipulator;
Manipulator.find = function(tag, attribute, functor){
var i$, x$, ref$, len$, that, results$ = [];
functor == null && (functor = function(){});
for (i$ = 0, len$ = (ref$ = document.getElementsByTagName(tag)).length; i$ < len$; ++i$) {
x$ = ref$[i$];
if ((that = x$.getAttribute(attribute)) != null) {
results$.push(functor(x$, attribute, that));
}
}
return results$;
};
Manipulator.move = function(src, dest){
var i$, x$, ref$, len$, y$;
dest == null && (dest = document.createElement(src.tagName));
for (i$ = 0, len$ = (ref$ = src.attributes).length; i$ < len$; ++i$) {
x$ = ref$[i$];
dest.setAttribute(x$.nodeName, x$.nodeValue);
}
for (i$ = 0, len$ = (ref$ = src.childNodes).length; i$ < len$; ++i$) {
y$ = ref$[i$];
dest.appendChild(src.childNodes.firstChild);
}
return dest;
};
Manipulator.update = function(element, name, value){
element.setAttribute(name, value);
return element;
};
Manipulator.replace = function(target, name, value){
var copied, x$;
copied = this.move(target, null);
this.update(copied, name, value);
x$ = target;
x$.parentNode.insertBefore(copied, x$);
x$.parentNode.removeChild(x$);
return x$;
};
function Manipulator(){}
return Manipulator;
}());
return AutoreloadClient;
}());
/* main */
new AutoreloadClient(null).connect();
function in$(x, xs){
var i = -1, l = xs.length >>> 0;
while (++i < l) if (x === xs[i]) return true;
return false;
}
function extend$(sub, sup){
function fun(){} fun.prototype = (sub.superclass = sup).prototype;
(sub.prototype = new fun).constructor = sub;
if (typeof sup.extended == 'function') sup.extended(sub);
return sub;
}
function import$(obj, src){
var own = {}.hasOwnProperty;
for (var key in src) if (own.call(src, key)) obj[key] = src[key];
return obj;
}
function curry$(f, bound){
var context,
_curry = function(args) {
return f.length > 1 ? function(){
var params = args ? args.concat() : [];
context = bound ? context || this : this;
return params.push.apply(params, arguments) <
f.length && arguments.length ?
_curry.call(context, params) : f.apply(context, params);
} : f;
};
return _curry();
}
function bind$(obj, key, target){
return function(){ return (target || obj)[key].apply(obj, arguments) };
}
function compose$() {
var functions = arguments;
return function() {
var i, result;
result = functions[0].apply(this, arguments);
for (i = 1; i < functions.length; ++i) {
result = functions[i](result);
}
return result;
};
}
}).call(this);
//]]>
</script>