markdown-editor joke stopped being a joke...

This commit is contained in:
ed 2020-04-30 00:47:28 +02:00
parent 334c07cc0c
commit bef2e92cef
12 changed files with 199 additions and 18 deletions

View file

@ -73,7 +73,7 @@ class MpWorker(object):
if PY2: if PY2:
sck = pickle.loads(sck) # nosec sck = pickle.loads(sck) # nosec
self.log(str(addr), "-" * 4 + "C-qpop") self.log("%s %s" % addr, "-" * 4 + "C-qpop")
self.httpsrv.accept(sck, addr) self.httpsrv.accept(sck, addr)
with self.mutex: with self.mutex:

View file

@ -28,7 +28,7 @@ class BrokerThr(object):
def put(self, want_retval, dest, *args): def put(self, want_retval, dest, *args):
if dest == "httpconn": if dest == "httpconn":
sck, addr = args sck, addr = args
self.log(str(addr), "-" * 4 + "C-qpop") self.log("%s %s" % addr, "-" * 4 + "C-qpop")
self.httpsrv.accept(sck, addr) self.httpsrv.accept(sck, addr)
else: else:

View file

@ -708,7 +708,14 @@ class HttpCli(object):
def tx_md(self, fs_path): def tx_md(self, fs_path):
logmsg = "{:4} {} ".format("", self.req) logmsg = "{:4} {} ".format("", self.req)
html_path = os.path.join(E.mod, "web/md.html") if "edit" in self.uparam:
html_path = "web/mde.html"
template = self.conn.tpl_mde
else:
html_path = "web/md.html"
template = self.conn.tpl_md
html_path = os.path.join(E.mod, html_path)
st = os.stat(fsenc(fs_path)) st = os.stat(fsenc(fs_path))
sz_md = st.st_size sz_md = st.st_size
@ -726,7 +733,7 @@ class HttpCli(object):
"title": html_escape(self.vpath, quote=False), "title": html_escape(self.vpath, quote=False),
"md": "", "md": "",
} }
sz_html = len(self.conn.tpl_md.render(**targs).encode("utf-8")) sz_html = len(template.render(**targs).encode("utf-8"))
self.send_headers(sz_html + sz_md, status) self.send_headers(sz_html + sz_md, status)
logmsg += str(status) logmsg += str(status)
@ -738,7 +745,7 @@ class HttpCli(object):
md = f.read() md = f.read()
targs["md"] = md.decode("utf-8", "replace") targs["md"] = md.decode("utf-8", "replace")
html = self.conn.tpl_md.render(**targs).encode("utf-8") html = template.render(**targs).encode("utf-8")
try: try:
self.s.sendall(html) self.s.sendall(html)
except: except:

View file

@ -36,6 +36,7 @@ class HttpConn(object):
self.tpl_browser = env.get_template("browser.html") self.tpl_browser = env.get_template("browser.html")
self.tpl_msg = env.get_template("msg.html") self.tpl_msg = env.get_template("msg.html")
self.tpl_md = env.get_template("md.html") self.tpl_md = env.get_template("md.html")
self.tpl_mde = env.get_template("mde.html")
def respath(self, res_name): def respath(self, res_name):
return os.path.join(E.mod, "web", res_name) return os.path.join(E.mod, "web", res_name)

View file

@ -38,7 +38,7 @@ class HttpSrv(object):
def accept(self, sck, addr): def accept(self, sck, addr):
"""takes an incoming tcp connection and creates a thread to handle it""" """takes an incoming tcp connection and creates a thread to handle it"""
self.log(str(addr), "-" * 5 + "C-cthr") self.log("%s %s" % addr, "-" * 5 + "C-cthr")
thr = threading.Thread(target=self.thr_client, args=(sck, addr)) thr = threading.Thread(target=self.thr_client, args=(sck, addr))
thr.daemon = True thr.daemon = True
thr.start() thr.start()
@ -66,16 +66,18 @@ class HttpSrv(object):
thr.start() thr.start()
try: try:
self.log(str(addr), "-" * 6 + "C-crun") self.log("%s %s" % addr, "-" * 6 + "C-crun")
cli.run() cli.run()
finally: finally:
self.log(str(addr), "-" * 7 + "C-done") self.log("%s %s" % addr, "-" * 7 + "C-done")
try: try:
sck.shutdown(socket.SHUT_RDWR) sck.shutdown(socket.SHUT_RDWR)
sck.close() sck.close()
except (OSError, socket.error) as ex: except (OSError, socket.error) as ex:
self.log(str(addr), "shut_rdwr err:\n {}\n {}".format(repr(sck), ex)) self.log(
"%s %s" % addr, "shut_rdwr err:\n {}\n {}".format(repr(sck), ex),
)
if ex.errno not in [10038, 107, 57, 9]: if ex.errno not in [10038, 107, 57, 9]:
# 10038 No longer considered a socket # 10038 No longer considered a socket
# 107 Transport endpoint not connected # 107 Transport endpoint not connected

