add markdown viewer

This commit is contained in:
ed 2020-04-26 23:43:26 +02:00
parent fc5c815824
commit 1c49b71606
11 changed files with 1465 additions and 7 deletions

View file

@ -34,8 +34,10 @@ turn your phone or raspi into a portable file server with resumable uploads/down
* [ ] download as zip
* [x] volumes
* [x] accounts
* [x] markdown viewer
* [ ] markdown editor? w
summary: close to beta
summary: it works! you can use it! (but technically not even close to beta)
# dependencies
@ -82,6 +84,7 @@ in the `scripts` folder:
roughly sorted by priority
* sortable browser columns
* up2k handle filename too long
* up2k fails on empty files? alert then stuck
* unexpected filepath on dupe up2k

View file

@ -706,6 +706,48 @@ class HttpCli(object):
self.log(logmsg)
return True
def tx_md(self, fs_path):
logmsg = "{:4} {} ".format("", self.req)
html_path = os.path.join(E.mod, "web/md.html")
st = os.stat(fsenc(fs_path))
sz_md = st.st_size
ts_md = st.st_mtime
st = os.stat(fsenc(html_path))
ts_html = st.st_mtime
file_ts = max(ts_md, ts_html)
file_lastmod, do_send = self._chk_lastmod(file_ts)
self.out_headers["Last-Modified"] = file_lastmod
status = 200 if do_send else 304
targs = {
"title": html_escape(self.vpath, quote=False),
"md": "",
}
sz_html = len(self.conn.tpl_md.render(**targs).encode("utf-8"))
self.send_headers(sz_html + sz_md, status)
logmsg += str(status)
if self.mode == "HEAD" or not do_send:
self.log(logmsg)
return True
with open(fsenc(fs_path), "rb") as f:
md = f.read()
targs["md"] = md.decode("utf-8", "replace")
html = self.conn.tpl_md.render(**targs).encode("utf-8")
try:
self.s.sendall(html)
except:
self.log(logmsg + " \033[31md/c\033[0m")
return False
self.log(logmsg + " " + str(len(html)))
return True
def tx_mounts(self):
rvol = [x + "/" if x else x for x in self.rvol]
wvol = [x + "/" if x else x for x in self.wvol]
@ -735,6 +777,9 @@ class HttpCli(object):
raise Pebkac(404)
if not os.path.isdir(fsenc(abspath)):
if abspath.endswith(".md") and "raw" not in self.uparam:
return self.tx_md(abspath)
return self.tx_file(abspath)
fsroot, vfs_ls, vfs_virt = vn.ls(rem, self.uname)

View file

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

375
copyparty/web/md.css Normal file
View file

