From 706f30033e2084202cbf0606665ff62f167bc588 Mon Sep 17 00:00:00 2001 From: ed Date: Fri, 1 May 2020 19:56:52 +0200 Subject: [PATCH] add linetracking to easymde --- copyparty/web/mde.css | 5 +- copyparty/web/upload.html | 2 +- scripts/deps-docker/Dockerfile | 12 +++- scripts/deps-docker/easymde-ln.patch | 95 ++++++++++++++++++++++++++++ scripts/deps-docker/easymde.patch | 52 +++++++++++++++ 5 files changed, 162 insertions(+), 4 deletions(-) create mode 100644 scripts/deps-docker/easymde-ln.patch create mode 100644 scripts/deps-docker/easymde.patch diff --git a/copyparty/web/mde.css b/copyparty/web/mde.css index 5a1d2786..ad682fbd 100644 --- a/copyparty/web/mde.css +++ b/copyparty/web/mde.css @@ -44,10 +44,13 @@ html, body { color: #000; text-decoration: underline; } - + +/* *[data-ln]:before { content: attr(data-ln); font-size: .8em; margin: 0 .4em; color: #f0c; } +.cm-header { font-size: .4em !important } +*/ \ No newline at end of file diff --git a/copyparty/web/upload.html b/copyparty/web/upload.html index 64110ff8..11a9d853 100644 --- a/copyparty/web/upload.html +++ b/copyparty/web/upload.html @@ -57,5 +57,5 @@

-

( if you don't need resumable uploads and progress bars just use the basic uploader)

+

( if you don't need lastmod timestamps, resumable uploads or progress bars just use the basic uploader)

diff --git a/scripts/deps-docker/Dockerfile b/scripts/deps-docker/Dockerfile index 14dcca49..b3f532d0 100644 --- a/scripts/deps-docker/Dockerfile +++ b/scripts/deps-docker/Dockerfile @@ -106,10 +106,16 @@ RUN cd marked-$ver_marked \ # build easymde (TODO man this thing is big) +COPY easymde.patch /z/ RUN cd easy-markdown-editor-$ver_mde \ + && patch -p1 < /z/easymde.patch \ && 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 \ + && npm install + +COPY easymde-ln.patch /z/ +RUN cd easy-markdown-editor-$ver_mde \ + && patch -p1 < /z/easymde-ln.patch \ && gulp \ && cp -pv dist/easymde.min.css /z/dist/easymde.css \ && cp -pv dist/easymde.min.js /z/dist/easymde.js \ @@ -202,7 +208,9 @@ RUN cd /z/dist \ # 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 +# easymde: +# 91836 orig +# 88635 no spellcheck # 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) diff --git a/scripts/deps-docker/easymde-ln.patch b/scripts/deps-docker/easymde-ln.patch new file mode 100644 index 00000000..a0644f4a --- /dev/null +++ b/scripts/deps-docker/easymde-ln.patch @@ -0,0 +1,95 @@ +diff -NarU2 easymde-mod1/src/js/easymde.js easymde-edit/src/js/easymde.js +--- easymde-mod1/src/js/easymde.js 2020-05-01 14:34:19.878774400 +0200 ++++ easymde-edit/src/js/easymde.js 2020-05-01 19:26:56.843140600 +0200 +@@ -2189,4 +2189,5 @@ + }; + ++ + EasyMDE.prototype.createSideBySide = function () { + var cm = this.codemirror; +@@ -2223,12 +2224,80 @@ + } + pScroll = true; +- var height = v.getScrollInfo().height - v.getScrollInfo().clientHeight; +- var ratio = parseFloat(v.getScrollInfo().top) / height; +- var move = (preview.scrollHeight - preview.clientHeight) * ratio; +- preview.scrollTop = move; ++ var md_vp = v.getScrollInfo(); ++ // viewport top: top ++ // viewport size: clientHeight ++ // document size: height ++ var md_scroll_y = md_vp.top + md_vp.clientHeight / 2; ++ var md_center_n = cm.lineAtHeight(md_scroll_y, 'local') + 1; ++ var md_next_n = md_center_n; ++ var md_top = cm.heightAtLine(md_center_n - 1, 'local'); ++ while (md_next_n < cm.lineCount()) ++ if (cm.getLine(md_next_n++).replace(/\s+/g, '').length > 0) ++ break; ++ var md_end = cm.heightAtLine(md_next_n - 1, 'local'); ++ var md_frac = (md_scroll_y - md_top) * 1.0 / (md_end - md_top); ++ var get_pre_line = function(line_n, increase) { ++ var end = 0; ++ var step = -1; ++ if (increase) { ++ step = 1; ++ end = line_n + 1000; ++ } ++ // there might be multiple elements in the marked.js output, ++ // take the element with the biggest height ++ var biggest = -1; ++ var line_dom = null; ++ for (; line_n != end; line_n += step) { ++ var hits = document.querySelectorAll('.editor-preview-side *[data-ln=\'' + line_n + '\']'); ++ for (var i = 0; i < hits.length; i++) { ++ var hit_size = hits[i].offsetHeight; ++ if (biggest < hit_size) { ++ biggest = hit_size; ++ line_dom = hits[i]; ++ } ++ } ++ if (line_dom) { ++ var ret_y = 0; ++ var el = line_dom; ++ while ((el.getAttribute('class') + '').indexOf('editor-preview-side') < 0) { ++ ret_y += el.offsetTop; ++ el = el.offsetParent; ++ } ++ return [line_n, line_dom, ret_y]; ++ } ++ } ++ return null; ++ }; ++ var pre1 = get_pre_line(md_center_n, false); ++ var pre2 = get_pre_line(pre1[0] + 1, true) || ++ [cm.lineCount(), null, preview.scrollHeight]; ++ ++ console.log('code-center %d, frac %.2f, pre [%d,%d] [%d,%d]', ++ md_center_n, md_frac, pre1[0], pre1[2], pre2[0], pre2[2]); ++ ++ // [0] is the markdown line which matches that preview y-pos ++ // and since not all preview lines are tagged with a line-number ++ // take the lineno diff and divide it by the distance ++ var pre_frac = md_frac / ((pre2[0] - pre1[0]) / (md_next_n - md_center_n)); ++ ++ // then use that fraction for the scroll offset ++ var pre_y = pre1[2] + (pre2[2] - pre1[2]) * pre_frac; ++ ++ // unless we couldn't match the markdown line exactly to any preview line ++ if (md_center_n > pre1[0] && md_center_n < pre2[0]) ++ pre_y = pre2[2]; ++ ++ // except jump to the top or bottom if we're close enough ++ if (md_vp.top < 32) ++ pre_y = 0; ++ else if (md_vp.top + 32 >= md_vp.height - md_vp.clientHeight) ++ pre_y = preview.scrollHeight; ++ ++ preview.scrollTop = pre_y - preview.clientHeight / 2; + }); + + // Syncs scroll preview -> editor +- preview.onscroll = function () { ++ // disabled since it should be possible to intentionally unsync ++ preview.onscroll_fgsfds = function () { + if (pScroll) { + pScroll = false; diff --git a/scripts/deps-docker/easymde.patch b/scripts/deps-docker/easymde.patch new file mode 100644 index 00000000..c60c4f32 --- /dev/null +++ b/scripts/deps-docker/easymde.patch @@ -0,0 +1,52 @@ +diff -NarU2 easymde-orig/gulpfile.js easymde-mod1/gulpfile.js +--- easymde-orig/gulpfile.js 2020-04-06 14:09:36.000000000 +0200 ++++ easymde-mod1/gulpfile.js 2020-05-01 14:33:52.260175200 +0200 +@@ -25,5 +25,4 @@ + './node_modules/codemirror/lib/codemirror.css', + './src/css/*.css', +- './node_modules/codemirror-spell-checker/src/css/spell-checker.css', + ]; + +diff -NarU2 easymde-orig/package.json easymde-mod1/package.json +--- easymde-orig/package.json 2020-04-06 14:09:36.000000000 +0200 ++++ easymde-mod1/package.json 2020-05-01 14:33:57.189975800 +0200 +@@ -21,5 +21,4 @@ + "dependencies": { + "codemirror": "^5.52.2", +- "codemirror-spell-checker": "1.1.2", + "marked": "^0.8.2" + }, +diff -NarU2 easymde-orig/src/js/easymde.js easymde-mod1/src/js/easymde.js +--- easymde-orig/src/js/easymde.js 2020-04-06 14:09:36.000000000 +0200 ++++ easymde-mod1/src/js/easymde.js 2020-05-01 14:34:19.878774400 +0200 +@@ -11,5 +11,4 @@ + require('codemirror/mode/gfm/gfm.js'); + require('codemirror/mode/xml/xml.js'); +-var CodeMirrorSpellChecker = require('codemirror-spell-checker'); + var marked = require('marked/lib/marked'); + +@@ -1889,18 +1888,7 @@ + + var mode, backdrop; +- if (options.spellChecker !== false) { +- mode = 'spell-checker'; +- backdrop = options.parsingConfig; +- backdrop.name = 'gfm'; +- backdrop.gitHubSpice = false; +- +- CodeMirrorSpellChecker({ +- codeMirrorInstance: CodeMirror, +- }); +- } else { + mode = options.parsingConfig; + mode.name = 'gfm'; + mode.gitHubSpice = false; +- } + + // eslint-disable-next-line no-unused-vars +@@ -1927,5 +1915,4 @@ + configureMouse: configureMouse, + inputStyle: (options.inputStyle != undefined) ? options.inputStyle : isMobile() ? 'contenteditable' : 'textarea', +- spellcheck: (options.nativeSpellcheck != undefined) ? options.nativeSpellcheck : true, + }); +