View file

@ -64,7 +64,7 @@ class TcpSrv(object):
self.log("tcpsrv", "-" * 2 + "C-acc1") self.log("tcpsrv", "-" * 2 + "C-acc1")
sck, addr = self.srv.accept() sck, addr = self.srv.accept()
self.log(str(addr), "-" * 3 + "C-acc2") self.log("%s %s" % addr, "-" * 3 + "C-acc2")
self.num_clients.add() self.num_clients.add()
self.hub.broker.put(False, "httpconn", sck, addr) self.hub.broker.put(False, "httpconn", sck, addr)

View file

@ -11,7 +11,7 @@
<div id="mn"></div> <div id="mn"></div>
<div id="mh"> <div id="mh">
<a id="lightswitch" href="#">dark</a> <a id="lightswitch" href="#">dark</a>
there will soon be more buttons on this row so it looks less dumb <a id="edit" href="?edit">edit</a>
</div> </div>
<div id="ml"> <div id="ml">
<div style="text-align:center;margin:5em 0"> <div style="text-align:center;margin:5em 0">

View file

@ -14,15 +14,15 @@ var dom_md = document.getElementById('mt');
// add toolbar buttons // add toolbar buttons
(function () { (function () {
var n = document.location + ''; var n = document.location + '';
n = n.substr(n.indexOf('//') + 2).split('/'); n = n.substr(n.indexOf('//') + 2).split('?')[0].split('/');
n[0] = 'top'; n[0] = 'top';
var loc = [];
var nav = []; var nav = [];
var url = '/';
for (var a = 0; a < n.length; a++) { for (var a = 0; a < n.length; a++) {
if (a > 0) if (a > 0)
url += n[a] + '/'; loc.push(n[a]);
nav.push('<a href="' + url + '">' + n[a] + '</a>'); nav.push('<a href="/' + loc.join('/') + '">' + n[a] + '</a>');
} }
dom_nav.innerHTML = nav.join(''); dom_nav.innerHTML = nav.join('');
})(); })();

75
copyparty/web/mde.css Normal file
View file

@ -0,0 +1,75 @@
/* fontawesome is 2big */
.fa { font-size: 1.5em; line-height: 1em; margin: -3em; position: relative; left: -.05em; font-style: normal }
.fa-bold:before { content: 'B'; font-weight: bold }
.fa-italic:before { content: 'I'; font-style: italic }
.fa-strikethrough:before { content: 'S'; text-decoration: line-through }
.fa-header:before { content: 'H'; font-weight: bold; font-family: serif; top: -.2em; left: .5em }
.fa-quote-left:before { content: '❝'; font-family: serif; top: -.5em }
.fa-list-ul:before { content: '•' }
.fa-list-ol:before { content: '①' }
.fa-link:before { content: '🔗'; font-size: .8em }
.fa-image:before { content: '🎨' }
.fa-eye:before { content: '👀'; font-size: .9em }
.fa-columns:before { content: '◫' }
.fa-arrows-alt:before { content: '⛶' }
.fa-undo:before { content: '⟲' }
.fa-redo:before { content: '⟳' }
.fa-question-circle:before { content: '?' }
.fa-code:before { content: '/'; font-size: .8em; }
.fa-eraser:before { content: '⁋' }
.fa-table:before { content: '⊞' }
.fa-minus:before { content: '' }
/*
https://dev.w3.org/html5/html-author/charref
http://xahlee.info/comp/unicode_arrows.html
https://www.fileformat.info/info/unicode/block/miscellaneous_symbols_and_pictographs/list.htm
💾 🗙
*/
button { border: 1px solid #999 !important; }
html, body {
margin: 0;
padding: 0;
min-height: 100%;
font-family: sans-serif;
}
#mn {
font-weight: normal;
margin: 1.3em 0 .7em 1em;
font-size: 1.4em;
}
#mn a {
color: #444;
margin: 0 0 0 -.2em;
padding: 0 0 0 .4em;
text-decoration: none;
}
#mn a:first-child {
padding-left: .5em;
}
#mn a:last-child {
padding-right: .5em;
}
#mn a:not(:last-child):after {
content: '';
width: 1.05em;
height: 1.05em;
margin: -.2em .3em -.2em -.4em;
display: inline-block;
border: 1px solid rgba(0,0,0,0.3);
border-width: .05em .05em 0 0;
transform: rotate(45deg);
}
#mn a:hover {
color: #000;
text-decoration: underline;
}
*[data-ln]:before {
content: attr(data-ln);
font-size: .8em;
margin: 0 .4em;
color: #f0c;
}