@ -0,0 +1,375 @@
html, body {
color: #333;
background: #eee;
font-family: sans-serif;
line-height: 1.5em;
}
#mw {
width: 48.5em;
margin: 0 auto;
margin-bottom: 6em;
}
pre, code, a {
color: #480;
background: #f7f7f7;
border: .07em solid #ddd;
border-radius: .2em;
padding: .1em .3em;
margin: 0 .1em;
}
code {
font-size: .96em;
}
pre, code {
font-family: monospace, monospace;
white-space: pre-wrap;
word-break: break-all;
}
pre {
counter-reset: precode;
}
pre code {
counter-increment: precode;
display: inline-block;
margin: 0 -.3em;
padding: .4em .5em;
border: none;
border-bottom: 1px solid #cdc;
min-width: calc(100% - .6em);
line-height: 1.1em;
}
pre code:last-child {
border-bottom: none;
}
pre code:before {
content: counter(precode);
-webkit-user-select: none;
display: inline-block;
text-align: right;
font-size: .75em;
color: #48a;
width: 4em;
padding-right: 1.5em;
margin-left: -5.5em;
}
pre code:hover {
background: #fec;
color: #360;
}
h1, h2 {
line-height: 1.5em;
}
h1 {
font-size: 1.7em;
text-align: center;
border: 1em solid #777;
border-width: .05em 0;
margin: 3em 0;
}
h2 {
font-size: 1.5em;
font-weight: normal;
background: #f7f7f7;
border-top: .07em solid #fff;
border-bottom: .07em solid #bbb;
border-radius: .5em .5em 0 0;
padding-left: .4em;
margin-top: 3em;
}
h1 a, h3 a, h5 a,
h2 a, h4 a, h6 a {
color: inherit;
background: none;
border: none;
padding: 0;
margin: 0;
}
#m ul,
#m ol {
border-left: .3em solid #ddd;
}
#m>ul,
#m>ol {
border-color: #bbb;
}
#m ul>li {
list-style-type: disc;
}
#m ul>li,
#m ol>li {
margin: .7em 0;
}
p>em,
li>em {
color: #c50;
padding: .1em;
border-bottom: .1em solid #bbb;
}
blockquote {
font-family: serif;
background: #f7f7f7;
border: .07em dashed #ccc;
padding: 0 2em;
margin: 1em 0;
}
small {
opacity: .8;
}
#toc {
width: 48.5em;
margin: 0 auto;
}
#toc ul {
padding-left: 1em;
}
#toc>ul {
text-align: left;
padding-left: .5em;
}
#toc li {
list-style-type: none;
line-height: 1.2em;
margin: .5em 0;
}
#toc a {
color: #057;
border: none;
background: none;
display: block;
margin-left: -.3em;
padding: .2em .3em;
}
#toc a.act {
color: #fff;
background: #07a;
}
.todo_pend,
.todo_done {
z-index: 99;
position: relative;
display: inline-block;
font-family: monospace, monospace;
font-weight: bold;
font-size: 1.3em;
line-height: .1em;
margin: -.5em 0 -.5em -.85em;
top: .1em;
color: #b29;
}
.todo_done {
color: #6b3;
text-shadow: .02em 0 0 #6b3;
}
table {
border-collapse: collapse;
}
td {
padding: .2em .5em;
border: .12em solid #aaa;
}
th {
border: .12em solid #aaa;
}
blink {
animation: blinker .7s cubic-bezier(.9, 0, .1, 1) infinite;
}
@keyframes blinker {
10% {
opacity: 0;
}
60% {
opacity: 1;
}
}
@media screen {
a {
color: #fff;
background: #39b;
text-decoration: none;
padding: 0 .3em;
border: none;
border-bottom: .07em solid #079;
}
h2 {
color: #fff;
background: #555;
margin-top: 2em;
border-bottom: .22em solid #999;
border-top: none;
}
h1 {
color: #fff;
background: #444;
font-weight: normal;
border-top: .4em solid #fb0;
border-bottom: .4em solid #777;
border-radius: 0 1em 0 1em;
margin: 3em 0 1em 0;
padding: .5em 0;
}
#mn {
text-shadow: 1px 1px 0 #000;
xfont-variant: small-caps;
font-weight: normal;
margin: 1.3em 0 0 0;
font-size: 1.4em;
}
#mn a {
background: #2c2c2c;
margin: 0 0 0 -.2em;
padding: 0 0 0 .4em;
/* ie: */
border-bottom: .1em solid #777\9;
margin-right: 1em\9;
}
#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(255,224,192,0.3);
border-width: .05em .05em 0 0;
transform: rotate(45deg);
background: linear-gradient(45deg, rgba(0,0,0,0) 40%, rgba(0,0,0,0.25) 75%, rgba(0,0,0,0.35));
}
#mn a:hover {
color: #fff;
background: linear-gradient(90deg, rgba(0,0,0,0), rgba(0,0,0,0.2), rgba(0,0,0,0));
}
#mh {
margin: 1.5em 0;
}
html.dark,
html.dark body {
background: #222;
color: #ccc;
}
html.dark #toc a {
color: #ccc;
border-left: .4em solid #444;
border-bottom: .1em solid #333;
}
html.dark #toc a.act {
color: #fff;
border-left: .4em solid #3ad;
}
html.dark #toc li {
border-width: 0;
}
html.dark #m a,
html.dark #mh a {
background: #057;
}
html.dark #m h1 a, html.dark #m h4 a,
html.dark #m h2 a, html.dark #m h5 a,
html.dark #m h3 a, html.dark #m h6 a {
color: inherit;
background: none;
}
html.dark pre,
html.dark code {
color: #8c0;
background: #1a1a1a;
border: .07em solid #333;
}
html.dark #m ul,
html.dark #m ol {
border-color: #444;
}
html.dark #m>ul,
html.dark #m>ol {
border-color: #555;
}
html.dark p>em,
html.dark li>em {
color: #f94;
border-color: #666;
}
html.dark h1 {
background: #383838;
border-top: .4em solid #b80;
border-bottom: .4em solid #4c4c4c;
}
html.dark h2 {
background: #444;
border-bottom: .22em solid #555;
}
html.dark td,
html.dark th {
border-color: #444;
}
html.dark blockquote {
background: #282828;
border: .07em dashed #444;
}
}
@media screen and (min-width: 64em) {
#mw {
margin-left: 14em;
margin-left: calc(100% - 50em);
}
#toc {
width: 13em;
width: calc(100% - 52.3em);
background: #eee;
position: fixed;
top: 0;
left: 0;
height: 100%;
overflow-y: auto;
padding: 0;
margin: 0;
box-shadow: 0 0 1em #ccc;
scrollbar-color: #eb0 #f7f7f7;
xscrollbar-width: thin;
}
#toc li {
border-left: .3em solid #ccc;
}
#toc::-webkit-scrollbar-track {
background: #f7f7f7;
}
#toc::-webkit-scrollbar {
background: #f7f7f7;
width: .8em;
}
#toc::-webkit-scrollbar-thumb {
background: #eb0;
}
html.dark #toc {
background: #282828;
box-shadow: 0 0 1em #181818;
scrollbar-color: #b80 #282828;
}
}
@media screen and (min-width: 84em) {
#toc { width: 30em }
#mw { margin-left: 32em }
}
@media print {
a {
color: #079;
text-decoration: none;
border-bottom: .07em solid #4ac;
padding: 0 .3em;
}
#toc>ul {
border-left: .1em solid #84c4dd;
}
#mn, #mh {
display: none;
}
}

47
copyparty/web/md.html Normal file
View file

@ -0,0 +1,47 @@
<!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/md.css" rel="stylesheet">
</head>
<body>
<div id="toc"></div>
<div id="mw">
<div id="mn"></div>
<div id="mh">
<a id="lightswitch" href="#">dark</a>
there will soon be more buttons on this row so it looks less dumb
</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)
(function () {
var btn = document.getElementById("lightswitch");
var toggle = function () {
var dark = !document.documentElement.getAttribute("class");
document.documentElement.setAttribute("class", dark ? "dark" : "");
btn.innerHTML = dark ? "light" : "dark";
if (window.localStorage)
localStorage.setItem('md-dark', dark ? 1 : 0);
};
btn.onclick = toggle;
if (window.localStorage && localStorage.getItem('md-dark') == 1)
toggle();
})();
</script>
<script src="/.cpr/deps/marked.full.js"></script>
<script src="/.cpr/md.js"></script>
</body></html>

232
copyparty/web/md.js Normal file
View file

