Lorolem upravena verze - LittleFS, FSBrowser pro offline, pouziti PROGMEM.

This commit is contained in:
2020-08-21 12:43:46 +02:00
parent 9db6f3d1ca
commit eeca8b9af6
117 changed files with 23138 additions and 2 deletions

581
src/edit.htm Normal file
View File

@ -0,0 +1,581 @@
<!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, .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>