29
copyparty/web/mde.html Normal file
View file

@ -0,0 +1,29 @@
<!DOCTYPE html><html><head>
<meta charset="utf-8">
<title>📝🎉 {{ title }}</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=0.7">
<link href="/.cpr/mde.css" rel="stylesheet">
<link href="/.cpr/deps/easymde.css" rel="stylesheet">
</head>
<body>
<div id="mw">
<div id="mn"></div>
<div id="ml">
<div style="text-align:center;margin:5em 0">
<div style="font-size:2em;margin:1em 0">Loading</div>
if you're still reading this, check that javascript is allowed
</div>
</div>
<div id="m">
<textarea id="mt" style="display:none">{{ md }}</textarea>
</div>
</div>
<script>
var link_md_as_html = false; // TODO (does nothing)
</script>
<script src="/.cpr/deps/easymde.full.js"></script>
<script src="/.cpr/mde.js"></script>
</body></html>

40
copyparty/web/mde.js Normal file
View file

@ -0,0 +1,40 @@
var dom_wrap = document.getElementById('mw');
var dom_nav = document.getElementById('mn');
var dom_doc = document.getElementById('m');
var dom_md = document.getElementById('mt');
(function () {
var n = document.location + '';
n = n.substr(n.indexOf('//') + 2).split('?')[0].split('/');
n[0] = 'top';
var loc = [];
var nav = [];
for (var a = 0; a < n.length; a++) {
if (a > 0)
loc.push(n[a]);
nav.push('<a href="/' + loc.join('/') + '">' + n[a] + '</a>');
}
dom_nav.innerHTML = nav.join('');
})();
(function () {
var mde = new EasyMDE({
autoDownloadFontAwesome: false,
autofocus: true,
insertTexts: ["[](", ")"],
renderingConfig: {
markedOptions: {
breaks: true,
gfm: true
}
},
spellChecker: false,
tabSize: 4,
showIcons: ['strikethrough', 'code', 'table', 'undo', 'redo', 'heading', 'clean-block', 'horizontal-rule']
});
var loader = document.getElementById('ml');
loader.parentNode.removeChild(loader);
})();
zsetTimeout(function () { window.location.reload(true); }, 1000);

View file