@ -0,0 +1,232 @@
/*var conv = new showdown.Converter();
conv.setFlavor('github');
conv.setOption('tasklists', 0);
var mhtml = conv.makeHtml(dom_md.value);
*/
var dom_toc = document.getElementById('toc');
var dom_wrap = document.getElementById('mw');
var dom_head = document.getElementById('mh');
var dom_nav = document.getElementById('mn');
var dom_doc = document.getElementById('m');
var dom_md = document.getElementById('mt');
// add toolbar buttons
(function () {
var n = document.location + '';
n = n.substr(n.indexOf('//') + 2).split('/');
n[0] = 'top';
var nav = [];
var url = '/';
for (var a = 0; a < n.length; a++) {
if (a > 0)
url += n[a] + '/';
nav.push('<a href="' + url + '">' + n[a] + '</a>');
}
dom_nav.innerHTML = nav.join('');
})();
function convert_markdown(md_text) {
marked.setOptions({
//headerPrefix: 'h-',
breaks: true,
gfm: true
});
var html = marked(md_text);
dom_doc.innerHTML = html;
var loader = document.getElementById('ml');
loader.parentNode.removeChild(loader);
// todo-lists (should probably be a marked extension)
var nodes = dom_doc.getElementsByTagName('input');
for (var a = nodes.length - 1; a >= 0; a--) {
var dom_box = nodes[a];
if (dom_box.getAttribute('type') !== 'checkbox')
continue;
var dom_li = dom_box.parentNode;
var done = dom_box.getAttribute('checked');
done = done !== null;
var clas = done ? 'done' : 'pend';
var char = done ? 'Y' : 'N';
dom_li.setAttribute('class', 'task-list-item');
dom_li.style.listStyleType = 'none';
var html = dom_li.innerHTML;
dom_li.innerHTML =
'<span class="todo_' + clas + '">' + char + '</span>' +
html.substr(html.indexOf('>') + 1);
}
}
function init_toc() {
var anchors = []; // list of toc entries, complex objects
var anchor = null; // current toc node
var id_seen = {}; // taken IDs
var html = []; // generated toc html
var lv = 0; // current indentation level in the toc html
var re = new RegExp('^[Hh]([1-3])');
var manip_nodes_dyn = dom_doc.getElementsByTagName('*');
var manip_nodes = [];
for (var a = 0, aa = manip_nodes_dyn.length; a < aa; a++)
manip_nodes.push(manip_nodes_dyn[a]);
for (var a = 0, aa = manip_nodes.length; a < aa; a++) {
var elm = manip_nodes[a];
var m = re.exec(elm.tagName);
var is_header =
m !== null;
var is_precode =
!is_header &&
elm.tagName == 'PRE' &&
elm.childNodes.length === 1 &&
elm.childNodes[0].tagName == 'CODE';
if (is_header) {
var nlv = m[1];
while (lv < nlv) {
html.push('<ul>');
lv++;
}
while (lv > nlv) {
html.push('</ul>');
lv--;
}
var orig_id = elm.getAttribute('id');
var id = orig_id;
if (id_seen[id]) {
for (var n = 1; n < 4096; n++) {
id = orig_id + '-' + n;
if (!id_seen[id])
break;
}
elm.setAttribute('id', id);
}
id_seen[id] = 1;
var ahref = '<a href="#' + id + '">' +
elm.innerHTML + '</a>';
html.push('<li>' + ahref + '</li>');
elm.innerHTML = ahref;
if (anchor != null)
anchors.push(anchor);
anchor = {
elm: elm,
kids: [],
y: null
};
}
else if (is_precode) {
elm.innerHTML = elm.innerHTML.replace(
/\r?\n<\/code>$/i, '</code>').split(/\r?\n/g).join('</code>\n<code>');
}
if (!is_header && anchor)
anchor.kids.push(elm);
}
dom_toc.innerHTML = html.join('\n');
if (anchor != null)
anchors.push(anchor);
// copy toc links into the toc list
var atoc = dom_toc.getElementsByTagName('a');
for (var a = 0, aa = anchors.length; a < aa; a++)
anchors[a].lnk = atoc[a];
// collect vertical position of all toc items (headers in document)
function freshen_offsets() {
var top = window.pageYOffset || document.documentElement.scrollTop;
for (var a = anchors.length - 1; a >= 0; a--) {
var y = top + anchors[a].elm.getBoundingClientRect().top;
y = Math.round(y * 10.0) / 10;
if (anchors[a].y === y)
break;
anchors[a].y = y;
}
}
// hilight the correct toc items + scroll into view
function freshen_toclist() {
if (anchors.length == 0)
return;
var ptop = window.pageYOffset || document.documentElement.scrollTop;
var hit = -1;
for (var a = 0; a < anchors.length; a++) {
if (anchors[a].y >= ptop - 8) { //???
hit = a;
break;
}
}
var links = dom_toc.getElementsByTagName('a');
if (!anchors[hit].active) {
for (var a = 0; a < anchors.length; a++) {
if (anchors[a].active) {
anchors[a].active = false;
links[a].setAttribute('class', '');
}
}
anchors[hit].active = true;
links[hit].setAttribute('class', 'act');
}
var pane_height = parseInt(getComputedStyle(dom_toc).height);
var link_bounds = links[hit].getBoundingClientRect();
var top = link_bounds.top - (pane_height / 6);
var btm = link_bounds.bottom + (pane_height / 6);
if (top < 0)
dom_toc.scrollTop -= -top;
else if (btm > pane_height)
dom_toc.scrollTop += btm - pane_height;
}
function refresh() {
freshen_offsets();
freshen_toclist();
}
return { "refresh": refresh }
}
// "main" :p
convert_markdown(dom_md.value);
var toc = init_toc();
// scroll handler
(function () {
var timer_active = false;
var final = null;
function onscroll() {
clearTimeout(final);
timer_active = false;
toc.refresh();
}
onscroll();
window.onscroll = function () {
// long timeout: scroll ended
clearTimeout(final);
final = setTimeout(onscroll, 100);
// short timeout: continuous updates
if (timer_active)
return;
timer_active = true;
setTimeout(onscroll, 10);
};
})();

View file

