581 lines
25 KiB
HTML
581 lines
25 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
|
|
<title>ESP Editor</title>
|
|
<link rel="apple-touch-icon" href="/ace.ico" type="image/x-icon" />
|
|
<link rel="shortcut icon" href="/ace.ico" type="image/x-icon" />
|
|
<link rel="icon" href="/ace.ico" type="image/x-icon" />
|
|
<style type="text/css" media="screen">
|
|
label {
|
|
font-size: 12px;
|
|
font-family: sans-serif;
|
|
}
|
|
|
|
.cm {
|
|
z-index: 300;
|
|
position: absolute;
|
|
left: 5px;
|
|
border: 1px solid #444;
|
|
background-color: #f5f5f5;
|
|
display: none;
|
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.4);
|
|
font-size: 12px;
|
|
font-family: sans-serif;
|
|
font-weight: 700;
|
|
}
|
|
|
|
.cm ul {
|
|
list-style: none;
|
|
top: 0;
|
|
left: 0;
|
|
margin: 0;
|
|
padding: 0;
|
|
}
|
|
|
|
.cm li {
|
|
position: relative;
|
|
min-width: 60px;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.cm span {
|
|
color: #444;
|
|
display: inline-block;
|
|
padding: 6px;
|
|
}
|
|
|
|
.cm li:hover {
|
|
background: #444;
|
|
}
|
|
|
|
.cm li:hover span {
|
|
color: #eee;
|
|
}
|
|
|
|
.tvu li,
|
|
.tvu ul {
|
|
padding: 0;
|
|
margin: 0;
|
|
list-style: none;
|
|
}
|
|
|
|
.tvu input {
|
|
position: absolute;
|
|
opacity: 0;
|
|
}
|
|
|
|
.tvu {
|
|
font: 400 12px Verdana, Arial, Sans-serif;
|
|
-moz-user-select: none;
|
|
-webkit-user-select: none;
|
|
user-select: none;
|
|
color: #444;
|
|
line-height: 16px;
|
|
}
|
|
|
|
.tvu span {
|
|
margin-bottom: 5px;
|
|
padding: 0 0 0 18px;
|
|
cursor: pointer;
|
|
display: inline-block;
|
|
height: 16px;
|
|
vertical-align: middle;
|
|
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAADoSURBVBgZBcExblNBGAbA2ceegTRBuIKOgiihSZNTcC5LUHAihNJR0kGKCDcYJY6D3/77MdOinTvzAgCw8ysThIvn/VojIyMjIyPP+bS1sUQIV2s95pBDDvmbP/mdkft83tpYguZq5Jh/OeaYh+yzy8hTHvNlaxNNczm+la9OTlar1UdA/+C2A4trRCnD3jS8BB1obq2Gk6GU6QbQAS4BUaYSQAf4bhhKKTFdAzrAOwAxEUAH+KEM01SY3gM6wBsEAQB0gJ+maZoC3gI6iPYaAIBJsiRmHU0AALOeFC3aK2cWAACUXe7+AwO0lc9eTHYTAAAAAElFTkSuQmCC)
|
|
no-repeat;
|
|
background-position: 0 0;
|
|
}
|
|
|
|
.tvu span:hover {
|
|
text-decoration: underline;
|
|
}
|
|
|
|
@media screen and (-webkit-min-device-pixel-ratio: 0) {
|
|
.tvu {
|
|
-webkit-animation: webkit-adjacent-element-selector-bugfix infinite 1s;
|
|
}
|
|
@-webkit-keyframes webkit-adjacent-element-selector-bugfix {
|
|
from {
|
|
padding: 0;
|
|
}
|
|
to {
|
|
padding: 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
#uploader {
|
|
position: absolute;
|
|
top: 0;
|
|
right: 0;
|
|
left: 0;
|
|
height: 28px;
|
|
line-height: 24px;
|
|
padding-left: 10px;
|
|
background-color: #444;
|
|
color: #eee;
|
|
}
|
|
|
|
#tree {
|
|
position: absolute;
|
|
top: 28px;
|
|
bottom: 0;
|
|
left: 0;
|
|
width: 160px;
|
|
padding: 8px;
|
|
}
|
|
|
|
#editor,
|
|
#preview {
|
|
position: absolute;
|
|
top: 28px;
|
|
right: 0;
|
|
bottom: 0;
|
|
left: 160px;
|
|
border-left: 1px solid #eee;
|
|
}
|
|
|
|
#preview {
|
|
background-color: #eee;
|
|
padding: 5px;
|
|
}
|
|
|
|
#loader {
|
|
position: absolute;
|
|
top: 36%;
|
|
right: 40%;
|
|
}
|
|
|
|
.loader {
|
|
z-index: 10000;
|
|
border: 8px solid #b5b5b5;
|
|
border-top: 8px solid #3498db;
|
|
border-bottom: 8px solid #3498db;
|
|
border-radius: 50%;
|
|
width: 240px;
|
|
height: 240px;
|
|
animation: spin 2s linear infinite;
|
|
display: none;
|
|
}
|
|
|
|
@keyframes spin {
|
|
0% {
|
|
transform: rotate(0);
|
|
}
|
|
100% {
|
|
transform: rotate(360deg);
|
|
}
|
|
}
|
|
</style>
|
|
<script>
|
|
function ge(e) {
|
|
return document.getElementById(e)
|
|
}
|
|
|
|
function ce(e) {
|
|
return document.createElement(e)
|
|
}
|
|
|
|
function sortByKey(e, t) {
|
|
return e.sort(function(e, n) {
|
|
var a = e[t],
|
|
i = n[t];
|
|
return i > a ? -1 : a > i ? 1 : 0
|
|
})
|
|
}
|
|
|
|
function createFileUploader(e, t, n) {
|
|
var isIpad = /(iPhone)*(OS ([7-9]|1[0-1])_)/i.test(navigator.userAgent);
|
|
|
|
function a(e, n) {
|
|
200 != e ? alert("ERROR[" + e + "]: " + n) : t.refreshPath(d.value)
|
|
}
|
|
|
|
function i(e) {
|
|
var t = new FormData;
|
|
t.append("path", e), requests.add("PUT", "/edit", t, a)
|
|
}
|
|
var o = ce("button");
|
|
o.innerHTML = "Root Dir", ge(e).appendChild(o);
|
|
var c = ce("input");
|
|
c.type = "file", c.multiple = !1, c.name = "data", c.id = "upload-select", ge(e).appendChild(c);
|
|
var d = ce("input");
|
|
d.id = "upload-path", d.type = "text", d.name = "path", d.defaultValue = "/", ge(e).appendChild(d);
|
|
var s = ce("button");
|
|
s.innerHTML = "Upload", ge(e).appendChild(s);
|
|
var r = ce("button");
|
|
r.innerHTML = "Create", ge(e).appendChild(r);
|
|
var l = ce("input");
|
|
l.id = "editor-filename", l.type = "text", l.disabled = !0, l.size = 20, ge(e).appendChild(l);
|
|
var y = ce("input");
|
|
y.id = "ipad-fix", y.name = "ipad-fix", y.type = "checkbox", isIpad ? y.checked = true : y.checked = false;
|
|
var z = ce("label");
|
|
z.for = y.id, z.innerHTML = " Alt.";
|
|
var u = ce("button");
|
|
u.innerHTML = " Save ", ge(e).appendChild(u), ge(e).appendChild(z), ge(e).appendChild(y), r.onclick = function(e) {
|
|
i(d.value), n.loadUrl(d.value), d.value = "/"
|
|
}, u.onclick = function(e) {
|
|
if (y.checked) {
|
|
var edi = ace.edit("editor");
|
|
var towrite = edi.getValue();
|
|
var q = new FormData;
|
|
q.append("rawname", l.value);
|
|
var xi = 0;
|
|
const chunkSize = 4096;
|
|
for (var start = 0; start < towrite.length; start += chunkSize) {
|
|
var chunk = towrite.substring(start, start + chunkSize);
|
|
q.append("raw" + xi, chunk);
|
|
xi++;
|
|
}
|
|
requests.add("POST", "/edit", q, a);
|
|
} else {
|
|
n.execCommand("saveCommand");
|
|
}
|
|
}, o.onclick = function(e) {
|
|
t.refreshPath(d.value)
|
|
}, s.onclick = function(e) {
|
|
if (0 !== c.files.length) {
|
|
var t = new FormData;
|
|
t.append("data", c.files[0], d.value), requests.add("POST", "/edit", t, a);
|
|
var n = ge("upload-path");
|
|
n.value = "/";
|
|
var i = ge("upload-select");
|
|
i.value = ""
|
|
}
|
|
}, c.onchange = function(e){
|
|
if(c.files.length === 0) return;
|
|
var fnm = c.files[0].name;
|
|
var ext = /(?:\.([^.]+))?$/.exec(fnm)[1];
|
|
var name = /(.*)\.[^.]+$/.exec(fnm)[1];
|
|
if(typeof name !== undefined){
|
|
fnm = name;
|
|
}
|
|
d.value = "/"+fnm+"."+ext;
|
|
};
|
|
}
|
|
|
|
function createTree(e, t) {
|
|
|
|
function n(e) {
|
|
ge("download-frame").src = "/edit?download=" + e
|
|
}
|
|
|
|
function a(e) {
|
|
var t = ge("editor-filename");
|
|
t.value = e, ge("editor").style.display = "none", h.style.display = "block", h.innerHTML = '<img src="/edit?edit=' + e + "&_cb=" + Date.now() + '" style="max-width:100%; max-height:100%; margin:auto; display:block;" />'
|
|
}
|
|
|
|
function i(e, i) {
|
|
var o = ce("ul");
|
|
e.appendChild(o);
|
|
var c = ce("li");
|
|
o.appendChild(c), r(i) ? (c.innerHTML = "<span>Preview</span>", c.onclick = function(t) {
|
|
a(i), document.body.getElementsByClassName("cm").length > 0 && document.body.removeChild(e)
|
|
}) : s(i) && (c.innerHTML = "<span>Edit</span>", c.onclick = function(n) {
|
|
t.loadUrl(i), document.body.getElementsByClassName("cm").length > 0 && document.body.removeChild(e)
|
|
});
|
|
var d = ce("li");
|
|
o.appendChild(d), s(i) || r(i) || k(i) ? (d.innerHTML = "<span>Download</span>", d.onclick = function(t) {
|
|
n(i), document.body.getElementsByClassName("cm").length > 0 && document.body.removeChild(e)
|
|
}) : z(i) ? (o.appendChild(d), d.innerHTML = "<span>ChDir</span>", d.onclick = function(t) {
|
|
f.removeChild(f.childNodes[0]), m(f, i), document.body.getElementsByClassName("cm").length > 0 && document.body.removeChild(e)
|
|
}) : ();
|
|
var l = ce("li");
|
|
o.appendChild(l), l.innerHTML = "<span>Delete</span>", l.onclick = function(t) {
|
|
u(i), document.body.getElementsByClassName("cm").length > 0 && document.body.removeChild(e)
|
|
}
|
|
}
|
|
|
|
function o(e, t, n) {
|
|
var a = ce("div"),
|
|
o = document.body.scrollTop ? document.body.scrollTop : document.documentElement.scrollTop,
|
|
c = document.body.scrollLeft ? document.body.scrollLeft : document.documentElement.scrollLeft,
|
|
d = e.clientX + c,
|
|
s = e.clientY + o;
|
|
a.className = "cm", a.style.display = "block", a.style.left = d + "px", a.style.top = s + "px", i(a, t), document.body.appendChild(a);
|
|
var r = a.offsetWidth,
|
|
l = a.offsetHeight;
|
|
a.onmouseout = function(e) {
|
|
(e.clientX < d || e.clientX > d + r || e.clientY < s || e.clientY > s + l) && document.body.getElementsByClassName("cm").length > 0 && document.body.removeChild(a)
|
|
}
|
|
}
|
|
|
|
function c(e, n, i) {
|
|
var c = ce("li");
|
|
c.id = n;
|
|
var d = ce("span");
|
|
return d.innerHTML = n, c.appendChild(d), c.onclick = function(e) {
|
|
s(c.id.toLowerCase()) ? t.loadUrl(c.id) : r(c.id.toLowerCase()) ? a(c.id) : z(c.id) ? f.removeChild(f.childNodes[0]) && m(f, c.id.toLowerCase()) : ()
|
|
}, c.oncontextmenu = function(e) {
|
|
e.preventDefault(), e.stopPropagation(), o(e, c.id, !0)
|
|
}, c
|
|
}
|
|
|
|
function d(e, t, n) {
|
|
sortByKey(n, "name");
|
|
var a = ce("ul");
|
|
e.appendChild(a);
|
|
for (var i = n.length, o = 0; i > o; o++) "file" === n[o].type && a.appendChild(c(t, n[o].name, n[o].size))
|
|
}
|
|
|
|
function z(e) {
|
|
if (e.indexOf('.') == -1) return !0
|
|
else return !1
|
|
}
|
|
|
|
function s(e) {
|
|
var t = /(?:.([^.]+))?$/.exec(e)[1];
|
|
if (void 0 !== typeof t) switch (t) {
|
|
case "txt":
|
|
case "htm":
|
|
case "html":
|
|
case "js":
|
|
case "css":
|
|
case "xml":
|
|
case "json":
|
|
case "conf":
|
|
case "ini":
|
|
case "h":
|
|
case "c":
|
|
case "cpp":
|
|
case "php":
|
|
case "hex":
|
|
case "ino":
|
|
case "pde":
|
|
return !0
|
|
}
|
|
return !1
|
|
}
|
|
|
|
function r(e) {
|
|
var t = /(?:.([^.]+))?$/.exec(e)[1];
|
|
if (void 0 !== typeof t) switch (t) {
|
|
case "png":
|
|
case "jpg":
|
|
case "gif":
|
|
case "bmp":
|
|
return !0
|
|
}
|
|
return !1
|
|
}
|
|
|
|
function k(e) { // other types may be there and good for download
|
|
var t = /(?:.([^.]+))?$/.exec(e)[1];
|
|
if (void 0 !== typeof t) switch (t) {
|
|
case "ico":
|
|
case "gz":
|
|
case "zip":
|
|
case "wav":
|
|
case "mp3":
|
|
case "pdf":
|
|
return !0
|
|
}
|
|
return !1
|
|
}
|
|
|
|
function l(e) {
|
|
return function(e, t) {
|
|
200 != e ? alert("ERROR[" + e + "]: " + t) : (f.removeChild(f.childNodes[0]), m(f, "/"))
|
|
}
|
|
}
|
|
|
|
function u(e) {
|
|
var t = new FormData;
|
|
t.append("path", e), requests.add("DELETE", "/edit", t, l(e))
|
|
}
|
|
|
|
function p(e, t) {
|
|
return function(n, a) {
|
|
200 == n && d(e, t, JSON.parse(a))
|
|
}
|
|
}
|
|
|
|
function m(e, t) {
|
|
requests.add("GET", "/edit", {
|
|
list: t
|
|
}, p(e, t))
|
|
}
|
|
var h = ge("preview"),
|
|
f = ce("div");
|
|
return f.className = "tvu", ge(e).appendChild(f), this.refreshPath = function(e) {
|
|
f.removeChild(f.childNodes[0]), m(f, "/")
|
|
}, m(f, "/"), this
|
|
}
|
|
|
|
function createEditor(e, t, n, a, i) {
|
|
function o(e) {
|
|
var t = "plain",
|
|
n = /(?:.([^.]+))?$/.exec(e)[1];
|
|
if (void 0 !== typeof n) switch (n) {
|
|
case "txt":
|
|
t = "plain";
|
|
break;
|
|
case "hex":
|
|
t = "plain";
|
|
break;
|
|
case "conf":
|
|
t = "plain";
|
|
break;
|
|
case "htm":
|
|
t = "html";
|
|
break;
|
|
case "js":
|
|
t = "javascript";
|
|
break;
|
|
case "h":
|
|
t = "c_cpp";
|
|
break;
|
|
case "c":
|
|
t = "c_cpp";
|
|
break;
|
|
case "cpp":
|
|
t = "c_cpp";
|
|
break;
|
|
case "css":
|
|
case "scss":
|
|
case "php":
|
|
case "html":
|
|
case "json":
|
|
case "xml":
|
|
case "ini":
|
|
t = n
|
|
}
|
|
return t
|
|
}
|
|
|
|
function c(e, t) {
|
|
200 != e && alert("ERROR[" + e + "]: " + t)
|
|
}
|
|
|
|
function d(e, t, n) {
|
|
var a = new FormData;
|
|
a.append("data", new Blob([t], {
|
|
type: n
|
|
}), e), requests.add("POST", "/edit", a, c)
|
|
}
|
|
|
|
function s(e, t) {
|
|
ge("preview").style.display = "none", ge("editor").style.display = "block", 200 == e ? l.setValue(t) : l.setValue(""), l.clearSelection()
|
|
}
|
|
|
|
function r(e) {
|
|
requests.add("GET", "/edit", {
|
|
edit: e
|
|
}, s)
|
|
}
|
|
"undefined" == typeof t && (t = "/index.htm"), "undefined" == typeof n && (n = o(t)), "undefined" == typeof a && (a = "monokai"), "undefined" == typeof i && (i = "text/" + n, "c_cpp" === n && (i = "text/plain"));
|
|
var l = ace.edit(e);
|
|
return "plain" !== n && l.getSession().setMode("ace/mode/" + n), l.setTheme("ace/theme/" + a), l.$blockScrolling = 1 / 0, l.getSession().setUseSoftTabs(!0), l.getSession().setTabSize(2), l.getSession().setUseWorker(!0), l.setHighlightActiveLine(!0), l.setShowPrintMargin(!1), l.commands.addCommand({
|
|
name: "saveCommand",
|
|
bindKey: {
|
|
win: "Ctrl-S",
|
|
mac: "Command-S"
|
|
},
|
|
exec: function(e) {
|
|
d(t, e.getValue() + "", i)
|
|
},
|
|
readOnly: !1
|
|
}), l.commands.addCommand({
|
|
name: "undoCommand",
|
|
bindKey: {
|
|
win: "Ctrl-Z",
|
|
mac: "Command-Z"
|
|
},
|
|
exec: function(e) {
|
|
e.getSession().getUndoManager().undo(!1)
|
|
},
|
|
readOnly: !1
|
|
}), l.commands.addCommand({
|
|
name: "redoCommand",
|
|
bindKey: {
|
|
win: "Ctrl-Shift-Z",
|
|
mac: "Command-Shift-Z"
|
|
},
|
|
exec: function(e) {
|
|
e.getSession().getUndoManager().redo(!1)
|
|
},
|
|
readOnly: !1
|
|
}), l.loadUrl = function(e) {
|
|
var a = ge("editor-filename");
|
|
a.value = e, t = e, n = o(t), i = "text/" + n, "plain" !== n && l.getSession().setMode("ace/mode/" + n), r(t)
|
|
}, l
|
|
}
|
|
|
|
function onBodyLoad() {
|
|
var e = {},
|
|
t = (window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(t, n, a) {
|
|
e[n] = a
|
|
}), createEditor("editor", e.file, e.lang, e.theme)),
|
|
n = createTree("tree", t);
|
|
|
|
window.define = ace.define;
|
|
window.require = ace.require;
|
|
ace.config.set('basePath', '/');
|
|
ace.config.set("workerPath", '/');
|
|
|
|
createFileUploader("uploader", n, t), "undefined" == typeof e.file && (e.file = "/index.htm"), t.loadUrl(e.file)
|
|
}
|
|
"undefined" == typeof XMLHttpRequest && (XMLHttpRequest = function() {
|
|
try {
|
|
return new ActiveXObject("Msxml2.XMLHTTP.6.0")
|
|
} catch (e) {}
|
|
try {
|
|
return new ActiveXObject("Msxml2.XMLHTTP.3.0")
|
|
} catch (e) {}
|
|
try {
|
|
return new ActiveXObject("Microsoft.XMLHTTP")
|
|
} catch (e) {}
|
|
throw new Error("This browser does not support XMLHttpRequest.")
|
|
});
|
|
var QueuedRequester = function() {
|
|
this.queue = [], this.running = !1, this.xmlhttp = null
|
|
};
|
|
QueuedRequester.prototype = {
|
|
_request: function(e) {
|
|
function t(e, t) {
|
|
return function() {
|
|
4 == e.readyState && (ge("loader").style.display = "none", t.callback(e.status, e.responseText), 0 === n.queue.length && (n.running = !1), n.running && n._request(n.queue.shift()))
|
|
}
|
|
}
|
|
if (this.running = !0, !(!e instanceof Object)) {
|
|
var n = this;
|
|
ge("loader").style.display = "block";
|
|
var a = "";
|
|
if (e.params instanceof FormData) a = e.params;
|
|
else if (e.params instanceof Object)
|
|
for (var i in e.params) a += "" === a ? "GET" === e.method ? "?" : "" : "&", a += encodeURIComponent(i) + "=" + encodeURIComponent(e.params[i]);
|
|
this.xmlhttp = new XMLHttpRequest, this.xmlhttp.onreadystatechange = t(this.xmlhttp, e), "GET" === e.method ? (this.xmlhttp.open(e.method, e.url + a, !0), this.xmlhttp.send()) : (this.xmlhttp.open(e.method, e.url, !0), a instanceof String && this.xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded"), this.xmlhttp.send(a))
|
|
}
|
|
},
|
|
stop: function() {
|
|
this.running && (this.running = !1), this.xmlhttp && this.xmlhttp.readyState < 4 && this.xmlhttp.abort()
|
|
},
|
|
add: function(e, t, n, a) {
|
|
this.queue.push({
|
|
url: t,
|
|
method: e,
|
|
params: n,
|
|
callback: a
|
|
}), this.running || this._request(this.queue.shift())
|
|
}
|
|
};
|
|
var requests = new QueuedRequester;
|
|
</script>
|
|
<script id="ace" src="/acefull.js" type="text/javascript" charset="utf-8"></script>
|
|
<script>
|
|
if ("undefined" == typeof ace.edit) {
|
|
var script = document.createElement("script");
|
|
(script.src = "/ace.js"), (script.async = !1), document.head.appendChild(script);
|
|
}
|
|
</script>
|
|
</head>
|
|
|
|
<body onload="onBodyLoad()">
|
|
<div id="loader" class="loader"></div>
|
|
<div id="uploader"></div>
|
|
<div id="tree"></div>
|
|
<div id="editor"></div>
|
|
<div id="preview" style="display: none;"></div>
|
|
<iframe id="download-frame" style="display: none;"></iframe>
|
|
</body>
|
|
</html> |