@ -4,7 +4,8 @@ ENV ver_asmcrypto=2821dd1dedd1196c378f5854037dda5c869313f3 \
ver_markdownit=10.0.0 \ ver_markdownit=10.0.0 \
ver_showdown=1.9.1 \ ver_showdown=1.9.1 \
ver_marked=1.0.0 \ ver_marked=1.0.0 \
ver_ogvjs=1.6.1 ver_ogvjs=1.6.1 \
ver_mde=2.10.1
# download # download
@ -12,6 +13,7 @@ RUN apk add make g++ git bash npm patch wget tar pigz brotli gzip unzip \
&& wget https://github.com/brion/ogv.js/releases/download/$ver_ogvjs/ogvjs-$ver_ogvjs.zip -O ogvjs.zip \ && wget https://github.com/brion/ogv.js/releases/download/$ver_ogvjs/ogvjs-$ver_ogvjs.zip -O ogvjs.zip \
&& wget https://github.com/asmcrypto/asmcrypto.js/archive/$ver_asmcrypto.tar.gz -O asmcrypto.tgz \ && wget https://github.com/asmcrypto/asmcrypto.js/archive/$ver_asmcrypto.tar.gz -O asmcrypto.tgz \
&& wget https://github.com/markedjs/marked/archive/v$ver_marked.tar.gz -O marked.tgz \ && wget https://github.com/markedjs/marked/archive/v$ver_marked.tar.gz -O marked.tgz \
&& wget https://github.com/Ionaru/easy-markdown-editor/archive/$ver_mde.tar.gz -O mde.tgz \
&& unzip ogvjs.zip \ && unzip ogvjs.zip \
&& (tar -xf asmcrypto.tgz \ && (tar -xf asmcrypto.tgz \
&& cd asmcrypto.js-$ver_asmcrypto \ && cd asmcrypto.js-$ver_asmcrypto \
@ -20,7 +22,13 @@ RUN apk add make g++ git bash npm patch wget tar pigz brotli gzip unzip \
&& cd marked-$ver_marked \ && cd marked-$ver_marked \
&& npm install \ && npm install \
&& npm i grunt uglify-js -g ) \ && npm i grunt uglify-js -g ) \
&& (tar -xf mde.tgz \
&& cd easy-markdown-editor* \
&& npm install \
&& npm i gulp-cli -g ) \
&& mkdir /z/dist && mkdir /z/dist
# && wget https://github.com/FortAwesome/Font-Awesome/releases/download/5.0.11/fontawesome-free-5.0.11.zip -O fontawesome.zip \
# && unzip fontawesome.zip \
# uncomment if you wanna test the abandoned markdown converters # uncomment if you wanna test the abandoned markdown converters
@ -74,10 +82,26 @@ RUN cd marked-$ver_marked \
&& patch -p1 < /z/marked.patch \ && patch -p1 < /z/marked.patch \
&& npm run build \ && npm run build \
&& cp -pv marked.min.js /z/dist/marked.js \ && cp -pv marked.min.js /z/dist/marked.js \
&& cp -pv lib/marked.js /z/dist/marked.full.js && cp -pv lib/marked.js /z/dist/marked.full.js \
&& mkdir -p /z/nodepkgs \
&& ln -s $(pwd) /z/nodepkgs/marked
# && npm run test \ # && npm run test \
# build easymde (TODO man this thing is big)
RUN cd easy-markdown-editor-$ver_mde \
&& sed -ri 's`https://registry.npmjs.org/marked/-/marked-0.8.2.tgz`file:/z/nodepkgs/marked`' package-lock.json \
&& sed -ri 's`("marked": ")[^"]+`\1file:/z/nodepkgs/marked`' ./package.json \
&& npm install \
&& gulp \
&& cp -pv dist/easymde.min.css /z/dist/easymde.css \
&& cp -pv dist/easymde.min.js /z/dist/easymde.js \
&& sed -ri '/pipe.terser/d; /cleanCSS/d' gulpfile.js \
&& gulp \
&& cp -pv dist/easymde.min.css /z/dist/easymde.full.css \
&& cp -pv dist/easymde.min.js /z/dist/easymde.full.js
# build showdown (abandoned; disabled by default) # build showdown (abandoned; disabled by default)
COPY showdown.patch /z/ COPY showdown.patch /z/
RUN [ $build_abandoned ] || exit 0; \ RUN [ $build_abandoned ] || exit 0; \
@ -126,6 +150,9 @@ COPY zopfli.makefile /z/dist/Makefile
RUN cd /z/dist \ RUN cd /z/dist \
&& make -j$(nproc) \ && make -j$(nproc) \
&& rm Makefile && rm Makefile
# && cp -pv "$(find /z/fontawesome-fre* -name fa-regular-400.woff | head -n 1)" fontawesome.woff
# && cp -pv "$(find /z/fontawesome-fre* -name fontawesome.min.css | head -n 1)" fontawesome.css \
# && sed -ri 's`@font-face.*``' fontawesome.css \
# showdown: abandoned due to code-blocks in lists failing # showdown: abandoned due to code-blocks in lists failing
@ -156,5 +183,5 @@ RUN cd /z/dist \
# f=../../copyparty/web/deps/marked.js.gz; (cd ~ed/src/ && diff -NarU1 marked-1.0.0-orig/ marked-1.0.0-edit/) >marked.patch; make && printf '%d ' $(wc -c <$f) $(gzip -d <$f | wc -c); echo # f=../../copyparty/web/deps/marked.js.gz; (cd ~ed/src/ && diff -NarU1 marked-1.0.0-orig/ marked-1.0.0-edit/) >marked.patch; make && printf '%d ' $(wc -c <$f) $(gzip -d <$f | wc -c); echo
# d=/home/ed/dev/copyparty/scripts/deps-docker/; scp Dockerfile marked-ln.patch root@$bip:$d && ssh root@$bip "cd $d && make" && ssh root@$bip 'tar -cC /home/ed/dev/copyparty/copyparty/web deps' | (cd ../../copyparty/web/; cat > the.tgz; tar -xvf the.tgz) # d=/home/ed/dev/copyparty/scripts/deps-docker/; tar -cf ../x . && ssh root@$bip "cd $d && tar -xv >&2 && make >&2 && tar -cC ../../copyparty/web deps" <../x | (cd ../../copyparty/web/; cat > the.tgz; tar -xvf the.tgz)
# gzip -dkf ../dev/copyparty/copyparty/web/deps/deps/marked.full.js.gz && diff -NarU2 ../dev/copyparty/copyparty/web/deps/{,deps/}marked.full.js # gzip -dkf ../dev/copyparty/copyparty/web/deps/deps/marked.full.js.gz && diff -NarU2 ../dev/copyparty/copyparty/web/deps/{,deps/}marked.full.js