@ -1,25 +1,50 @@
FROM alpine:3.11
WORKDIR /z
ENV ver_asmcrypto=2821dd1dedd1196c378f5854037dda5c869313f3 \
ver_markdownit=10.0.0 \
ver_showdown=1.9.1 \
ver_marked=1.0.0 \
ver_ogvjs=1.6.1
# download
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 \
&& wget https://github.com/asmcrypto/asmcrypto.js/archive/$ver_asmcrypto.tar.gz \
&& unzip ogvjs-$ver_ogvjs.zip \
&& tar -xf $ver_asmcrypto.tar.gz \
&& 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/markedjs/marked/archive/v$ver_marked.tar.gz -O marked.tgz \
&& unzip ogvjs.zip \
&& (tar -xf asmcrypto.tgz \
&& cd asmcrypto.js-$ver_asmcrypto \
&& npm install ) \
&& (tar -xf marked.tgz \
&& cd marked-$ver_marked \
&& npm install \
&& npm i grunt uglify-js -g ) \
&& mkdir /z/dist
# uncomment if you wanna test the abandoned markdown converters
#ENV build_abandoned=1
RUN [ $build_abandoned ] || exit 0; \
git clone --depth 1 --branch $ver_showdown https://github.com/showdownjs/showdown/ \
&& wget https://github.com/markdown-it/markdown-it/archive/$ver_markdownit.tar.gz -O markdownit.tgz \
&& (cd showdown \
&& npm install \
&& npm i grunt -g ) \
&& (tar -xf markdownit.tgz \
&& cd markdown-it-$ver_markdownit \
&& npm install )
# build asmcrypto
RUN cd asmcrypto.js-$ver_asmcrypto \
&& echo "export { Sha512 } from './hash/sha512/sha512';" > src/entry-export_all.ts \
&& node -r esm build.js \
&& mv asmcrypto.all.es5.js /z/dist/sha512.js
# build ogvjs
RUN cd ogvjs-$ver_ogvjs \
&& cp -pv \
@ -40,8 +65,90 @@ RUN cd ogvjs-$ver_ogvjs \
dynamicaudio.swf \
/z/dist
# build marked
COPY marked.patch /z/
RUN cd marked-$ver_marked \
&& patch -p1 < /z/marked.patch \
&& npm run build \
&& cp -pv marked.min.js /z/dist/marked.js \
&& cp -pv lib/marked.js /z/dist/marked.full.js
# && npm run test \
# build showdown (abandoned; disabled by default)
COPY showdown.patch /z/
RUN [ $build_abandoned ] || exit 0; \
cd showdown \
&& rm -rf bin dist \
# # remove ellipsis plugin \
&& rm \
src/subParsers/ellipsis.js \
test/cases/ellipsis* \
# # remove html-to-md converter \
&& rm \
test/node/testsuite.makemd.js \
test/node/showdown.Converter.makeMarkdown.js \
# # remove emojis \
&& rm src/subParsers/emoji.js \
&& awk '/^showdown.helper.emojis/ {o=1} !o; /^\}/ {o=0}' \
>f <src/helpers.js \
&& mv f src/helpers.js \
&& rm -rf test/features/emojis \
# # remove ghmentions \
&& rm test/features/ghMentions.* \
# # remove option descriptions \
&& sed -ri '/descri(ption|be): /d' src/options.js \
&& patch -p1 < /z/showdown.patch
RUN [ $build_abandoned ] || exit 0; \
cd showdown \
&& grunt build \
&& sed -ri '/sourceMappingURL=showdown.min.js.map/d' dist/showdown.min.js \
&& mv dist/showdown.min.js /z/dist/showdown.js \
&& ls -al /z/dist/showdown.js
# build markdownit (abandoned; disabled by default)
COPY markdown-it.patch /z/
RUN [ $build_abandoned ] || exit 0; \
cd markdown-it-$ver_markdownit \
&& patch -p1 < /z/markdown-it.patch \
&& make browserify \
&& cp -pv dist/markdown-it.min.js /z/dist/markdown-it.js \
&& cp -pv dist/markdown-it.js /z/dist/markdown-it-full.js
# compress
COPY zopfli.makefile /z/dist/Makefile
RUN cd /z/dist \
&& make -j$(nproc) \
&& rm Makefile
# showdown: abandoned due to code-blocks in lists failing
# 22770 orig
# 12154 no-emojis
# 12134 no-srcmap
# 11189 no-descriptions
# 11152 no-ellipsis
# 10617 no-this.makeMd
# 9569 no-extensions
# 9537 no-extensions
# 9410 no-mentions
# markdown-it: abandoned because no header anchors (and too big)
# 32322 107754 orig (wowee)
# 19619 21392 71540 less entities
# marked:
# 9253 29773 orig
# 9159 29633 no copyright (reverted)
# 9040 29057 no sanitize
# 8870 28631 no email-mangle
# so really not worth it, just drop the patch when that stops working
# 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

View file

@ -0,0 +1,10 @@
diff -NarU1 markdown-it-10.0.0-orig/lib/common/entities.js markdown-it-10.0.0-edit/lib/common/entities.js
--- markdown-it-10.0.0-orig/lib/common/entities.js 2019-09-10 21:39:58.000000000 +0000
+++ markdown-it-10.0.0-edit/lib/common/entities.js 2020-04-26 10:24:33.043023331 +0000
@@ -5,2 +5,5 @@
/*eslint quotes:0*/
-module.exports = require('entities/lib/maps/entities.json');
+//module.exports = require('entities/lib/maps/entities.json');
+module.exports = {
+ "amp": "&", "quot": "\"", "gt": ">", "lt": "<"
+}

View file

