From 229e1850ab4e6f1257c9a2a82d8469b5dc826ae1 Mon Sep 17 00:00:00 2001 From: Ben Hadley-Evans Date: Fri, 20 Mar 2015 16:46:03 +0000 Subject: [PATCH] Improve the italic and bold buttons on multiline selections. This misuses the system that Pagedown has set up somewhat, but it has to in order to affect the content inside the selection. The end behaviour seems to me to be non-buggy and much more obvious to an end user. Essentially, instead of performing the operation to surround characters on one line, it splits the selection into lines the loops the operation. But usually a single "chunk" is returned with some replacement text and markdown to insert before and after the text. Because we're replacing text inside the selections the before and after are left blank and the selection contains all the changed markdown. --- .../discourse/lib/Markdown.Editor.js | 82 +++++++++++-------- 1 file changed, 50 insertions(+), 32 deletions(-) diff --git a/app/assets/javascripts/discourse/lib/Markdown.Editor.js b/app/assets/javascripts/discourse/lib/Markdown.Editor.js index 6e5c1185d43..f954250b8b5 100644 --- a/app/assets/javascripts/discourse/lib/Markdown.Editor.js +++ b/app/assets/javascripts/discourse/lib/Markdown.Editor.js @@ -1542,57 +1542,75 @@ }; commandProto.doBold = function (chunk, postProcessing) { - return this.doBorI(chunk, postProcessing, 2, this.getString("boldexample")); + return this.doSurroundLines(chunk, postProcessing, 2, this.getString("boldexample")); }; commandProto.doItalic = function (chunk, postProcessing) { - return this.doBorI(chunk, postProcessing, 1, this.getString("italicexample")); + return this.doSurroundLines(chunk, postProcessing, 1, this.getString("italicexample")); }; - // chunk: The selected region that will be enclosed with */** + commandProto.doSurroundLines = function(realChunk, postProcessing, nStars, fallbackText) { + realChunk.trimWhitespace(); + + // Look for stars before and after, absorb them into the selection. + var starsBefore = /(\**$)/.exec(realChunk.before)[0]; + var starsAfter = /(^\**)/.exec(realChunk.after)[0]; + + realChunk.before = realChunk.before.replace(/(\**$)/, ""); + realChunk.after = realChunk.after.replace(/(^\**)/, ""); + + var lines = (starsBefore + realChunk.selection + starsAfter).split("\n"); + + // Don't show the fallback text if more than one line is selected, + // it's probably a break between paragraphs. + if(lines.length > 1) { + fallbackText = "" + } + + for(var i=0; i= nStars) && (prevStars != 2 || nStars != 1)) { + if ((minStars >= nStars) && (minStars != 2 || nStars != 1)) { chunk.before = chunk.before.replace(re("[*]{" + nStars + "}$", ""), ""); chunk.after = chunk.after.replace(re("^[*]{" + nStars + "}", ""), ""); } - else if (!chunk.selection && starsAfter) { - // It's not really clear why this code is necessary. It just moves - // some arbitrary stuff around. - chunk.after = chunk.after.replace(/^([*_]*)/, ""); - chunk.before = chunk.before.replace(/(\s?)$/, ""); - var whitespace = re.$1; - chunk.before = chunk.before + starsAfter + whitespace; - } else { - // In most cases, if you don't have any selected text and click the button // you'll get a selected, marked up region with the default text inserted. - if (!chunk.selection && !starsAfter) { - chunk.selection = insertText; + if (!chunk.selection && !chunk.after) { + chunk.selection = fallbackText; } - // Add the true markup. - var markup = nStars <= 1 ? "*" : "**"; // shouldn't the test be = ? - chunk.before = chunk.before + markup; - chunk.after = markup + chunk.after; + // Only operate if it's not a blank line + if(chunk.selection) { + // Add the true markup. + var markup = nStars === 1 ? "*" : "**"; + chunk.before = chunk.before + markup; + chunk.after = markup + chunk.after; + } } - - return; }; commandProto.stripLinkDefs = function (text, defsToAdd) {