mirror of
https://github.com/9001/copyparty.git
synced 2025-10-28 18:43:39 +00:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7d9057cc62 | ||
|
|
c4b322b883 | ||
|
|
19b09c898a | ||
|
|
eafe2098b6 | ||
|
|
2bc6a20d71 | ||
|
|
8b502a7235 | ||
|
|
37567844af | ||
|
|
2f6c4e0e34 | ||
|
|
1c7cc4cb2b | ||
|
|
f83db3648e | ||
|
|
b164aa00d4 | ||
|
|
a2d866d0c2 |
12
.eslintrc.json
Normal file
12
.eslintrc.json
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"browser": true,
|
||||||
|
"es2021": true
|
||||||
|
},
|
||||||
|
"extends": "eslint:recommended",
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaVersion": 12
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -123,20 +123,17 @@ def main():
|
|||||||
"""
|
"""
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
ap.add_argument(
|
ap.add_argument("-c", metavar="PATH", type=str, action="append", help="add config file")
|
||||||
"-c", metavar="PATH", type=str, action="append", help="add config file"
|
|
||||||
)
|
|
||||||
ap.add_argument("-i", metavar="IP", type=str, default="0.0.0.0", help="ip to bind")
|
ap.add_argument("-i", metavar="IP", type=str, default="0.0.0.0", help="ip to bind")
|
||||||
ap.add_argument("-p", metavar="PORT", type=int, default=3923, help="port to bind")
|
ap.add_argument("-p", metavar="PORT", type=int, default=3923, help="port to bind")
|
||||||
ap.add_argument("-nc", metavar="NUM", type=int, default=64, help="max num clients")
|
ap.add_argument("-nc", metavar="NUM", type=int, default=64, help="max num clients")
|
||||||
ap.add_argument(
|
ap.add_argument("-j", metavar="CORES", type=int, default=1, help="max num cpu cores")
|
||||||
"-j", metavar="CORES", type=int, default=1, help="max num cpu cores"
|
|
||||||
)
|
|
||||||
ap.add_argument("-a", metavar="ACCT", type=str, action="append", help="add account")
|
ap.add_argument("-a", metavar="ACCT", type=str, action="append", help="add account")
|
||||||
ap.add_argument("-v", metavar="VOL", type=str, action="append", help="add volume")
|
ap.add_argument("-v", metavar="VOL", type=str, action="append", help="add volume")
|
||||||
ap.add_argument("-q", action="store_true", help="quiet")
|
ap.add_argument("-q", action="store_true", help="quiet")
|
||||||
ap.add_argument("-ed", action="store_true", help="enable ?dots")
|
ap.add_argument("-ed", action="store_true", help="enable ?dots")
|
||||||
ap.add_argument("-emp", action="store_true", help="enable markdown plugins")
|
ap.add_argument("-emp", action="store_true", help="enable markdown plugins")
|
||||||
|
ap.add_argument("-mcr", metavar="SEC", type=int, default=60, help="md-editor mod-chk rate")
|
||||||
ap.add_argument("-nw", action="store_true", help="disable writes (benchmark)")
|
ap.add_argument("-nw", action="store_true", help="disable writes (benchmark)")
|
||||||
ap.add_argument("-nih", action="store_true", help="no info hostname")
|
ap.add_argument("-nih", action="store_true", help="no info hostname")
|
||||||
ap.add_argument("-nid", action="store_true", help="no info disk-usage")
|
ap.add_argument("-nid", action="store_true", help="no info disk-usage")
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
|
|
||||||
VERSION = (0, 5, 5)
|
VERSION = (0, 6, 0)
|
||||||
CODENAME = "fuse jelly"
|
CODENAME = "CHRISTMAAAAAS"
|
||||||
BUILD_DT = (2020, 11, 27)
|
BUILD_DT = (2020, 12, 1)
|
||||||
|
|
||||||
S_VERSION = ".".join(map(str, VERSION))
|
S_VERSION = ".".join(map(str, VERSION))
|
||||||
S_BUILD_DT = "{0:04d}-{1:02d}-{2:02d}".format(*BUILD_DT)
|
S_BUILD_DT = "{0:04d}-{1:02d}-{2:02d}".format(*BUILD_DT)
|
||||||
|
|||||||
@@ -756,9 +756,12 @@ class HttpCli(object):
|
|||||||
cli_dt = time.strptime(cli_lastmod, "%a, %d %b %Y %H:%M:%S GMT")
|
cli_dt = time.strptime(cli_lastmod, "%a, %d %b %Y %H:%M:%S GMT")
|
||||||
cli_ts = calendar.timegm(cli_dt)
|
cli_ts = calendar.timegm(cli_dt)
|
||||||
return file_lastmod, int(file_ts) > int(cli_ts)
|
return file_lastmod, int(file_ts) > int(cli_ts)
|
||||||
except:
|
except Exception as ex:
|
||||||
self.log("bad lastmod format: {}".format(cli_lastmod))
|
self.log(
|
||||||
self.log(" expected format: {}".format(file_lastmod))
|
"lastmod {}\nremote: [{}]\n local: [{}]".format(
|
||||||
|
repr(ex), cli_lastmod, file_lastmod
|
||||||
|
)
|
||||||
|
)
|
||||||
return file_lastmod, file_lastmod != cli_lastmod
|
return file_lastmod, file_lastmod != cli_lastmod
|
||||||
|
|
||||||
return file_lastmod, True
|
return file_lastmod, True
|
||||||
@@ -964,6 +967,7 @@ class HttpCli(object):
|
|||||||
"title": html_escape(self.vpath),
|
"title": html_escape(self.vpath),
|
||||||
"lastmod": int(ts_md * 1000),
|
"lastmod": int(ts_md * 1000),
|
||||||
"md_plug": "true" if self.args.emp else "false",
|
"md_plug": "true" if self.args.emp else "false",
|
||||||
|
"md_chk_rate": self.args.mcr,
|
||||||
"md": "",
|
"md": "",
|
||||||
}
|
}
|
||||||
sz_html = len(template.render(**targs).encode("utf-8"))
|
sz_html = len(template.render(**targs).encode("utf-8"))
|
||||||
|
|||||||
12
copyparty/web/Makefile
Normal file
12
copyparty/web/Makefile
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# run me to zopfli all the static files
|
||||||
|
# which should help on really slow connections
|
||||||
|
# but then why are you using copyparty in the first place
|
||||||
|
|
||||||
|
pk: $(addsuffix .gz, $(wildcard *.js *.css))
|
||||||
|
un: $(addsuffix .un, $(wildcard *.gz))
|
||||||
|
|
||||||
|
%.gz: %
|
||||||
|
pigz -11 -J 34 -I 5730 $<
|
||||||
|
|
||||||
|
%.un: %
|
||||||
|
pigz -d $<
|
||||||
@@ -68,6 +68,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script src="/.cpr/util.js{{ ts }}"></script>
|
||||||
|
|
||||||
{%- if can_read %}
|
{%- if can_read %}
|
||||||
<script src="/.cpr/browser.js{{ ts }}"></script>
|
<script src="/.cpr/browser.js{{ ts }}"></script>
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|||||||
@@ -1,75 +1,9 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
// error handler for mobile devices
|
window.onerror = vis_exh;
|
||||||
function hcroak(msg) {
|
|
||||||
document.body.innerHTML = msg;
|
|
||||||
window.onerror = undefined;
|
|
||||||
throw 'fatal_err';
|
|
||||||
}
|
|
||||||
function croak(msg) {
|
|
||||||
document.body.textContent = msg;
|
|
||||||
window.onerror = undefined;
|
|
||||||
throw msg;
|
|
||||||
}
|
|
||||||
function esc(txt) {
|
|
||||||
return txt.replace(/[&"<>]/g, function (c) {
|
|
||||||
return {
|
|
||||||
'&': '&',
|
|
||||||
'"': '"',
|
|
||||||
'<': '<',
|
|
||||||
'>': '>'
|
|
||||||
}[c];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
window.onerror = function (msg, url, lineNo, columnNo, error) {
|
|
||||||
window.onerror = undefined;
|
|
||||||
var html = ['<h1>you hit a bug!</h1><p>please screenshot this error and send me a copy arigathanks gozaimuch (ed/irc.rizon.net or ed#2644)</p><p>',
|
|
||||||
esc(String(msg)), '</p><p>', esc(url + ' @' + lineNo + ':' + columnNo), '</p>'];
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
var find = ['desc', 'stack', 'trace'];
|
|
||||||
for (var a = 0; a < find.length; a++)
|
|
||||||
if (String(error[find[a]]) !== 'undefined')
|
|
||||||
html.push('<h2>' + find[a] + '</h2>' +
|
|
||||||
esc(String(error[find[a]])).replace(/\n/g, '<br />\n'));
|
|
||||||
}
|
|
||||||
document.body.style.fontSize = '0.8em';
|
|
||||||
document.body.style.padding = '0 1em 1em 1em';
|
|
||||||
hcroak(html.join('\n'));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith
|
|
||||||
if (!String.prototype.endsWith) {
|
|
||||||
String.prototype.endsWith = function (search, this_len) {
|
|
||||||
if (this_len === undefined || this_len > this.length) {
|
|
||||||
this_len = this.length;
|
|
||||||
}
|
|
||||||
return this.substring(this_len - search.length, this_len) === search;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// https://stackoverflow.com/a/950146
|
|
||||||
function import_js(url, cb) {
|
|
||||||
var head = document.head || document.getElementsByTagName('head')[0];
|
|
||||||
var script = document.createElement('script');
|
|
||||||
script.type = 'text/javascript';
|
|
||||||
script.src = url;
|
|
||||||
|
|
||||||
script.onreadystatechange = cb;
|
|
||||||
script.onload = cb;
|
|
||||||
|
|
||||||
head.appendChild(script);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function o(id) {
|
|
||||||
return document.getElementById(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
function dbg(msg) {
|
function dbg(msg) {
|
||||||
o('path').innerHTML = msg;
|
ebi('path').innerHTML = msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
function ev(e) {
|
function ev(e) {
|
||||||
@@ -78,40 +12,7 @@ function ev(e) {
|
|||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
makeSortable(ebi('files'));
|
||||||
function sortTable(table, col) {
|
|
||||||
var tb = table.tBodies[0], // use `<tbody>` to ignore `<thead>` and `<tfoot>` rows
|
|
||||||
th = table.tHead.rows[0].cells,
|
|
||||||
tr = Array.prototype.slice.call(tb.rows, 0),
|
|
||||||
i, reverse = th[col].className == 'sort1' ? -1 : 1;
|
|
||||||
for (var a = 0, thl = th.length; a < thl; a++)
|
|
||||||
th[a].className = '';
|
|
||||||
th[col].className = 'sort' + reverse;
|
|
||||||
var stype = th[col].getAttribute('sort');
|
|
||||||
tr = tr.sort(function (a, b) {
|
|
||||||
var v1 = a.cells[col].textContent.trim();
|
|
||||||
var v2 = b.cells[col].textContent.trim();
|
|
||||||
if (stype == 'int') {
|
|
||||||
v1 = parseInt(v1.replace(/,/g, ''));
|
|
||||||
v2 = parseInt(v2.replace(/,/g, ''));
|
|
||||||
return reverse * (v1 - v2);
|
|
||||||
}
|
|
||||||
return reverse * (v1.localeCompare(v2));
|
|
||||||
});
|
|
||||||
for (i = 0; i < tr.length; ++i) tb.appendChild(tr[i]);
|
|
||||||
}
|
|
||||||
function makeSortable(table) {
|
|
||||||
var th = table.tHead, i;
|
|
||||||
th && (th = th.rows[0]) && (th = th.cells);
|
|
||||||
if (th) i = th.length;
|
|
||||||
else return; // if no `<thead>` then do nothing
|
|
||||||
while (--i >= 0) (function (i) {
|
|
||||||
th[i].onclick = function () {
|
|
||||||
sortTable(table, i);
|
|
||||||
};
|
|
||||||
}(i));
|
|
||||||
}
|
|
||||||
makeSortable(o('files'));
|
|
||||||
|
|
||||||
|
|
||||||
// extract songs + add play column
|
// extract songs + add play column
|
||||||
@@ -124,9 +25,9 @@ var mp = (function () {
|
|||||||
'tracks': tracks,
|
'tracks': tracks,
|
||||||
'cover_url': ''
|
'cover_url': ''
|
||||||
};
|
};
|
||||||
var re_audio = new RegExp('\.(opus|ogg|m4a|aac|mp3|wav|flac)$', 'i');
|
var re_audio = /\.(opus|ogg|m4a|aac|mp3|wav|flac)$/i;
|
||||||
|
|
||||||
var trs = document.getElementById('files').getElementsByTagName('tbody')[0].getElementsByTagName('tr');
|
var trs = ebi('files').getElementsByTagName('tbody')[0].getElementsByTagName('tr');
|
||||||
for (var a = 0, aa = trs.length; a < aa; a++) {
|
for (var a = 0, aa = trs.length; a < aa; a++) {
|
||||||
var tds = trs[a].getElementsByTagName('td');
|
var tds = trs[a].getElementsByTagName('td');
|
||||||
var link = tds[1].getElementsByTagName('a')[0];
|
var link = tds[1].getElementsByTagName('a')[0];
|
||||||
@@ -142,7 +43,7 @@ var mp = (function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (var a = 0, aa = tracks.length; a < aa; a++)
|
for (var a = 0, aa = tracks.length; a < aa; a++)
|
||||||
o('trk' + a).onclick = ev_play;
|
ebi('trk' + a).onclick = ev_play;
|
||||||
|
|
||||||
ret.vol = localStorage.getItem('vol');
|
ret.vol = localStorage.getItem('vol');
|
||||||
if (ret.vol !== null)
|
if (ret.vol !== null)
|
||||||
@@ -169,8 +70,8 @@ var mp = (function () {
|
|||||||
// toggle player widget
|
// toggle player widget
|
||||||
var widget = (function () {
|
var widget = (function () {
|
||||||
var ret = {};
|
var ret = {};
|
||||||
var widget = document.getElementById('widget');
|
var widget = ebi('widget');
|
||||||
var wtoggle = document.getElementById('wtoggle');
|
var wtoggle = ebi('wtoggle');
|
||||||
var touchmode = false;
|
var touchmode = false;
|
||||||
var side_open = false;
|
var side_open = false;
|
||||||
var was_paused = true;
|
var was_paused = true;
|
||||||
@@ -199,7 +100,7 @@ var widget = (function () {
|
|||||||
ret.paused = function (paused) {
|
ret.paused = function (paused) {
|
||||||
if (was_paused != paused) {
|
if (was_paused != paused) {
|
||||||
was_paused = paused;
|
was_paused = paused;
|
||||||
o('bplay').innerHTML = paused ? '▶' : '⏸';
|
ebi('bplay').innerHTML = paused ? '▶' : '⏸';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
var click_handler = function (e) {
|
var click_handler = function (e) {
|
||||||
@@ -223,8 +124,8 @@ var widget = (function () {
|
|||||||
// buffer/position bar
|
// buffer/position bar
|
||||||
var pbar = (function () {
|
var pbar = (function () {
|
||||||
var r = {};
|
var r = {};
|
||||||
r.bcan = o('barbuf');
|
r.bcan = ebi('barbuf');
|
||||||
r.pcan = o('barpos');
|
r.pcan = ebi('barpos');
|
||||||
r.bctx = r.bcan.getContext('2d');
|
r.bctx = r.bcan.getContext('2d');
|
||||||
r.pctx = r.pcan.getContext('2d');
|
r.pctx = r.pcan.getContext('2d');
|
||||||
|
|
||||||
@@ -289,7 +190,7 @@ var pbar = (function () {
|
|||||||
// volume bar
|
// volume bar
|
||||||
var vbar = (function () {
|
var vbar = (function () {
|
||||||
var r = {};
|
var r = {};
|
||||||
r.can = o('pvol');
|
r.can = ebi('pvol');
|
||||||
r.ctx = r.can.getContext('2d');
|
r.ctx = r.can.getContext('2d');
|
||||||
|
|
||||||
var bctx = r.ctx;
|
var bctx = r.ctx;
|
||||||
@@ -386,7 +287,7 @@ var vbar = (function () {
|
|||||||
else
|
else
|
||||||
play(0);
|
play(0);
|
||||||
};
|
};
|
||||||
o('bplay').onclick = function (e) {
|
ebi('bplay').onclick = function (e) {
|
||||||
ev(e);
|
ev(e);
|
||||||
if (mp.au) {
|
if (mp.au) {
|
||||||
if (mp.au.paused)
|
if (mp.au.paused)
|
||||||
@@ -397,15 +298,15 @@ var vbar = (function () {
|
|||||||
else
|
else
|
||||||
play(0);
|
play(0);
|
||||||
};
|
};
|
||||||
o('bprev').onclick = function (e) {
|
ebi('bprev').onclick = function (e) {
|
||||||
ev(e);
|
ev(e);
|
||||||
bskip(-1);
|
bskip(-1);
|
||||||
};
|
};
|
||||||
o('bnext').onclick = function (e) {
|
ebi('bnext').onclick = function (e) {
|
||||||
ev(e);
|
ev(e);
|
||||||
bskip(1);
|
bskip(1);
|
||||||
};
|
};
|
||||||
o('barpos').onclick = function (e) {
|
ebi('barpos').onclick = function (e) {
|
||||||
if (!mp.au) {
|
if (!mp.au) {
|
||||||
//dbg((new Date()).getTime());
|
//dbg((new Date()).getTime());
|
||||||
return play(0);
|
return play(0);
|
||||||
@@ -471,7 +372,7 @@ function ev_play(e) {
|
|||||||
|
|
||||||
|
|
||||||
function setclass(id, clas) {
|
function setclass(id, clas) {
|
||||||
o(id).setAttribute('class', clas);
|
ebi(id).setAttribute('class', clas);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -567,7 +468,6 @@ function play(tid, call_depth) {
|
|||||||
function evau_error(e) {
|
function evau_error(e) {
|
||||||
var err = '';
|
var err = '';
|
||||||
var eplaya = (e && e.target) || (window.event && window.event.srcElement);
|
var eplaya = (e && e.target) || (window.event && window.event.srcElement);
|
||||||
var url = eplaya.src;
|
|
||||||
|
|
||||||
switch (eplaya.error.code) {
|
switch (eplaya.error.code) {
|
||||||
case eplaya.error.MEDIA_ERR_ABORTED:
|
case eplaya.error.MEDIA_ERR_ABORTED:
|
||||||
@@ -608,20 +508,20 @@ function show_modal(html) {
|
|||||||
|
|
||||||
// hide fullscreen message
|
// hide fullscreen message
|
||||||
function unblocked() {
|
function unblocked() {
|
||||||
var dom = o('blocked');
|
var dom = ebi('blocked');
|
||||||
if (dom)
|
if (dom)
|
||||||
dom.parentNode.removeChild(dom);
|
dom.parentNode.removeChild(dom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// show ui to manually start playback of a linked song
|
// show ui to manually start playback of a linked song
|
||||||
function autoplay_blocked(tid) {
|
function autoplay_blocked() {
|
||||||
show_modal(
|
show_modal(
|
||||||
'<div id="blk_play"><a href="#" id="blk_go"></a></div>' +
|
'<div id="blk_play"><a href="#" id="blk_go"></a></div>' +
|
||||||
'<div id="blk_abrt"><a href="#" id="blk_na">Cancel<br />(show file list)</a></div>');
|
'<div id="blk_abrt"><a href="#" id="blk_na">Cancel<br />(show file list)</a></div>');
|
||||||
|
|
||||||
var go = o('blk_go');
|
var go = ebi('blk_go');
|
||||||
var na = o('blk_na');
|
var na = ebi('blk_na');
|
||||||
|
|
||||||
var fn = mp.tracks[mp.au.tid].split(/\//).pop();
|
var fn = mp.tracks[mp.au.tid].split(/\//).pop();
|
||||||
fn = decodeURIComponent(fn.replace(/\+/g, ' '));
|
fn = decodeURIComponent(fn.replace(/\+/g, ' '));
|
||||||
|
|||||||
@@ -126,7 +126,8 @@ write markdown (most html is 🙆 too)
|
|||||||
var last_modified = {{ lastmod }};
|
var last_modified = {{ lastmod }};
|
||||||
var md_opt = {
|
var md_opt = {
|
||||||
link_md_as_html: false,
|
link_md_as_html: false,
|
||||||
allow_plugins: {{ md_plug }}
|
allow_plugins: {{ md_plug }},
|
||||||
|
modpoll_freq: {{ md_chk_rate }}
|
||||||
};
|
};
|
||||||
|
|
||||||
(function () {
|
(function () {
|
||||||
@@ -144,14 +145,8 @@ var md_opt = {
|
|||||||
toggle();
|
toggle();
|
||||||
})();
|
})();
|
||||||
|
|
||||||
if (!String.startsWith) {
|
|
||||||
String.prototype.startsWith = function(s, i) {
|
|
||||||
i = i>0 ? i|0 : 0;
|
|
||||||
return this.substring(i, i + s.length) === s;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
<script src="/.cpr/util.js"></script>
|
||||||
<script src="/.cpr/deps/marked.full.js"></script>
|
<script src="/.cpr/deps/marked.full.js"></script>
|
||||||
<script src="/.cpr/md.js"></script>
|
<script src="/.cpr/md.js"></script>
|
||||||
{%- if edit %}
|
{%- if edit %}
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
var dom_toc = document.getElementById('toc');
|
"use strict";
|
||||||
var dom_wrap = document.getElementById('mw');
|
|
||||||
var dom_hbar = document.getElementById('mh');
|
var dom_toc = ebi('toc');
|
||||||
var dom_nav = document.getElementById('mn');
|
var dom_wrap = ebi('mw');
|
||||||
var dom_pre = document.getElementById('mp');
|
var dom_hbar = ebi('mh');
|
||||||
var dom_src = document.getElementById('mt');
|
var dom_nav = ebi('mn');
|
||||||
var dom_navtgl = document.getElementById('navtoggle');
|
var dom_pre = ebi('mp');
|
||||||
|
var dom_src = ebi('mt');
|
||||||
|
var dom_navtgl = ebi('navtoggle');
|
||||||
|
|
||||||
|
|
||||||
// chrome 49 needs this
|
// chrome 49 needs this
|
||||||
@@ -34,7 +36,7 @@ function cls(dom, name, add) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function static(obj) {
|
function statify(obj) {
|
||||||
return JSON.parse(JSON.stringify(obj));
|
return JSON.parse(JSON.stringify(obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,6 +160,46 @@ function copydom(src, dst, lv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function md_plug_err(ex, js) {
|
||||||
|
var errbox = ebi('md_errbox');
|
||||||
|
if (errbox)
|
||||||
|
errbox.parentNode.removeChild(errbox);
|
||||||
|
|
||||||
|
if (!ex)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var msg = (ex + '').split('\n')[0];
|
||||||
|
var ln = ex.lineNumber;
|
||||||
|
var o = null;
|
||||||
|
if (ln) {
|
||||||
|
msg = "Line " + ln + ", " + msg;
|
||||||
|
var lns = js.split('\n');
|
||||||
|
if (ln < lns.length) {
|
||||||
|
o = document.createElement('span');
|
||||||
|
o.style.cssText = 'color:#ac2;font-size:.9em;font-family:scp;display:block';
|
||||||
|
o.textContent = lns[ln - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
errbox = document.createElement('div');
|
||||||
|
errbox.setAttribute('id', 'md_errbox');
|
||||||
|
errbox.style.cssText = 'position:absolute;top:0;left:0;padding:1em .5em;background:#2b2b2b;color:#fc5'
|
||||||
|
errbox.textContent = msg;
|
||||||
|
errbox.onclick = function () {
|
||||||
|
alert('' + ex.stack);
|
||||||
|
};
|
||||||
|
if (o) {
|
||||||
|
errbox.appendChild(o);
|
||||||
|
errbox.style.padding = '.25em .5em';
|
||||||
|
}
|
||||||
|
dom_nav.appendChild(errbox);
|
||||||
|
|
||||||
|
try {
|
||||||
|
console.trace();
|
||||||
|
}
|
||||||
|
catch (ex2) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function load_plug(md_text, plug_type) {
|
function load_plug(md_text, plug_type) {
|
||||||
if (!md_opt.allow_plugins)
|
if (!md_opt.allow_plugins)
|
||||||
return md_text;
|
return md_text;
|
||||||
@@ -177,7 +219,14 @@ function load_plug(md_text, plug_type) {
|
|||||||
var old_plug = md_plug[plug_type];
|
var old_plug = md_plug[plug_type];
|
||||||
if (!old_plug || old_plug[1] != js) {
|
if (!old_plug || old_plug[1] != js) {
|
||||||
js = 'const x = { ' + js + ' }; x;';
|
js = 'const x = { ' + js + ' }; x;';
|
||||||
|
try {
|
||||||
var x = eval(js);
|
var x = eval(js);
|
||||||
|
}
|
||||||
|
catch (ex) {
|
||||||
|
md_plug[plug_type] = null;
|
||||||
|
md_plug_err(ex, js);
|
||||||
|
return md;
|
||||||
|
}
|
||||||
if (x['ctor']) {
|
if (x['ctor']) {
|
||||||
x['ctor']();
|
x['ctor']();
|
||||||
delete x['ctor'];
|
delete x['ctor'];
|
||||||
@@ -191,20 +240,30 @@ function load_plug(md_text, plug_type) {
|
|||||||
|
|
||||||
function convert_markdown(md_text, dest_dom) {
|
function convert_markdown(md_text, dest_dom) {
|
||||||
md_text = md_text.replace(/\r/g, '');
|
md_text = md_text.replace(/\r/g, '');
|
||||||
|
|
||||||
|
md_plug_err(null);
|
||||||
md_text = load_plug(md_text, 'pre');
|
md_text = load_plug(md_text, 'pre');
|
||||||
md_text = load_plug(md_text, 'post');
|
md_text = load_plug(md_text, 'post');
|
||||||
|
|
||||||
marked.setOptions({
|
var marked_opts = {
|
||||||
//headerPrefix: 'h-',
|
//headerPrefix: 'h-',
|
||||||
breaks: true,
|
breaks: true,
|
||||||
gfm: true
|
gfm: true
|
||||||
});
|
};
|
||||||
|
|
||||||
if (md_plug['pre']) {
|
var ext = md_plug['pre'];
|
||||||
marked.use(md_plug['pre'][0]);
|
if (ext)
|
||||||
|
Object.assign(marked_opts, ext[0]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
var md_html = marked(md_text, marked_opts);
|
||||||
}
|
}
|
||||||
|
catch (ex) {
|
||||||
|
if (ext)
|
||||||
|
md_plug_err(ex, ext[1]);
|
||||||
|
|
||||||
var md_html = marked(md_text);
|
throw ex;
|
||||||
|
}
|
||||||
var md_dom = new DOMParser().parseFromString(md_html, "text/html").body;
|
var md_dom = new DOMParser().parseFromString(md_html, "text/html").body;
|
||||||
|
|
||||||
var nodes = md_dom.getElementsByTagName('a');
|
var nodes = md_dom.getElementsByTagName('a');
|
||||||
@@ -240,7 +299,7 @@ function convert_markdown(md_text, dest_dom) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// separate <code> for each line in <pre>
|
// separate <code> for each line in <pre>
|
||||||
var nodes = md_dom.getElementsByTagName('pre');
|
nodes = md_dom.getElementsByTagName('pre');
|
||||||
for (var a = nodes.length - 1; a >= 0; a--) {
|
for (var a = nodes.length - 1; a >= 0; a--) {
|
||||||
var el = nodes[a];
|
var el = nodes[a];
|
||||||
|
|
||||||
@@ -286,15 +345,29 @@ function convert_markdown(md_text, dest_dom) {
|
|||||||
el.innerHTML = '<a href="#' + id + '">' + el.innerHTML + '</a>';
|
el.innerHTML = '<a href="#' + id + '">' + el.innerHTML + '</a>';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (md_plug['post'])
|
ext = md_plug['post'];
|
||||||
md_plug['post'][0].render(md_dom);
|
if (ext && ext[0].render)
|
||||||
|
try {
|
||||||
|
ext[0].render(md_dom);
|
||||||
|
}
|
||||||
|
catch (ex) {
|
||||||
|
md_plug_err(ex, ext[1]);
|
||||||
|
}
|
||||||
|
|
||||||
copydom(md_dom, dest_dom, 0);
|
copydom(md_dom, dest_dom, 0);
|
||||||
|
|
||||||
|
if (ext && ext[0].render2)
|
||||||
|
try {
|
||||||
|
ext[0].render2(dest_dom);
|
||||||
|
}
|
||||||
|
catch (ex) {
|
||||||
|
md_plug_err(ex, ext[1]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function init_toc() {
|
function init_toc() {
|
||||||
var loader = document.getElementById('ml');
|
var loader = ebi('ml');
|
||||||
loader.parentNode.removeChild(loader);
|
loader.parentNode.removeChild(loader);
|
||||||
|
|
||||||
var anchors = []; // list of toc entries, complex objects
|
var anchors = []; // list of toc entries, complex objects
|
||||||
|
|||||||
@@ -77,32 +77,52 @@ html.dark #mt {
|
|||||||
background: #f97;
|
background: #f97;
|
||||||
border-radius: .15em;
|
border-radius: .15em;
|
||||||
}
|
}
|
||||||
|
html.dark #save.force-save {
|
||||||
|
color: #fca;
|
||||||
|
background: #720;
|
||||||
|
}
|
||||||
#save.disabled {
|
#save.disabled {
|
||||||
opacity: .4;
|
opacity: .4;
|
||||||
}
|
}
|
||||||
|
#helpbox,
|
||||||
|
#toast {
|
||||||
|
background: #f7f7f7;
|
||||||
|
border-radius: .4em;
|
||||||
|
z-index: 9001;
|
||||||
|
}
|
||||||
#helpbox {
|
#helpbox {
|
||||||
display: none;
|
display: none;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
background: #f7f7f7;
|
|
||||||
box-shadow: 0 .5em 2em #777;
|
|
||||||
border-radius: .4em;
|
|
||||||
padding: 2em;
|
padding: 2em;
|
||||||
top: 4em;
|
top: 4em;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
box-shadow: 0 .5em 2em #777;
|
||||||
height: calc(100% - 12em);
|
height: calc(100% - 12em);
|
||||||
left: calc(50% - 15em);
|
left: calc(50% - 15em);
|
||||||
right: 0;
|
right: 0;
|
||||||
width: 30em;
|
width: 30em;
|
||||||
z-index: 9001;
|
|
||||||
}
|
}
|
||||||
#helpclose {
|
#helpclose {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
html.dark #helpbox {
|
html.dark #helpbox {
|
||||||
background: #222;
|
|
||||||
box-shadow: 0 .5em 2em #444;
|
box-shadow: 0 .5em 2em #444;
|
||||||
|
}
|
||||||
|
html.dark #helpbox,
|
||||||
|
html.dark #toast {
|
||||||
|
background: #222;
|
||||||
border: 1px solid #079;
|
border: 1px solid #079;
|
||||||
border-width: 1px 0;
|
border-width: 1px 0;
|
||||||
}
|
}
|
||||||
|
#toast {
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
padding: .6em 0;
|
||||||
|
position: fixed;
|
||||||
|
z-index: 9001;
|
||||||
|
top: 30%;
|
||||||
|
transition: opacity 0.2s ease-in-out;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
# mt {opacity: .5;top:1px}
|
# mt {opacity: .5;top:1px}
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
|
||||||
// server state
|
// server state
|
||||||
var server_md = dom_src.value;
|
var server_md = dom_src.value;
|
||||||
|
|
||||||
@@ -8,15 +11,15 @@ var js_uni_whitelist = eval('\'' + esc_uni_whitelist + '\'');
|
|||||||
|
|
||||||
|
|
||||||
// dom nodes
|
// dom nodes
|
||||||
var dom_swrap = document.getElementById('mtw');
|
var dom_swrap = ebi('mtw');
|
||||||
var dom_sbs = document.getElementById('sbs');
|
var dom_sbs = ebi('sbs');
|
||||||
var dom_nsbs = document.getElementById('nsbs');
|
var dom_nsbs = ebi('nsbs');
|
||||||
var dom_tbox = document.getElementById('toolsbox');
|
var dom_tbox = ebi('toolsbox');
|
||||||
var dom_ref = (function () {
|
var dom_ref = (function () {
|
||||||
var d = document.createElement('div');
|
var d = document.createElement('div');
|
||||||
d.setAttribute('id', 'mtr');
|
d.setAttribute('id', 'mtr');
|
||||||
dom_swrap.appendChild(d);
|
dom_swrap.appendChild(d);
|
||||||
d = document.getElementById('mtr');
|
d = ebi('mtr');
|
||||||
// hide behind the textarea (offsetTop is not computed if display:none)
|
// hide behind the textarea (offsetTop is not computed if display:none)
|
||||||
dom_src.style.zIndex = '4';
|
dom_src.style.zIndex = '4';
|
||||||
d.style.zIndex = '3';
|
d.style.zIndex = '3';
|
||||||
@@ -105,7 +108,7 @@ var draw_md = (function () {
|
|||||||
map_src = genmap(dom_ref, map_src);
|
map_src = genmap(dom_ref, map_src);
|
||||||
map_pre = genmap(dom_pre, map_pre);
|
map_pre = genmap(dom_pre, map_pre);
|
||||||
|
|
||||||
cls(document.getElementById('save'), 'disabled', src == server_md);
|
cls(ebi('save'), 'disabled', src == server_md);
|
||||||
|
|
||||||
var t1 = new Date().getTime();
|
var t1 = new Date().getTime();
|
||||||
delay = t1 - t0 > 100 ? 25 : 1;
|
delay = t1 - t0 > 100 ? 25 : 1;
|
||||||
@@ -141,7 +144,7 @@ redraw = (function () {
|
|||||||
onresize();
|
onresize();
|
||||||
}
|
}
|
||||||
function modetoggle() {
|
function modetoggle() {
|
||||||
mode = dom_nsbs.innerHTML;
|
var mode = dom_nsbs.innerHTML;
|
||||||
dom_nsbs.innerHTML = mode == 'editor' ? 'preview' : 'editor';
|
dom_nsbs.innerHTML = mode == 'editor' ? 'preview' : 'editor';
|
||||||
mode += ' single';
|
mode += ' single';
|
||||||
dom_wrap.setAttribute('class', mode);
|
dom_wrap.setAttribute('class', mode);
|
||||||
@@ -177,7 +180,7 @@ redraw = (function () {
|
|||||||
y += src.clientHeight / 2;
|
y += src.clientHeight / 2;
|
||||||
var sy1 = -1, sy2 = -1, dy1 = -1, dy2 = -1;
|
var sy1 = -1, sy2 = -1, dy1 = -1, dy2 = -1;
|
||||||
for (var a = 1; a < nlines + 1; a++) {
|
for (var a = 1; a < nlines + 1; a++) {
|
||||||
if (srcmap[a] === null || dstmap[a] === null)
|
if (srcmap[a] == null || dstmap[a] == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (srcmap[a] > y) {
|
if (srcmap[a] > y) {
|
||||||
@@ -220,14 +223,108 @@ redraw = (function () {
|
|||||||
})();
|
})();
|
||||||
|
|
||||||
|
|
||||||
|
// modification checker
|
||||||
|
function Modpoll() {
|
||||||
|
this.skip_one = true;
|
||||||
|
this.disabled = false;
|
||||||
|
|
||||||
|
this.periodic = function () {
|
||||||
|
var that = this;
|
||||||
|
setTimeout(function () {
|
||||||
|
that.periodic();
|
||||||
|
}, 1000 * md_opt.modpoll_freq);
|
||||||
|
|
||||||
|
var skip = null;
|
||||||
|
|
||||||
|
if (ebi('toast'))
|
||||||
|
skip = 'toast';
|
||||||
|
|
||||||
|
else if (this.skip_one)
|
||||||
|
skip = 'saved';
|
||||||
|
|
||||||
|
else if (this.disabled)
|
||||||
|
skip = 'disabled';
|
||||||
|
|
||||||
|
if (skip) {
|
||||||
|
console.log('modpoll skip, ' + skip);
|
||||||
|
this.skip_one = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('modpoll...');
|
||||||
|
var url = (document.location + '').split('?')[0] + '?raw&_=' + new Date().getTime();
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
xhr.modpoll = this;
|
||||||
|
xhr.open('GET', url, true);
|
||||||
|
xhr.responseType = 'text';
|
||||||
|
xhr.onreadystatechange = this.cb;
|
||||||
|
xhr.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.cb = function () {
|
||||||
|
if (this.modpoll.disabled || this.modpoll.skip_one) {
|
||||||
|
console.log('modpoll abort');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.readyState != XMLHttpRequest.DONE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (this.status !== 200) {
|
||||||
|
console.log('modpoll err ' + this.status + ": " + this.responseText);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.responseText)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var server_ref = server_md.replace(/\r/g, '');
|
||||||
|
var server_now = this.responseText.replace(/\r/g, '');
|
||||||
|
|
||||||
|
if (server_ref != server_now) {
|
||||||
|
console.log("modpoll diff |" + server_ref.length + "|, |" + server_now.length + "|");
|
||||||
|
this.modpoll.disabled = true;
|
||||||
|
var msg = [
|
||||||
|
"The document has changed on the server.<br />" +
|
||||||
|
"The changes will NOT be loaded into your editor automatically.",
|
||||||
|
|
||||||
|
"Press F5 or CTRL-R to refresh the page,<br />" +
|
||||||
|
"replacing your document with the server copy.",
|
||||||
|
|
||||||
|
"You can click this message to ignore and contnue."
|
||||||
|
];
|
||||||
|
return toast(false, "box-shadow:0 1em 2em rgba(64,64,64,0.8);font-weight:normal",
|
||||||
|
36, "<p>" + msg.join('</p>\n<p>') + '</p>');
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('modpoll eq');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (md_opt.modpoll_freq > 0)
|
||||||
|
this.periodic();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
var modpoll = new Modpoll();
|
||||||
|
|
||||||
|
|
||||||
|
window.onbeforeunload = function (e) {
|
||||||
|
if ((ebi("save").getAttribute('class') + '').indexOf('disabled') >= 0)
|
||||||
|
return; //nice (todo)
|
||||||
|
|
||||||
|
e.preventDefault(); //ff
|
||||||
|
e.returnValue = ''; //chrome
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// save handler
|
// save handler
|
||||||
function save(e) {
|
function save(e) {
|
||||||
if (e) e.preventDefault();
|
if (e) e.preventDefault();
|
||||||
var save_btn = document.getElementById("save"),
|
var save_btn = ebi("save"),
|
||||||
save_cls = save_btn.getAttribute('class') + '';
|
save_cls = save_btn.getAttribute('class') + '';
|
||||||
|
|
||||||
if (save_cls.indexOf('disabled') >= 0) {
|
if (save_cls.indexOf('disabled') >= 0) {
|
||||||
toast('font-size:2em;color:#fc6;width:9em;', 'no changes');
|
toast(true, ";font-size:2em;color:#c90", 9, "no changes");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,6 +348,8 @@ function save(e) {
|
|||||||
xhr.onreadystatechange = save_cb;
|
xhr.onreadystatechange = save_cb;
|
||||||
xhr.btn = save_btn;
|
xhr.btn = save_btn;
|
||||||
xhr.txt = txt;
|
xhr.txt = txt;
|
||||||
|
|
||||||
|
modpoll.skip_one = true; // skip one iteration while we save
|
||||||
xhr.send(fd);
|
xhr.send(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -344,23 +443,44 @@ function savechk_cb() {
|
|||||||
last_modified = this.lastmod;
|
last_modified = this.lastmod;
|
||||||
server_md = this.txt;
|
server_md = this.txt;
|
||||||
draw_md();
|
draw_md();
|
||||||
toast('font-size:6em;font-family:serif;color:#cf6;width:4em;',
|
toast(true, ";font-size:6em;font-family:serif;color:#9b4", 4,
|
||||||
'OK✔️<span style="font-size:.2em;color:#999;position:absolute">' + this.ntry + '</span>');
|
'OK✔️<span style="font-size:.2em;color:#999;position:absolute">' + this.ntry + '</span>');
|
||||||
|
|
||||||
|
modpoll.disabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function toast(style, msg) {
|
function toast(autoclose, style, width, msg) {
|
||||||
var ok = document.createElement('div');
|
var ok = ebi("toast");
|
||||||
style += 'font-weight:bold;background:#444;border-radius:.3em;padding:.6em 0;position:fixed;top:30%;left:calc(50% - 2em);text-align:center;z-index:9001;transition:opacity 0.2s ease-in-out;opacity:1';
|
if (ok)
|
||||||
|
ok.parentNode.removeChild(ok);
|
||||||
|
|
||||||
|
style = "width:" + width + "em;left:calc(50% - " + (width / 2) + "em);" + style;
|
||||||
|
ok = document.createElement('div');
|
||||||
|
ok.setAttribute('id', 'toast');
|
||||||
ok.setAttribute('style', style);
|
ok.setAttribute('style', style);
|
||||||
ok.innerHTML = msg;
|
ok.innerHTML = msg;
|
||||||
var parent = document.getElementById('m');
|
var parent = ebi('m');
|
||||||
document.documentElement.appendChild(ok);
|
document.documentElement.appendChild(ok);
|
||||||
|
|
||||||
|
var hide = function (delay) {
|
||||||
|
delay = delay || 0;
|
||||||
|
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
ok.style.opacity = 0;
|
ok.style.opacity = 0;
|
||||||
}, 500);
|
}, delay);
|
||||||
|
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
|
if (ok.parentNode)
|
||||||
ok.parentNode.removeChild(ok);
|
ok.parentNode.removeChild(ok);
|
||||||
}, 750);
|
}, delay + 250);
|
||||||
|
}
|
||||||
|
|
||||||
|
ok.onclick = function () {
|
||||||
|
hide(0);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (autoclose)
|
||||||
|
hide(500);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -623,7 +743,8 @@ function fmt_table(e) {
|
|||||||
lpipe = tab[1].indexOf('|') < tab[1].indexOf('-'),
|
lpipe = tab[1].indexOf('|') < tab[1].indexOf('-'),
|
||||||
rpipe = tab[1].lastIndexOf('|') > tab[1].lastIndexOf('-'),
|
rpipe = tab[1].lastIndexOf('|') > tab[1].lastIndexOf('-'),
|
||||||
re_lpipe = lpipe ? /^\s*\|\s*/ : /^\s*/,
|
re_lpipe = lpipe ? /^\s*\|\s*/ : /^\s*/,
|
||||||
re_rpipe = rpipe ? /\s*\|\s*$/ : /\s*$/;
|
re_rpipe = rpipe ? /\s*\|\s*$/ : /\s*$/,
|
||||||
|
ncols;
|
||||||
|
|
||||||
// the second row defines the table,
|
// the second row defines the table,
|
||||||
// need to process that first
|
// need to process that first
|
||||||
@@ -680,6 +801,7 @@ function fmt_table(e) {
|
|||||||
for (var col = 0; col < ncols; col++) {
|
for (var col = 0; col < ncols; col++) {
|
||||||
var max = 0;
|
var max = 0;
|
||||||
for (var row = 0; row < tab.length; row++)
|
for (var row = 0; row < tab.length; row++)
|
||||||
|
if (row != 1)
|
||||||
max = Math.max(max, tab[row][col].length);
|
max = Math.max(max, tab[row][col].length);
|
||||||
|
|
||||||
var s = '';
|
var s = '';
|
||||||
@@ -747,8 +869,7 @@ function mark_uni(e) {
|
|||||||
dom_tbox.setAttribute('class', '');
|
dom_tbox.setAttribute('class', '');
|
||||||
|
|
||||||
var txt = dom_src.value,
|
var txt = dom_src.value,
|
||||||
ptn = new RegExp('([^' + js_uni_whitelist + ']+)', 'g');
|
ptn = new RegExp('([^' + js_uni_whitelist + ']+)', 'g'),
|
||||||
|
|
||||||
mod = txt.replace(/\r/g, "").replace(ptn, "\u2588\u2770$1\u2771");
|
mod = txt.replace(/\r/g, "").replace(ptn, "\u2588\u2770$1\u2771");
|
||||||
|
|
||||||
if (txt == mod) {
|
if (txt == mod) {
|
||||||
@@ -785,7 +906,12 @@ function iter_uni(e) {
|
|||||||
// configure whitelist
|
// configure whitelist
|
||||||
function cfg_uni(e) {
|
function cfg_uni(e) {
|
||||||
if (e) e.preventDefault();
|
if (e) e.preventDefault();
|
||||||
esc_uni_whitelist = prompt("unicode whitelist", esc_uni_whitelist);
|
|
||||||
|
var reply = prompt("unicode whitelist", esc_uni_whitelist);
|
||||||
|
if (reply === null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
esc_uni_whitelist = reply;
|
||||||
js_uni_whitelist = eval('\'' + esc_uni_whitelist + '\'');
|
js_uni_whitelist = eval('\'' + esc_uni_whitelist + '\'');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -802,7 +928,7 @@ function cfg_uni(e) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (ev.code == "Escape" || kc == 27) {
|
if (ev.code == "Escape" || kc == 27) {
|
||||||
var d = document.getElementById('helpclose');
|
var d = ebi('helpclose');
|
||||||
if (d)
|
if (d)
|
||||||
d.click();
|
d.click();
|
||||||
}
|
}
|
||||||
@@ -859,22 +985,22 @@ function cfg_uni(e) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
document.onkeydown = keydown;
|
document.onkeydown = keydown;
|
||||||
document.getElementById('save').onclick = save;
|
ebi('save').onclick = save;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
|
||||||
document.getElementById('tools').onclick = function (e) {
|
ebi('tools').onclick = function (e) {
|
||||||
if (e) e.preventDefault();
|
if (e) e.preventDefault();
|
||||||
var is_open = dom_tbox.getAttribute('class') != 'open';
|
var is_open = dom_tbox.getAttribute('class') != 'open';
|
||||||
dom_tbox.setAttribute('class', is_open ? 'open' : '');
|
dom_tbox.setAttribute('class', is_open ? 'open' : '');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
document.getElementById('help').onclick = function (e) {
|
ebi('help').onclick = function (e) {
|
||||||
if (e) e.preventDefault();
|
if (e) e.preventDefault();
|
||||||
dom_tbox.setAttribute('class', '');
|
dom_tbox.setAttribute('class', '');
|
||||||
|
|
||||||
var dom = document.getElementById('helpbox');
|
var dom = ebi('helpbox');
|
||||||
var dtxt = dom.getElementsByTagName('textarea');
|
var dtxt = dom.getElementsByTagName('textarea');
|
||||||
if (dtxt.length > 0) {
|
if (dtxt.length > 0) {
|
||||||
convert_markdown(dtxt[0].value, dom);
|
convert_markdown(dtxt[0].value, dom);
|
||||||
@@ -882,16 +1008,16 @@ document.getElementById('help').onclick = function (e) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dom.style.display = 'block';
|
dom.style.display = 'block';
|
||||||
document.getElementById('helpclose').onclick = function () {
|
ebi('helpclose').onclick = function () {
|
||||||
dom.style.display = 'none';
|
dom.style.display = 'none';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
document.getElementById('fmt_table').onclick = fmt_table;
|
ebi('fmt_table').onclick = fmt_table;
|
||||||
document.getElementById('mark_uni').onclick = mark_uni;
|
ebi('mark_uni').onclick = mark_uni;
|
||||||
document.getElementById('iter_uni').onclick = iter_uni;
|
ebi('iter_uni').onclick = iter_uni;
|
||||||
document.getElementById('cfg_uni').onclick = cfg_uni;
|
ebi('cfg_uni').onclick = cfg_uni;
|
||||||
|
|
||||||
|
|
||||||
// blame steen
|
// blame steen
|
||||||
@@ -999,13 +1125,12 @@ action_stack = (function () {
|
|||||||
ref = newtxt;
|
ref = newtxt;
|
||||||
dbg('undos(%d) redos(%d)', hist.un.length, hist.re.length);
|
dbg('undos(%d) redos(%d)', hist.un.length, hist.re.length);
|
||||||
if (hist.un.length > 0)
|
if (hist.un.length > 0)
|
||||||
dbg(static(hist.un.slice(-1)[0]));
|
dbg(statify(hist.un.slice(-1)[0]));
|
||||||
if (hist.re.length > 0)
|
if (hist.re.length > 0)
|
||||||
dbg(static(hist.re.slice(-1)[0]));
|
dbg(statify(hist.re.slice(-1)[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
push: push,
|
|
||||||
undo: undo,
|
undo: undo,
|
||||||
redo: redo,
|
redo: redo,
|
||||||
push: schedule_push,
|
push: schedule_push,
|
||||||
@@ -1015,7 +1140,7 @@ action_stack = (function () {
|
|||||||
})();
|
})();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
document.getElementById('help').onclick = function () {
|
ebi('help').onclick = function () {
|
||||||
var c1 = getComputedStyle(dom_src).cssText.split(';');
|
var c1 = getComputedStyle(dom_src).cssText.split(';');
|
||||||
var c2 = getComputedStyle(dom_ref).cssText.split(';');
|
var c2 = getComputedStyle(dom_ref).cssText.split(';');
|
||||||
var max = Math.min(c1.length, c2.length);
|
var max = Math.min(c1.length, c2.length);
|
||||||
|
|||||||
@@ -25,7 +25,8 @@
|
|||||||
var last_modified = {{ lastmod }};
|
var last_modified = {{ lastmod }};
|
||||||
var md_opt = {
|
var md_opt = {
|
||||||
link_md_as_html: false,
|
link_md_as_html: false,
|
||||||
allow_plugins: {{ md_plug }}
|
allow_plugins: {{ md_plug }},
|
||||||
|
modpoll_freq: {{ md_chk_rate }}
|
||||||
};
|
};
|
||||||
|
|
||||||
var lightswitch = (function () {
|
var lightswitch = (function () {
|
||||||
@@ -42,6 +43,7 @@ var lightswitch = (function () {
|
|||||||
})();
|
})();
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
<script src="/.cpr/util.js"></script>
|
||||||
<script src="/.cpr/deps/easymde.js"></script>
|
<script src="/.cpr/deps/easymde.js"></script>
|
||||||
<script src="/.cpr/mde.js"></script>
|
<script src="/.cpr/mde.js"></script>
|
||||||
</body></html>
|
</body></html>
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
var dom_wrap = document.getElementById('mw');
|
"use strict";
|
||||||
var dom_nav = document.getElementById('mn');
|
|
||||||
var dom_doc = document.getElementById('m');
|
var dom_wrap = ebi('mw');
|
||||||
var dom_md = document.getElementById('mt');
|
var dom_nav = ebi('mn');
|
||||||
|
var dom_doc = ebi('m');
|
||||||
|
var dom_md = ebi('mt');
|
||||||
|
|
||||||
(function () {
|
(function () {
|
||||||
var n = document.location + '';
|
var n = document.location + '';
|
||||||
@@ -63,7 +65,7 @@ var mde = (function () {
|
|||||||
mde.codemirror.on("change", function () {
|
mde.codemirror.on("change", function () {
|
||||||
md_changed(mde);
|
md_changed(mde);
|
||||||
});
|
});
|
||||||
var loader = document.getElementById('ml');
|
var loader = ebi('ml');
|
||||||
loader.parentNode.removeChild(loader);
|
loader.parentNode.removeChild(loader);
|
||||||
return mde;
|
return mde;
|
||||||
})();
|
})();
|
||||||
@@ -213,7 +215,7 @@ function save_chk() {
|
|||||||
var ok = document.createElement('div');
|
var ok = document.createElement('div');
|
||||||
ok.setAttribute('style', 'font-size:6em;font-family:serif;font-weight:bold;color:#cf6;background:#444;border-radius:.3em;padding:.6em 0;position:fixed;top:30%;left:calc(50% - 2em);width:4em;text-align:center;z-index:9001;transition:opacity 0.2s ease-in-out;opacity:1');
|
ok.setAttribute('style', 'font-size:6em;font-family:serif;font-weight:bold;color:#cf6;background:#444;border-radius:.3em;padding:.6em 0;position:fixed;top:30%;left:calc(50% - 2em);width:4em;text-align:center;z-index:9001;transition:opacity 0.2s ease-in-out;opacity:1');
|
||||||
ok.innerHTML = 'OK✔️';
|
ok.innerHTML = 'OK✔️';
|
||||||
var parent = document.getElementById('m');
|
var parent = ebi('m');
|
||||||
document.documentElement.appendChild(ok);
|
document.documentElement.appendChild(ok);
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
ok.style.opacity = 0;
|
ok.style.opacity = 0;
|
||||||
|
|||||||
@@ -1,61 +1,6 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
// error handler for mobile devices
|
window.onerror = vis_exh;
|
||||||
function hcroak(msg) {
|
|
||||||
document.body.innerHTML = msg;
|
|
||||||
window.onerror = undefined;
|
|
||||||
throw 'fatal_err';
|
|
||||||
}
|
|
||||||
function croak(msg) {
|
|
||||||
document.body.textContent = msg;
|
|
||||||
window.onerror = undefined;
|
|
||||||
throw msg;
|
|
||||||
}
|
|
||||||
function esc(txt) {
|
|
||||||
return txt.replace(/[&"<>]/g, function (c) {
|
|
||||||
return {
|
|
||||||
'&': '&',
|
|
||||||
'"': '"',
|
|
||||||
'<': '<',
|
|
||||||
'>': '>'
|
|
||||||
}[c];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
window.onerror = function (msg, url, lineNo, columnNo, error) {
|
|
||||||
window.onerror = undefined;
|
|
||||||
var html = ['<h1>you hit a bug!</h1><p>please screenshot this error and send me a copy arigathanks gozaimuch (ed/irc.rizon.net or ed#2644)</p><p>',
|
|
||||||
esc(String(msg)), '</p><p>', esc(url + ' @' + lineNo + ':' + columnNo), '</p>'];
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
var find = ['desc', 'stack', 'trace'];
|
|
||||||
for (var a = 0; a < find.length; a++)
|
|
||||||
if (String(error[find[a]]) !== 'undefined')
|
|
||||||
html.push('<h2>' + find[a] + '</h2>' +
|
|
||||||
esc(String(error[find[a]])).replace(/\n/g, '<br />\n'));
|
|
||||||
}
|
|
||||||
document.body.style.fontSize = '0.8em';
|
|
||||||
document.body.style.padding = '0 1em 1em 1em';
|
|
||||||
hcroak(html.join('\n'));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// https://stackoverflow.com/a/950146
|
|
||||||
function import_js(url, cb) {
|
|
||||||
var head = document.head || document.getElementsByTagName('head')[0];
|
|
||||||
var script = document.createElement('script');
|
|
||||||
script.type = 'text/javascript';
|
|
||||||
script.src = url;
|
|
||||||
|
|
||||||
script.onreadystatechange = cb;
|
|
||||||
script.onload = cb;
|
|
||||||
|
|
||||||
head.appendChild(script);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function o(id) {
|
|
||||||
return document.getElementById(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
(function () {
|
(function () {
|
||||||
@@ -88,12 +33,12 @@ function goto(dest) {
|
|||||||
for (var a = obj.length - 1; a >= 0; a--)
|
for (var a = obj.length - 1; a >= 0; a--)
|
||||||
obj[a].classList.remove('act');
|
obj[a].classList.remove('act');
|
||||||
|
|
||||||
var obj = document.querySelectorAll('#ops>a');
|
obj = document.querySelectorAll('#ops>a');
|
||||||
for (var a = obj.length - 1; a >= 0; a--)
|
for (var a = obj.length - 1; a >= 0; a--)
|
||||||
obj[a].classList.remove('act');
|
obj[a].classList.remove('act');
|
||||||
|
|
||||||
if (dest) {
|
if (dest) {
|
||||||
document.getElementById('op_' + dest).classList.add('act');
|
ebi('op_' + dest).classList.add('act');
|
||||||
document.querySelector('#ops>a[data-dest=' + dest + ']').classList.add('act');
|
document.querySelector('#ops>a[data-dest=' + dest + ']').classList.add('act');
|
||||||
|
|
||||||
var fn = window['goto_' + dest];
|
var fn = window['goto_' + dest];
|
||||||
@@ -121,7 +66,7 @@ function goto_up2k() {
|
|||||||
if (op !== null && op !== '.')
|
if (op !== null && op !== '.')
|
||||||
goto(op);
|
goto(op);
|
||||||
}
|
}
|
||||||
document.getElementById('ops').style.display = 'block';
|
ebi('ops').style.display = 'block';
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
|
||||||
@@ -150,21 +95,21 @@ function up2k_init(have_crypto) {
|
|||||||
|
|
||||||
// show modal message
|
// show modal message
|
||||||
function showmodal(msg) {
|
function showmodal(msg) {
|
||||||
o('u2notbtn').innerHTML = msg;
|
ebi('u2notbtn').innerHTML = msg;
|
||||||
o('u2btn').style.display = 'none';
|
ebi('u2btn').style.display = 'none';
|
||||||
o('u2notbtn').style.display = 'block';
|
ebi('u2notbtn').style.display = 'block';
|
||||||
o('u2conf').style.opacity = '0.5';
|
ebi('u2conf').style.opacity = '0.5';
|
||||||
}
|
}
|
||||||
|
|
||||||
// hide modal message
|
// hide modal message
|
||||||
function unmodal() {
|
function unmodal() {
|
||||||
o('u2notbtn').style.display = 'none';
|
ebi('u2notbtn').style.display = 'none';
|
||||||
o('u2btn').style.display = 'block';
|
ebi('u2btn').style.display = 'block';
|
||||||
o('u2conf').style.opacity = '1';
|
ebi('u2conf').style.opacity = '1';
|
||||||
o('u2notbtn').innerHTML = '';
|
ebi('u2notbtn').innerHTML = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
var post_url = o('op_bup').getElementsByTagName('form')[0].getAttribute('action');
|
var post_url = ebi('op_bup').getElementsByTagName('form')[0].getAttribute('action');
|
||||||
if (post_url && post_url.charAt(post_url.length - 1) !== '/')
|
if (post_url && post_url.charAt(post_url.length - 1) !== '/')
|
||||||
post_url += '/';
|
post_url += '/';
|
||||||
|
|
||||||
@@ -181,25 +126,25 @@ function up2k_init(have_crypto) {
|
|||||||
import_js('/.cpr/deps/sha512.js', unmodal);
|
import_js('/.cpr/deps/sha512.js', unmodal);
|
||||||
|
|
||||||
if (is_https)
|
if (is_https)
|
||||||
o('u2foot').innerHTML = shame + ' so <em>this</em> uploader will do like 500kB/s at best';
|
ebi('u2foot').innerHTML = shame + ' so <em>this</em> uploader will do like 500kB/s at best';
|
||||||
else
|
else
|
||||||
o('u2foot').innerHTML = 'seems like ' + shame + ' so do that if you want more performance';
|
ebi('u2foot').innerHTML = 'seems like ' + shame + ' so do that if you want more performance';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
// show uploader if the user only has write-access
|
// show uploader if the user only has write-access
|
||||||
if (!o('files'))
|
if (!ebi('files'))
|
||||||
goto('up2k');
|
goto('up2k');
|
||||||
|
|
||||||
// shows or clears an error message in the basic uploader ui
|
// shows or clears an error message in the basic uploader ui
|
||||||
function setmsg(msg) {
|
function setmsg(msg) {
|
||||||
if (msg !== undefined) {
|
if (msg !== undefined) {
|
||||||
o('u2err').setAttribute('class', 'err');
|
ebi('u2err').setAttribute('class', 'err');
|
||||||
o('u2err').innerHTML = msg;
|
ebi('u2err').innerHTML = msg;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
o('u2err').setAttribute('class', '');
|
ebi('u2err').setAttribute('class', '');
|
||||||
o('u2err').innerHTML = '';
|
ebi('u2err').innerHTML = '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,7 +155,7 @@ function up2k_init(have_crypto) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle user intent to use the basic uploader instead
|
// handle user intent to use the basic uploader instead
|
||||||
o('u2nope').onclick = function (e) {
|
ebi('u2nope').onclick = function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setmsg('');
|
setmsg('');
|
||||||
goto('bup');
|
goto('bup');
|
||||||
@@ -229,9 +174,9 @@ function up2k_init(have_crypto) {
|
|||||||
function cfg_get(name) {
|
function cfg_get(name) {
|
||||||
var val = localStorage.getItem(name);
|
var val = localStorage.getItem(name);
|
||||||
if (val === null)
|
if (val === null)
|
||||||
return parseInt(o(name).value);
|
return parseInt(ebi(name).value);
|
||||||
|
|
||||||
o(name).value = val;
|
ebi(name).value = val;
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,7 +187,7 @@ function up2k_init(have_crypto) {
|
|||||||
else
|
else
|
||||||
val = (val == '1');
|
val = (val == '1');
|
||||||
|
|
||||||
o(name).checked = val;
|
ebi(name).checked = val;
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,7 +195,7 @@ function up2k_init(have_crypto) {
|
|||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
name, val ? '1' : '0');
|
name, val ? '1' : '0');
|
||||||
|
|
||||||
o(name).checked = val;
|
ebi(name).checked = val;
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,9 +229,9 @@ function up2k_init(have_crypto) {
|
|||||||
return un2k("this is the basic uploader; up2k needs at least<br />chrome 21 // firefox 13 // edge 12 // opera 12 // safari 5.1");
|
return un2k("this is the basic uploader; up2k needs at least<br />chrome 21 // firefox 13 // edge 12 // opera 12 // safari 5.1");
|
||||||
|
|
||||||
function nav() {
|
function nav() {
|
||||||
o('file' + fdom_ctr).click();
|
ebi('file' + fdom_ctr).click();
|
||||||
}
|
}
|
||||||
o('u2btn').addEventListener('click', nav, false);
|
ebi('u2btn').addEventListener('click', nav, false);
|
||||||
|
|
||||||
function ondrag(ev) {
|
function ondrag(ev) {
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
@@ -294,8 +239,8 @@ function up2k_init(have_crypto) {
|
|||||||
ev.dataTransfer.dropEffect = 'copy';
|
ev.dataTransfer.dropEffect = 'copy';
|
||||||
ev.dataTransfer.effectAllowed = 'copy';
|
ev.dataTransfer.effectAllowed = 'copy';
|
||||||
}
|
}
|
||||||
o('u2btn').addEventListener('dragover', ondrag, false);
|
ebi('u2btn').addEventListener('dragover', ondrag, false);
|
||||||
o('u2btn').addEventListener('dragenter', ondrag, false);
|
ebi('u2btn').addEventListener('dragenter', ondrag, false);
|
||||||
|
|
||||||
function gotfile(ev) {
|
function gotfile(ev) {
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
@@ -357,7 +302,7 @@ function up2k_init(have_crypto) {
|
|||||||
var tr = document.createElement('tr');
|
var tr = document.createElement('tr');
|
||||||
tr.innerHTML = '<td id="f{0}n"></td><td id="f{0}t">hashing</td><td id="f{0}p" class="prog"></td>'.format(st.files.length);
|
tr.innerHTML = '<td id="f{0}n"></td><td id="f{0}t">hashing</td><td id="f{0}p" class="prog"></td>'.format(st.files.length);
|
||||||
tr.getElementsByTagName('td')[0].textContent = entry.name;
|
tr.getElementsByTagName('td')[0].textContent = entry.name;
|
||||||
o('u2tab').appendChild(tr);
|
ebi('u2tab').appendChild(tr);
|
||||||
|
|
||||||
st.files.push(entry);
|
st.files.push(entry);
|
||||||
st.todo.hash.push(entry);
|
st.todo.hash.push(entry);
|
||||||
@@ -374,14 +319,14 @@ function up2k_init(have_crypto) {
|
|||||||
alert(msg);
|
alert(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
o('u2btn').addEventListener('drop', gotfile, false);
|
ebi('u2btn').addEventListener('drop', gotfile, false);
|
||||||
|
|
||||||
function more_one_file() {
|
function more_one_file() {
|
||||||
fdom_ctr++;
|
fdom_ctr++;
|
||||||
var elm = document.createElement('div')
|
var elm = document.createElement('div')
|
||||||
elm.innerHTML = '<input id="file{0}" type="file" name="file{0}[]" multiple="multiple" />'.format(fdom_ctr);
|
elm.innerHTML = '<input id="file{0}" type="file" name="file{0}[]" multiple="multiple" />'.format(fdom_ctr);
|
||||||
o('u2form').appendChild(elm);
|
ebi('u2form').appendChild(elm);
|
||||||
o('file' + fdom_ctr).addEventListener('change', gotfile, false);
|
ebi('file' + fdom_ctr).addEventListener('change', gotfile, false);
|
||||||
}
|
}
|
||||||
more_one_file();
|
more_one_file();
|
||||||
|
|
||||||
@@ -451,17 +396,6 @@ function up2k_init(have_crypto) {
|
|||||||
/// hashing
|
/// hashing
|
||||||
//
|
//
|
||||||
|
|
||||||
// https://gist.github.com/jonleighton/958841
|
|
||||||
function buf2b64_maybe_fucky(buffer) {
|
|
||||||
var ret = '';
|
|
||||||
var view = new DataView(buffer);
|
|
||||||
for (var i = 0; i < view.byteLength; i++) {
|
|
||||||
ret += String.fromCharCode(view.getUint8(i));
|
|
||||||
}
|
|
||||||
return window.btoa(ret).replace(
|
|
||||||
/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://gist.github.com/jonleighton/958841
|
// https://gist.github.com/jonleighton/958841
|
||||||
function buf2b64(arrayBuffer) {
|
function buf2b64(arrayBuffer) {
|
||||||
var base64 = '';
|
var base64 = '';
|
||||||
@@ -502,20 +436,6 @@ function up2k_init(have_crypto) {
|
|||||||
return base64;
|
return base64;
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest
|
|
||||||
function buf2hex(buffer) {
|
|
||||||
var hexCodes = [];
|
|
||||||
var view = new DataView(buffer);
|
|
||||||
for (var i = 0; i < view.byteLength; i += 4) {
|
|
||||||
var value = view.getUint32(i) // 4 bytes per iter
|
|
||||||
var stringValue = value.toString(16) // doesn't pad
|
|
||||||
var padding = '00000000'
|
|
||||||
var paddedValue = (padding + stringValue).slice(-padding.length)
|
|
||||||
hexCodes.push(paddedValue);
|
|
||||||
}
|
|
||||||
return hexCodes.join("");
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_chunksize(filesize) {
|
function get_chunksize(filesize) {
|
||||||
var chunksize = 1024 * 1024;
|
var chunksize = 1024 * 1024;
|
||||||
var stepsize = 512 * 1024;
|
var stepsize = 512 * 1024;
|
||||||
@@ -602,7 +522,7 @@ function up2k_init(have_crypto) {
|
|||||||
pb_html += '<div id="f{0}p{1}" style="width:{2}%"><div></div></div>'.format(
|
pb_html += '<div id="f{0}p{1}" style="width:{2}%"><div></div></div>'.format(
|
||||||
t.n, a, pb_perc);
|
t.n, a, pb_perc);
|
||||||
|
|
||||||
o('f{0}p'.format(t.n)).innerHTML = pb_html;
|
ebi('f{0}p'.format(t.n)).innerHTML = pb_html;
|
||||||
|
|
||||||
var reader = new FileReader();
|
var reader = new FileReader();
|
||||||
|
|
||||||
@@ -677,7 +597,7 @@ function up2k_init(have_crypto) {
|
|||||||
alert('{0} ms, {1} MB/s\n'.format(t.t2 - t.t1, spd.toFixed(3)) + t.hash.join('\n'));
|
alert('{0} ms, {1} MB/s\n'.format(t.t2 - t.t1, spd.toFixed(3)) + t.hash.join('\n'));
|
||||||
}
|
}
|
||||||
|
|
||||||
o('f{0}t'.format(t.n)).innerHTML = 'connecting';
|
ebi('f{0}t'.format(t.n)).innerHTML = 'connecting';
|
||||||
st.busy.hash.splice(st.busy.hash.indexOf(t), 1);
|
st.busy.hash.splice(st.busy.hash.indexOf(t), 1);
|
||||||
st.todo.handshake.push(t);
|
st.todo.handshake.push(t);
|
||||||
};
|
};
|
||||||
@@ -706,7 +626,7 @@ function up2k_init(have_crypto) {
|
|||||||
if (response.name !== t.name) {
|
if (response.name !== t.name) {
|
||||||
// file exists; server renamed us
|
// file exists; server renamed us
|
||||||
t.name = response.name;
|
t.name = response.name;
|
||||||
o('f{0}n'.format(t.n)).textContent = t.name;
|
ebi('f{0}n'.format(t.n)).textContent = t.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
t.postlist = [];
|
t.postlist = [];
|
||||||
@@ -736,13 +656,13 @@ function up2k_init(have_crypto) {
|
|||||||
msg = 'uploading';
|
msg = 'uploading';
|
||||||
done = false;
|
done = false;
|
||||||
}
|
}
|
||||||
o('f{0}t'.format(t.n)).innerHTML = msg;
|
ebi('f{0}t'.format(t.n)).innerHTML = msg;
|
||||||
st.busy.handshake.splice(st.busy.handshake.indexOf(t), 1);
|
st.busy.handshake.splice(st.busy.handshake.indexOf(t), 1);
|
||||||
|
|
||||||
if (done) {
|
if (done) {
|
||||||
var spd1 = (t.size / ((t.t2 - t.t1) / 1000.)) / (1024 * 1024.);
|
var spd1 = (t.size / ((t.t2 - t.t1) / 1000.)) / (1024 * 1024.);
|
||||||
var spd2 = (t.size / ((t.t3 - t.t2) / 1000.)) / (1024 * 1024.);
|
var spd2 = (t.size / ((t.t3 - t.t2) / 1000.)) / (1024 * 1024.);
|
||||||
o('f{0}p'.format(t.n)).innerHTML = 'hash {0}, up {1} MB/s'.format(
|
ebi('f{0}p'.format(t.n)).innerHTML = 'hash {0}, up {1} MB/s'.format(
|
||||||
spd1.toFixed(2), spd2.toFixed(2));
|
spd1.toFixed(2), spd2.toFixed(2));
|
||||||
}
|
}
|
||||||
tasker();
|
tasker();
|
||||||
@@ -803,7 +723,7 @@ function up2k_init(have_crypto) {
|
|||||||
t.postlist.splice(t.postlist.indexOf(npart), 1);
|
t.postlist.splice(t.postlist.indexOf(npart), 1);
|
||||||
if (t.postlist.length == 0) {
|
if (t.postlist.length == 0) {
|
||||||
t.t3 = new Date().getTime();
|
t.t3 = new Date().getTime();
|
||||||
o('f{0}t'.format(t.n)).innerHTML = 'verifying';
|
ebi('f{0}t'.format(t.n)).innerHTML = 'verifying';
|
||||||
st.todo.handshake.push(t);
|
st.todo.handshake.push(t);
|
||||||
}
|
}
|
||||||
tasker();
|
tasker();
|
||||||
@@ -834,7 +754,7 @@ function up2k_init(have_crypto) {
|
|||||||
//
|
//
|
||||||
|
|
||||||
function prog(nfile, nchunk, color, percent) {
|
function prog(nfile, nchunk, color, percent) {
|
||||||
var n1 = o('f{0}p{1}'.format(nfile, nchunk));
|
var n1 = ebi('f{0}p{1}'.format(nfile, nchunk));
|
||||||
var n2 = n1.getElementsByTagName('div')[0];
|
var n2 = n1.getElementsByTagName('div')[0];
|
||||||
if (percent === undefined) {
|
if (percent === undefined) {
|
||||||
n1.style.background = color;
|
n1.style.background = color;
|
||||||
@@ -857,7 +777,7 @@ function up2k_init(have_crypto) {
|
|||||||
dir.preventDefault();
|
dir.preventDefault();
|
||||||
} catch (ex) { }
|
} catch (ex) { }
|
||||||
|
|
||||||
var obj = o('nthread');
|
var obj = ebi('nthread');
|
||||||
if (dir.target) {
|
if (dir.target) {
|
||||||
obj.style.background = '#922';
|
obj.style.background = '#922';
|
||||||
var v = Math.floor(parseInt(obj.value));
|
var v = Math.floor(parseInt(obj.value));
|
||||||
@@ -892,19 +812,19 @@ function up2k_init(have_crypto) {
|
|||||||
this.click();
|
this.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
o('nthread_add').onclick = function (ev) {
|
ebi('nthread_add').onclick = function (ev) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
bumpthread(1);
|
bumpthread(1);
|
||||||
};
|
};
|
||||||
o('nthread_sub').onclick = function (ev) {
|
ebi('nthread_sub').onclick = function (ev) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
bumpthread(-1);
|
bumpthread(-1);
|
||||||
};
|
};
|
||||||
|
|
||||||
o('nthread').addEventListener('input', bumpthread, false);
|
ebi('nthread').addEventListener('input', bumpthread, false);
|
||||||
o('multitask').addEventListener('click', tgl_multitask, false);
|
ebi('multitask').addEventListener('click', tgl_multitask, false);
|
||||||
|
|
||||||
var nodes = o('u2conf').getElementsByTagName('a');
|
var nodes = ebi('u2conf').getElementsByTagName('a');
|
||||||
for (var a = nodes.length - 1; a >= 0; a--)
|
for (var a = nodes.length - 1; a >= 0; a--)
|
||||||
nodes[a].addEventListener('touchend', nop, false);
|
nodes[a].addEventListener('touchend', nop, false);
|
||||||
|
|
||||||
|
|||||||
109
copyparty/web/util.js
Normal file
109
copyparty/web/util.js
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
// error handler for mobile devices
|
||||||
|
function hcroak(msg) {
|
||||||
|
document.body.innerHTML = msg;
|
||||||
|
window.onerror = undefined;
|
||||||
|
throw 'fatal_err';
|
||||||
|
}
|
||||||
|
function croak(msg) {
|
||||||
|
document.body.textContent = msg;
|
||||||
|
window.onerror = undefined;
|
||||||
|
throw msg;
|
||||||
|
}
|
||||||
|
function esc(txt) {
|
||||||
|
return txt.replace(/[&"<>]/g, function (c) {
|
||||||
|
return {
|
||||||
|
'&': '&',
|
||||||
|
'"': '"',
|
||||||
|
'<': '<',
|
||||||
|
'>': '>'
|
||||||
|
}[c];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function vis_exh(msg, url, lineNo, columnNo, error) {
|
||||||
|
window.onerror = undefined;
|
||||||
|
var html = ['<h1>you hit a bug!</h1><p>please screenshot this error and send me a copy arigathanks gozaimuch (ed/irc.rizon.net or ed#2644)</p><p>',
|
||||||
|
esc(String(msg)), '</p><p>', esc(url + ' @' + lineNo + ':' + columnNo), '</p>'];
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
var find = ['desc', 'stack', 'trace'];
|
||||||
|
for (var a = 0; a < find.length; a++)
|
||||||
|
if (String(error[find[a]]) !== 'undefined')
|
||||||
|
html.push('<h2>' + find[a] + '</h2>' +
|
||||||
|
esc(String(error[find[a]])).replace(/\n/g, '<br />\n'));
|
||||||
|
}
|
||||||
|
document.body.style.fontSize = '0.8em';
|
||||||
|
document.body.style.padding = '0 1em 1em 1em';
|
||||||
|
hcroak(html.join('\n'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function ebi(id) {
|
||||||
|
return document.getElementById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith
|
||||||
|
if (!String.prototype.endsWith) {
|
||||||
|
String.prototype.endsWith = function (search, this_len) {
|
||||||
|
if (this_len === undefined || this_len > this.length) {
|
||||||
|
this_len = this.length;
|
||||||
|
}
|
||||||
|
return this.substring(this_len - search.length, this_len) === search;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (!String.startsWith) {
|
||||||
|
String.prototype.startsWith = function (s, i) {
|
||||||
|
i = i > 0 ? i | 0 : 0;
|
||||||
|
return this.substring(i, i + s.length) === s;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// https://stackoverflow.com/a/950146
|
||||||
|
function import_js(url, cb) {
|
||||||
|
var head = document.head || document.getElementsByTagName('head')[0];
|
||||||
|
var script = document.createElement('script');
|
||||||
|
script.type = 'text/javascript';
|
||||||
|
script.src = url;
|
||||||
|
|
||||||
|
script.onreadystatechange = cb;
|
||||||
|
script.onload = cb;
|
||||||
|
|
||||||
|
head.appendChild(script);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function sortTable(table, col) {
|
||||||
|
var tb = table.tBodies[0], // use `<tbody>` to ignore `<thead>` and `<tfoot>` rows
|
||||||
|
th = table.tHead.rows[0].cells,
|
||||||
|
tr = Array.prototype.slice.call(tb.rows, 0),
|
||||||
|
i, reverse = th[col].className == 'sort1' ? -1 : 1;
|
||||||
|
for (var a = 0, thl = th.length; a < thl; a++)
|
||||||
|
th[a].className = '';
|
||||||
|
th[col].className = 'sort' + reverse;
|
||||||
|
var stype = th[col].getAttribute('sort');
|
||||||
|
tr = tr.sort(function (a, b) {
|
||||||
|
var v1 = a.cells[col].textContent.trim();
|
||||||
|
var v2 = b.cells[col].textContent.trim();
|
||||||
|
if (stype == 'int') {
|
||||||
|
v1 = parseInt(v1.replace(/,/g, ''));
|
||||||
|
v2 = parseInt(v2.replace(/,/g, ''));
|
||||||
|
return reverse * (v1 - v2);
|
||||||
|
}
|
||||||
|
return reverse * (v1.localeCompare(v2));
|
||||||
|
});
|
||||||
|
for (i = 0; i < tr.length; ++i) tb.appendChild(tr[i]);
|
||||||
|
}
|
||||||
|
function makeSortable(table) {
|
||||||
|
var th = table.tHead, i;
|
||||||
|
th && (th = th.rows[0]) && (th = th.cells);
|
||||||
|
if (th) i = th.length;
|
||||||
|
else return; // if no `<thead>` then do nothing
|
||||||
|
while (--i >= 0) (function (i) {
|
||||||
|
th[i].onclick = function () {
|
||||||
|
sortTable(table, i);
|
||||||
|
};
|
||||||
|
}(i));
|
||||||
|
}
|
||||||
@@ -19,6 +19,8 @@ set -e
|
|||||||
# -rwxr-xr-x 0 ed ed 183808 Nov 19 00:43 copyparty-extras/sfx-lite/copyparty-sfx.py
|
# -rwxr-xr-x 0 ed ed 183808 Nov 19 00:43 copyparty-extras/sfx-lite/copyparty-sfx.py
|
||||||
|
|
||||||
|
|
||||||
|
command -v gtar && tar() { gtar "$@"; }
|
||||||
|
command -v gsed && sed() { gsed "$@"; }
|
||||||
td="$(mktemp -d)"
|
td="$(mktemp -d)"
|
||||||
od="$(pwd)"
|
od="$(pwd)"
|
||||||
cd "$td"
|
cd "$td"
|
||||||
@@ -86,7 +88,7 @@ rm -rf copyparty-{0..9}*.*.*{0..9}
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# and include the repacker itself too
|
# and include the repacker itself too
|
||||||
cp -pv "$od/$0" copyparty-extras/
|
cp -pv "$od/$0" copyparty-extras/
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -94,8 +94,39 @@ cd sfx
|
|||||||
rm -f ../tar
|
rm -f ../tar
|
||||||
}
|
}
|
||||||
|
|
||||||
ver="$(awk '/^VERSION *= \(/ {
|
ver=
|
||||||
gsub(/[^0-9,]/,""); gsub(/,/,"."); print; exit}' < ../copyparty/__version__.py)"
|
git describe --tags >/dev/null 2>/dev/null && {
|
||||||
|
git_ver="$(git describe --tags)"; # v0.5.5-2-gb164aa0
|
||||||
|
ver="$(printf '%s\n' "$git_ver" | sed -r 's/^v//; s/-g?/./g')";
|
||||||
|
t_ver=
|
||||||
|
|
||||||
|
printf '%s\n' "$git_ver" | grep -qE '^v[0-9\.]+$' && {
|
||||||
|
# short format (exact version number)
|
||||||
|
t_ver="$(printf '%s\n' "$ver" | sed -r 's/\./, /g')";
|
||||||
|
}
|
||||||
|
|
||||||
|
printf '%s\n' "$git_ver" | grep -qE '^v[0-9\.]+-[0-9]+-g[0-9a-f]+$' && {
|
||||||
|
# long format (unreleased commit)
|
||||||
|
t_ver="$(printf '%s\n' "$ver" | sed -r 's/\./, /g; s/(.*) (.*)/\1 "\2"/')"
|
||||||
|
}
|
||||||
|
|
||||||
|
[ -z "$t_ver" ] && {
|
||||||
|
printf 'unexpected git version format: [%s]\n' "$git_ver"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
dt="$(git log -1 --format=%cd --date=format:'%Y, %m, %d')"
|
||||||
|
printf 'git %3s: \033[36m%s\033[0m\n' ver "$ver" dt "$dt"
|
||||||
|
sed -ri '
|
||||||
|
s/^(VERSION =)(.*)/#\1\2\n\1 ('"$t_ver"')/;
|
||||||
|
s/^(S_VERSION =)(.*)/#\1\2\n\1 "'"$ver"'"/;
|
||||||
|
s/^(BUILD_DT =)(.*)/#\1\2\n\1 ('"$dt"')/;
|
||||||
|
' copyparty/__version__.py
|
||||||
|
}
|
||||||
|
|
||||||
|
[ -z "$ver" ] &&
|
||||||
|
ver="$(awk '/^VERSION *= \(/ {
|
||||||
|
gsub(/[^0-9,]/,""); gsub(/,/,"."); print; exit}' < copyparty/__version__.py)"
|
||||||
|
|
||||||
ts=$(date -u +%s)
|
ts=$(date -u +%s)
|
||||||
hts=$(date -u +%Y-%m%d-%H%M%S) # --date=@$ts (thx osx)
|
hts=$(date -u +%Y-%m%d-%H%M%S) # --date=@$ts (thx osx)
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ this one becomes a hyperlink to ./except/ thanks to
|
|||||||
|
|
||||||
it is a passthrough to the markdown extension api, see https://marked.js.org/using_pro
|
it is a passthrough to the markdown extension api, see https://marked.js.org/using_pro
|
||||||
|
|
||||||
|
in addition to the markdown extension functions, `ctor` will be called on document init
|
||||||
|
|
||||||
|
|
||||||
### these/
|
### these/
|
||||||
and this one becomes ./except/these/
|
and this one becomes ./except/these/
|
||||||
@@ -36,6 +38,13 @@ whic hshoud be ./except/also-this.md
|
|||||||
# ok
|
# ok
|
||||||
now for another extension type, `copyparty_post` which is called to manipulate the generated dom instead
|
now for another extension type, `copyparty_post` which is called to manipulate the generated dom instead
|
||||||
|
|
||||||
|
`copyparty_post` can have the following functions, all optional
|
||||||
|
* `ctor` is called on document init
|
||||||
|
* `render` is called when the dom is done but still in-memory
|
||||||
|
* `render2` is called with the live browser dom as-displayed
|
||||||
|
|
||||||
|
## post example
|
||||||
|
|
||||||
the values in the `ex:` columns are linkified to `example.com/$value`
|
the values in the `ex:` columns are linkified to `example.com/$value`
|
||||||
|
|
||||||
| ex:foo | bar | ex:baz |
|
| ex:foo | bar | ex:baz |
|
||||||
@@ -43,6 +52,8 @@ the values in the `ex:` columns are linkified to `example.com/$value`
|
|||||||
| asdf | nice | fgsfds |
|
| asdf | nice | fgsfds |
|
||||||
| more one row | hi hello | aaa |
|
| more one row | hi hello | aaa |
|
||||||
|
|
||||||
|
and the table can be sorted by clicking the headers
|
||||||
|
|
||||||
the difference is that with `copyparty_pre` you'll probably break various copyparty features but if you use `copyparty_post` then future copyparty versions will probably break you
|
the difference is that with `copyparty_pre` you'll probably break various copyparty features but if you use `copyparty_post` then future copyparty versions will probably break you
|
||||||
|
|
||||||
|
|
||||||
@@ -123,5 +134,8 @@ render(dom) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
render2(dom) {
|
||||||
|
window.makeSortable(dom.getElementsByTagName('table')[0]);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
Reference in New Issue
Block a user