@ -0,0 +1,269 @@
diff -NarU1 marked-1.0.0-orig/src/defaults.js marked-1.0.0-edit/src/defaults.js
--- marked-1.0.0-orig/src/defaults.js 2020-04-21 01:03:48.000000000 +0000
+++ marked-1.0.0-edit/src/defaults.js 2020-04-25 19:16:56.124621393 +0000
@@ -9,10 +9,6 @@
langPrefix: 'language-',
- mangle: true,
pedantic: false,
renderer: null,
- sanitize: false,
- sanitizer: null,
silent: false,
smartLists: false,
- smartypants: false,
tokenizer: null,
diff -NarU1 marked-1.0.0-orig/src/helpers.js marked-1.0.0-edit/src/helpers.js
--- marked-1.0.0-orig/src/helpers.js 2020-04-21 01:03:48.000000000 +0000
+++ marked-1.0.0-edit/src/helpers.js 2020-04-25 18:58:43.001320210 +0000
@@ -65,16 +65,3 @@
const originIndependentUrl = /^$|^[a-z][a-z0-9+.-]*:|^[?#]/i;
-function cleanUrl(sanitize, base, href) {
- if (sanitize) {
- let prot;
- try {
- prot = decodeURIComponent(unescape(href))
- .replace(nonWordAndColonTest, '')
- .toLowerCase();
- } catch (e) {
- return null;
- }
- if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0 || prot.indexOf('data:') === 0) {
- return null;
- }
- }
+function cleanUrl(base, href) {
if (base && !originIndependentUrl.test(href)) {
@@ -224,8 +211,2 @@
-function checkSanitizeDeprecation(opt) {
- if (opt && opt.sanitize && !opt.silent) {
- console.warn('marked(): sanitize and sanitizer parameters are deprecated since version 0.7.0, should not be used and will be removed in the future. Read more here: https://marked.js.org/#/USING_ADVANCED.md#options');
- }
-}
-
module.exports = {
@@ -240,4 +221,3 @@
rtrim,
- findClosingBracket,
- checkSanitizeDeprecation
+ findClosingBracket
};
diff -NarU1 marked-1.0.0-orig/src/Lexer.js marked-1.0.0-edit/src/Lexer.js
--- marked-1.0.0-orig/src/Lexer.js 2020-04-21 01:03:48.000000000 +0000
+++ marked-1.0.0-edit/src/Lexer.js 2020-04-25 22:46:54.107584066 +0000
@@ -6,3 +6,3 @@
* smartypants text replacement
- */
+ *
function smartypants(text) {
@@ -27,3 +27,3 @@
* mangle email addresses
- */
+ *
function mangle(text) {
@@ -388,3 +388,3 @@
// autolink
- if (token = this.tokenizer.autolink(src, mangle)) {
+ if (token = this.tokenizer.autolink(src)) {
src = src.substring(token.raw.length);
@@ -395,3 +395,3 @@
// url (gfm)
- if (!inLink && (token = this.tokenizer.url(src, mangle))) {
+ if (!inLink && (token = this.tokenizer.url(src))) {
src = src.substring(token.raw.length);
@@ -402,3 +402,3 @@
// text
- if (token = this.tokenizer.inlineText(src, inRawBlock, smartypants)) {
+ if (token = this.tokenizer.inlineText(src, inRawBlock)) {
src = src.substring(token.raw.length);
diff -NarU1 marked-1.0.0-orig/src/marked.js marked-1.0.0-edit/src/marked.js
--- marked-1.0.0-orig/src/marked.js 2020-04-21 01:03:48.000000000 +0000
+++ marked-1.0.0-edit/src/marked.js 2020-04-25 22:42:55.140924439 +0000
@@ -8,3 +8,2 @@
merge,
- checkSanitizeDeprecation,
escape
@@ -37,3 +36,2 @@
opt = merge({}, marked.defaults, opt || {});
- checkSanitizeDeprecation(opt);
const highlight = opt.highlight;
@@ -101,6 +99,5 @@
opt = merge({}, marked.defaults, opt || {});
- checkSanitizeDeprecation(opt);
return Parser.parse(Lexer.lex(src, opt), opt);
} catch (e) {
- e.message += '\nPlease report this to https://github.com/markedjs/marked.';
+ e.message += '\nmake issue @ https://github.com/9001/copyparty';
if ((opt || marked.defaults).silent) {
diff -NarU1 marked-1.0.0-orig/src/Renderer.js marked-1.0.0-edit/src/Renderer.js
--- marked-1.0.0-orig/src/Renderer.js 2020-04-21 01:03:48.000000000 +0000
+++ marked-1.0.0-edit/src/Renderer.js 2020-04-25 18:59:15.091319265 +0000
@@ -134,3 +134,3 @@
link(href, title, text) {
- href = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
+ href = cleanUrl(this.options.baseUrl, href);
if (href === null) {
@@ -147,3 +147,3 @@
image(href, title, text) {
- href = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
+ href = cleanUrl(this.options.baseUrl, href);
if (href === null) {
diff -NarU1 marked-1.0.0-orig/src/Tokenizer.js marked-1.0.0-edit/src/Tokenizer.js
--- marked-1.0.0-orig/src/Tokenizer.js 2020-04-21 01:03:48.000000000 +0000
+++ marked-1.0.0-edit/src/Tokenizer.js 2020-04-25 22:47:07.610917004 +0000
@@ -256,9 +256,6 @@
return {
- type: this.options.sanitize
- ? 'paragraph'
- : 'html',
- raw: cap[0],
- pre: !this.options.sanitizer
- && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'),
- text: this.options.sanitize ? (this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape(cap[0])) : cap[0]
+ type: 'html',
+ raw: cap[0],
+ pre: cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style',
+ text: cap[0]
};
@@ -382,5 +379,3 @@
return {
- type: this.options.sanitize
- ? 'text'
- : 'html',
+ type: 'html',
raw: cap[0],
@@ -388,7 +383,3 @@
inRawBlock,
- text: this.options.sanitize
- ? (this.options.sanitizer
- ? this.options.sanitizer(cap[0])
- : escape(cap[0]))
- : cap[0]
+ text: cap[0]
};
@@ -504,3 +495,3 @@
- autolink(src, mangle) {
+ autolink(src) {
const cap = this.rules.inline.autolink.exec(src);
@@ -509,3 +500,3 @@
if (cap[2] === '@') {
- text = escape(this.options.mangle ? mangle(cap[1]) : cap[1]);
+ text = escape(cap[1]);
href = 'mailto:' + text;
@@ -532,3 +523,3 @@
- url(src, mangle) {
+ url(src) {
let cap;
@@ -537,3 +528,3 @@
if (cap[2] === '@') {
- text = escape(this.options.mangle ? mangle(cap[0]) : cap[0]);
+ text = escape(cap[0]);
href = 'mailto:' + text;
@@ -569,3 +560,3 @@
- inlineText(src, inRawBlock, smartypants) {
+ inlineText(src, inRawBlock) {
const cap = this.rules.inline.text.exec(src);
@@ -574,5 +565,5 @@
if (inRawBlock) {
- text = this.options.sanitize ? (this.options.sanitizer ? this.options.sanitizer(cap[0]) : escape(cap[0])) : cap[0];
+ text = cap[0];
} else {
- text = escape(this.options.smartypants ? smartypants(cap[0]) : cap[0]);
+ text = escape(cap[0]);
}
diff -NarU1 marked-1.0.0-orig/test/bench.js marked-1.0.0-edit/test/bench.js
--- marked-1.0.0-orig/test/bench.js 2020-04-21 01:03:48.000000000 +0000
+++ marked-1.0.0-edit/test/bench.js 2020-04-25 19:02:27.227980287 +0000
@@ -34,3 +34,2 @@
pedantic: false,
- sanitize: false,
smartLists: false
@@ -46,3 +45,2 @@
pedantic: false,
- sanitize: false,
smartLists: false
@@ -59,3 +57,2 @@
pedantic: false,
- sanitize: false,
smartLists: false
@@ -71,3 +68,2 @@
pedantic: false,
- sanitize: false,
smartLists: false
@@ -84,3 +80,2 @@
pedantic: true,
- sanitize: false,
smartLists: false
@@ -96,3 +91,2 @@
pedantic: true,
- sanitize: false,
smartLists: false
diff -NarU1 marked-1.0.0-orig/test/specs/run-spec.js marked-1.0.0-edit/test/specs/run-spec.js
--- marked-1.0.0-orig/test/specs/run-spec.js 2020-04-21 01:03:48.000000000 +0000
+++ marked-1.0.0-edit/test/specs/run-spec.js 2020-04-25 19:05:24.321308408 +0000
@@ -21,6 +21,2 @@
}
- if (spec.options.sanitizer) {
- // eslint-disable-next-line no-eval
- spec.options.sanitizer = eval(spec.options.sanitizer);
- }
(spec.only ? fit : (spec.skip ? xit : it))('should ' + passFail + example, async() => {
@@ -49,2 +45 @@
runSpecs('ReDOS', './redos');
-runSpecs('Security', './security', false, { silent: true }); // silent - do not show deprecation warning
diff -NarU1 marked-1.0.0-orig/test/unit/Lexer-spec.js marked-1.0.0-edit/test/unit/Lexer-spec.js
--- marked-1.0.0-orig/test/unit/Lexer-spec.js 2020-04-21 01:03:48.000000000 +0000
+++ marked-1.0.0-edit/test/unit/Lexer-spec.js 2020-04-25 22:47:27.170916427 +0000
@@ -464,3 +464,3 @@
- it('sanitize', () => {
+ /*it('sanitize', () => {
expectTokens({
@@ -482,3 +482,3 @@
});
- });
+ });*/
});
@@ -586,3 +586,3 @@
- it('html sanitize', () => {
+ /*it('html sanitize', () => {
expectInlineTokens({
@@ -596,3 +596,3 @@
});
- });
+ });*/
@@ -825,3 +825,3 @@
- it('autolink mangle email', () => {
+ /*it('autolink mangle email', () => {
expectInlineTokens({
@@ -845,3 +845,3 @@
});
- });
+ });*/
@@ -882,3 +882,3 @@
- it('url mangle email', () => {
+ /*it('url mangle email', () => {
expectInlineTokens({
@@ -902,3 +902,3 @@
});
- });
+ });*/
});
@@ -918,3 +918,3 @@
- describe('smartypants', () => {
+ /*describe('smartypants', () => {
it('single quotes', () => {
@@ -988,3 +988,3 @@
});
- });
+ });*/
});

View file

@ -0,0 +1,214 @@
diff -NarU1 showdown-orig/Gruntfile.js showdown-mod/Gruntfile.js
--- showdown-orig/Gruntfile.js 2020-04-23 06:22:01.486676149 +0000
+++ showdown-mod/Gruntfile.js 2020-04-23 08:03:56.700219788 +0000
@@ -27,3 +27,2 @@
'src/subParsers/*.js',
- 'src/subParsers/makeMarkdown/*.js',
'src/loader.js'
diff -NarU1 showdown-orig/src/converter.js showdown-mod/src/converter.js
--- showdown-orig/src/converter.js 2020-04-23 06:22:01.496676150 +0000
+++ showdown-mod/src/converter.js 2020-04-23 08:20:11.056920123 +0000
@@ -84,5 +84,5 @@
- if (options.extensions) {
+ /*if (options.extensions) {
showdown.helper.forEach(options.extensions, _parseExtension);
- }
+ }*/
}
@@ -95,3 +95,3 @@
*/
- function _parseExtension (ext, name) {
+ /*function _parseExtension (ext, name) {
@@ -159,3 +159,3 @@
*/
- function legacyExtensionLoading (ext, name) {
+ /*function legacyExtensionLoading (ext, name) {
if (typeof ext === 'function') {
@@ -351,3 +351,3 @@
*/
- this.makeMarkdown = this.makeMd = function (src, HTMLParser) {
+ /*this.makeMarkdown = this.makeMd = function (src, HTMLParser) {
@@ -482,3 +482,3 @@
*/
- this.addExtension = function (extension, name) {
+ /*this.addExtension = function (extension, name) {
name = name || null;
@@ -491,3 +491,3 @@
*/
- this.useExtension = function (extensionName) {
+ /*this.useExtension = function (extensionName) {
_parseExtension(extensionName);
@@ -526,3 +526,3 @@
*/
- this.removeExtension = function (extension) {
+ /*this.removeExtension = function (extension) {
if (!showdown.helper.isArray(extension)) {
@@ -549,3 +549,3 @@
*/
- this.getAllExtensions = function () {
+ /*this.getAllExtensions = function () {
return {
diff -NarU1 showdown-orig/src/options.js showdown-mod/src/options.js
--- showdown-orig/src/options.js 2020-04-23 06:22:01.496676150 +0000
+++ showdown-mod/src/options.js 2020-04-23 08:24:29.176929018 +0000
@@ -118,3 +118,3 @@
},
- ghMentions: {
+ /*ghMentions: {
defaultValue: false,
@@ -127,3 +127,3 @@
type: 'string'
- },
+ },*/
encodeEmails: {
diff -NarU1 showdown-orig/src/showdown.js showdown-mod/src/showdown.js
--- showdown-orig/src/showdown.js 2020-04-23 06:22:01.496676150 +0000
+++ showdown-mod/src/showdown.js 2020-04-23 08:25:01.976930148 +0000
@@ -7,3 +7,2 @@
parsers = {},
- extensions = {},
globalOptions = getDefaultOpts(true),
@@ -25,5 +24,4 @@
ghCompatibleHeaderId: true,
- ghMentions: true,
+ //ghMentions: true,
backslashEscapesHTMLTags: true,
- emoji: true,
splitAdjacentBlockquotes: true
@@ -48,3 +46,3 @@
requireSpaceBeforeHeadingText: true,
- ghMentions: false,
+ //ghMentions: false,
encodeEmails: true
@@ -65,3 +63,2 @@
*/
-showdown.extensions = {};
@@ -193,3 +190,3 @@
*/
-showdown.extension = function (name, ext) {
+/*showdown.extension = function (name, ext) {
'use strict';
@@ -235,3 +232,3 @@
*/
-showdown.getAllExtensions = function () {
+/*showdown.getAllExtensions = function () {
'use strict';
@@ -244,3 +241,3 @@
*/
-showdown.removeExtension = function (name) {
+/*showdown.removeExtension = function (name) {
'use strict';
@@ -252,3 +249,3 @@
*/
-showdown.resetExtensions = function () {
+/*showdown.resetExtensions = function () {
'use strict';
@@ -263,3 +260,3 @@
*/
-function validate (extension, name) {
+/*function validate (extension, name) {
'use strict';
@@ -370,3 +367,3 @@
*/
-showdown.validateExtension = function (ext) {
+/*showdown.validateExtension = function (ext) {
'use strict';
@@ -380 +377,2 @@
};
+*/
diff -NarU1 showdown-orig/src/subParsers/anchors.js showdown-mod/src/subParsers/anchors.js
--- showdown-orig/src/subParsers/anchors.js 2020-04-23 06:22:01.496676150 +0000
+++ showdown-mod/src/subParsers/anchors.js 2020-04-23 08:25:26.880264347 +0000
@@ -76,3 +76,3 @@
// Lastly handle GithubMentions if option is enabled
- if (options.ghMentions) {
+ /*if (options.ghMentions) {
text = text.replace(/(^|\s)(\\)?(@([a-z\d]+(?:[a-z\d.-]+?[a-z\d]+)*))/gmi, function (wm, st, escape, mentions, username) {
@@ -93,3 +93,3 @@
});
- }
+ }*/
diff -NarU1 showdown-orig/src/subParsers/spanGamut.js showdown-mod/src/subParsers/spanGamut.js
--- showdown-orig/src/subParsers/spanGamut.js 2020-04-23 06:22:01.496676150 +0000
+++ showdown-mod/src/subParsers/spanGamut.js 2020-04-23 08:07:50.460227880 +0000
@@ -22,3 +22,2 @@
text = showdown.subParser('simplifiedAutoLinks')(text, options, globals);
- text = showdown.subParser('emoji')(text, options, globals);
text = showdown.subParser('underline')(text, options, globals);
@@ -26,3 +25,2 @@
text = showdown.subParser('strikethrough')(text, options, globals);
- text = showdown.subParser('ellipsis')(text, options, globals);
diff -NarU1 showdown-orig/test/node/showdown.Converter.js showdown-mod/test/node/showdown.Converter.js
--- showdown-orig/test/node/showdown.Converter.js 2020-04-23 06:22:01.520009484 +0000
+++ showdown-mod/test/node/showdown.Converter.js 2020-04-23 08:14:58.086909318 +0000
@@ -29,3 +29,3 @@
- describe('Converter.options extensions', function () {
+ /*describe('Converter.options extensions', function () {
var runCount;
@@ -48,3 +48,3 @@
});
- });
+ });*/
@@ -115,3 +115,3 @@
- describe('extension methods', function () {
+ /*describe('extension methods', function () {
var extObjMock = {
@@ -145,3 +145,3 @@
});
- });
+ });*/
diff -NarU1 showdown-orig/test/node/showdown.js showdown-mod/test/node/showdown.js
--- showdown-orig/test/node/showdown.js 2020-04-23 06:22:01.523342816 +0000
+++ showdown-mod/test/node/showdown.js 2020-04-23 08:14:31.733575073 +0000
@@ -25,3 +25,3 @@
-describe('showdown.extension()', function () {
+/*describe('showdown.extension()', function () {
'use strict';
@@ -110,3 +110,3 @@
});
-});
+});*/
diff -NarU1 showdown-orig/test/node/testsuite.features.js showdown-mod/test/node/testsuite.features.js
--- showdown-orig/test/node/testsuite.features.js 2020-04-23 06:22:01.523342816 +0000
+++ showdown-mod/test/node/testsuite.features.js 2020-04-23 08:25:48.880265106 +0000
@@ -13,3 +13,2 @@
rawPrefixHeaderIdSuite = bootstrap.getTestSuite('test/features/rawPrefixHeaderId/'),
- emojisSuite = bootstrap.getTestSuite('test/features/emojis/'),
underlineSuite = bootstrap.getTestSuite('test/features/underline/'),
@@ -69,4 +68,4 @@
converter = new showdown.Converter({ghCompatibleHeaderId: true});
- } else if (testsuite[i].name === 'ghMentions') {
- converter = new showdown.Converter({ghMentions: true});
+ //} else if (testsuite[i].name === 'ghMentions') {
+ // converter = new showdown.Converter({ghMentions: true});
} else if (testsuite[i].name === 'disable-email-encoding') {
@@ -185,17 +184,2 @@
it(suite[i].name.replace(/-/g, ' '), assertion(suite[i], converter));
- }
- });
-
- /** test emojis support **/
- describe('emojis support', function () {
- var converter,
- suite = emojisSuite;
- for (var i = 0; i < suite.length; ++i) {
- if (suite[i].name === 'simplifiedautolinks') {
- converter = new showdown.Converter({emoji: true, simplifiedAutoLink: true});
- } else {
- converter = new showdown.Converter({emoji: true});
- }
-
- it(suite[i].name.replace(/-/g, ' '), assertion(suite[i], converter));
}

155
srv/test.md Normal file
View file

@ -0,0 +1,155 @@
*fails marked/showdown/tui/simplemde (just italics), **OK: markdown-it/simplemde:***
testing just google.com and underscored _google.com_ also with _google.com,_ trailing comma and _google.com_, comma after
*fails tui (just italics), **OK: marked/showdown/markdown-it/simplemde:***
testing just https://google.com and underscored _https://google.com_ links like that
*fails marked (no markup) and showdown/tui/simplemde (no links at all), **OK: markdown-it:***
let's try <google.com> bracketed and _<google.com>_ underscored bracketed
*fails marked (literal underscore), **OK: showdown/markdown-it/simplemde:***
let's try <https://google.com> bracketed and _<https://google.com>_ underscored bracketed
*fails none:*
and then [google](google.com) verbose and _[google](google.com)_ underscored
*fails none:*
and then [google](https://google.com/) verbose and _[google](https://google.com/)_ underscored
*all behave similarly (only verbose ones):*
and then <local> or maybe <./local> fsgfds </absolute> fsgfds
and then [local] or maybe [./local] fsgfds [/absolute] fsgfds
and then (local) or maybe (./local) fsgfds (/absolute) fsgfds
and then [](local) or maybe [](./local) fsgfds [](/absolute) fsgfds
and then [.](local) or maybe [.](./local) fsgfds [.](/absolute) fsgfds
and then [asdf](local) or maybe [asdf](./local) fsgfds [asdf](/absolute) fsgfds
*`ng/OK/OK/OK markdown-it`
`ng/OK/ng/OK marked`
`ng/OK/OK/OK showdown`
`OK/OK/OK/OK simplemde`*
[with spaces](/with spaces) plain, [with spaces](/with%20spaces) %20, [with spaces](</with spaces>) brackets, [with spaces](/with%20spaces) %20
*this fails marked, **OK: markdown-it, simplemde:***
* testing a list with:
`some code after a newline`
* testing a list with:
just a newline
and here is really just
a newline toplevel
*this fails showdown/hypermd, **OK: marked/markdown-it/simplemde:***
* testing a list with
code here
and a newline
this should have two leading spaces
* second list level
more code here
and a newline
this should have two leading spaces
.
* testing a list with
code here
and a newline
this should have two leading spaces
* second list level
more code here
and a newline
this should have two leading spaces
*this fails stackedit, **OK: showdown/marked/markdown-it/simplemde:***
|||
|--|--|
| a table | with no header |
| second row | foo bar |
*this fails showdown/stackedit, **OK: marked/markdown-it/simplemde:***
|||
|--|--:|
| a table | on the right |
| second row | foo bar |
* list entry
* [x] yes
* [ ] no
* another entry
# s1
## ep1
## ep2
# s2
## ep1
## ep2
# s3
## ep1
## ep2
#######################################################################
marked:
works in last ff/chrome for xp
bug: config{breaks:true} does nothing in 1.0
use whitespace, no tabs
showdown:
ie6 and ie8 broken, works in last ff/chrome for xp
markdown-it:
works in last ff/chrome for xp
use whitespace, no tabs
no header anchors
tui wysiwyg:
requires links to be <http://> or [title](location)
links:
http://demo.showdownjs.com/
https://marked.js.org/demo/
https://markdown-it.github.io/
https://simplemde.com/
all-pass:
https://github.com/joemccann/dillinger
https://dillinger.io/
uses markdown-it
https://github.com/markdown-it/markdown-it
https://markdown-it.github.io/
almost-all-pass:
https://simplemde.com/
https://github.com/nhn/tui.editor
https://nhn.github.io/tui.editor/latest/tutorial-example01-editor-basic
ie10 and up
unrelated neat stuff:
https://github.com/gnab/remark