From 9fd653738dc7c5fd1b4d4f1044d15eadecf90333 Mon Sep 17 00:00:00 2001 From: Matthew Harrison-Jones Date: Thu, 18 Jul 2013 14:02:54 +0100 Subject: [PATCH 1/3] Additional Keyboard Shortcuts and improvements to text highlighting This fixes the event where text would be selected after manipulation from shortcut, the cursor is now placed after the text. On links and images the url field text is highlighted. Additional shortcuts; * Ctrl+U: Make text uppercase * Ctrl+Shift+U: Make text lowercase * Ctrl+Alt+Shift+U: Make text titlecase * Ctrl+Alt+W: Select word * Ctrl+L: Make into list --- core/client/markdown-actions.js | 50 ++++++++++++++++++++++++++++++--- core/client/views/editor.js | 7 ++++- 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/core/client/markdown-actions.js b/core/client/markdown-actions.js index 11157ec743..3c2325470b 100644 --- a/core/client/markdown-actions.js +++ b/core/client/markdown-actions.js @@ -15,10 +15,52 @@ self.replace(); }, replace: function () { - var text = this.elem.getSelection(), md; - if (this.options.syntax[this.style]) { - md = this.options.syntax[this.style].replace('$1', text); - this.elem.replaceSelection(md); + var text = this.elem.getSelection(), pass = true, md, cursor, word; + switch (this.style) { + case "link": + md = this.options.syntax.link.replace('$1', text); + this.elem.replaceSelection(md, "end"); + cursor = this.elem.getCursor(); + this.elem.setSelection({line: cursor.line, ch: cursor.ch - 8}, {line: cursor.line, ch: cursor.ch - 1}); + pass = false; + break; + case "image": + md = this.options.syntax.image.replace('$1', text); + this.elem.replaceSelection(md, "end"); + cursor = this.elem.getCursor(); + this.elem.setSelection({line: cursor.line, ch: cursor.ch - 8}, {line: cursor.line, ch: cursor.ch - 1}); + pass = false; + break; + case "uppercase": + md = text.toLocaleUpperCase(); + break; + case "lowercase": + md = text.toLocaleLowerCase(); + break; + case "titlecase": + md = text.replace(/\w\S*/g, function (text) {return text.charAt(0).toUpperCase() + text.substr(1).toLowerCase(); }); + break; + case "selectword": + cursor = this.elem.getCursor(); + word = this.elem.getTokenAt(cursor); + if (!/\w$/g.test(word.string)) { + this.elem.setSelection({line: cursor.line, ch: word.start}, {line: cursor.line, ch: word.end - 1}); + } else { + this.elem.setSelection({line: cursor.line, ch: word.start}, {line: cursor.line, ch: word.end}); + } + break; + case "list": + md = text.replace(/^/gm, "* "); + this.elem.replaceSelection("\n" + md + "\n", "end"); + pass = false; + break; + default: + if (this.options.syntax[this.style]) { + md = this.options.syntax[this.style].replace('$1', text); + } + } + if (pass && md) { + this.elem.replaceSelection(md, "end"); } } }; diff --git a/core/client/views/editor.js b/core/client/views/editor.js index 3e89b03235..547905e18b 100644 --- a/core/client/views/editor.js +++ b/core/client/views/editor.js @@ -23,7 +23,12 @@ {'key': 'Ctrl+Shift+L', 'style': 'link'}, {'key': 'Ctrl+Shift+I', 'style': 'image'}, {'key': 'Ctrl+Q', 'style': 'blockquote'}, - {'key': 'Ctrl+Shift+1', 'style': 'currentdate'} + {'key': 'Ctrl+Shift+1', 'style': 'currentdate'}, + {'key': 'Ctrl+U', 'style': 'uppercase'}, + {'key': 'Ctrl+Shift+U', 'style': 'lowercase'}, + {'key': 'Ctrl+Alt+Shift+U', 'style': 'titlecase'}, + {'key': 'Ctrl+Alt+W', 'style': 'selectword'}, + {'key': 'Ctrl+L', 'style': 'list'} ]; // The publish bar associated with a post, which has the TagWidget and From f85bbd5422e1bcd9ed801c4824b3299a38223731 Mon Sep 17 00:00:00 2001 From: Matthew Harrison-Jones Date: Thu, 18 Jul 2013 14:42:16 +0100 Subject: [PATCH 2/3] Improve title casing --- core/client/assets/vendor/to-title-case.js | 22 ++++++++++++++++++++++ core/client/markdown-actions.js | 2 +- core/server/views/default.hbs | 1 + 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 core/client/assets/vendor/to-title-case.js diff --git a/core/client/assets/vendor/to-title-case.js b/core/client/assets/vendor/to-title-case.js new file mode 100644 index 0000000000..cdb561e718 --- /dev/null +++ b/core/client/assets/vendor/to-title-case.js @@ -0,0 +1,22 @@ +/* + * To Title Case 2.0.1 – http://individed.com/code/to-title-case/ + * Copyright © 2008–2012 David Gouch. Licensed under the MIT License. + */ + +String.prototype.toTitleCase = function () { + var smallWords = /^(a|an|and|as|at|but|by|en|for|if|in|of|on|or|the|to|vs?\.?|via)$/i; + + return this.replace(/([^\W_]+[^\s-]*) */g, function (match, p1, index, title) { + if (index > 0 && index + p1.length !== title.length && + p1.search(smallWords) > -1 && title.charAt(index - 2) !== ":" && + title.charAt(index - 1).search(/[^\s-]/) < 0) { + return match.toLowerCase(); + } + + if (p1.substr(1).search(/[A-Z]|\../) > -1) { + return match; + } + + return match.charAt(0).toUpperCase() + match.substr(1); + }); +}; \ No newline at end of file diff --git a/core/client/markdown-actions.js b/core/client/markdown-actions.js index 3c2325470b..bc8ce43cef 100644 --- a/core/client/markdown-actions.js +++ b/core/client/markdown-actions.js @@ -38,7 +38,7 @@ md = text.toLocaleLowerCase(); break; case "titlecase": - md = text.replace(/\w\S*/g, function (text) {return text.charAt(0).toUpperCase() + text.substr(1).toLowerCase(); }); + md = text.toTitleCase(); break; case "selectword": cursor = this.elem.getCursor(); diff --git a/core/server/views/default.hbs b/core/server/views/default.hbs index 51ac5ae425..67b1118cb0 100644 --- a/core/server/views/default.hbs +++ b/core/server/views/default.hbs @@ -44,6 +44,7 @@ + From 4b5932bef2fb13e7eb7bd4c2d7580c44bed5ff76 Mon Sep 17 00:00:00 2001 From: Matthew Harrison-Jones Date: Mon, 22 Jul 2013 13:50:50 +0100 Subject: [PATCH 3/3] Added the ability to copy as HTML. --- core/client/markdown-actions.js | 10 ++++++++-- core/client/views/editor.js | 4 +++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/core/client/markdown-actions.js b/core/client/markdown-actions.js index bc8ce43cef..bf14ab3447 100644 --- a/core/client/markdown-actions.js +++ b/core/client/markdown-actions.js @@ -1,6 +1,6 @@ // # Surrounds given text with Markdown syntax -/*global $, CodeMirror */ +/*global $, window, CodeMirror, Showdown */ (function () { "use strict"; var Markdown = { @@ -15,7 +15,7 @@ self.replace(); }, replace: function () { - var text = this.elem.getSelection(), pass = true, md, cursor, word; + var text = this.elem.getSelection(), pass = true, md, cursor, word, converter; switch (this.style) { case "link": md = this.options.syntax.link.replace('$1', text); @@ -49,6 +49,12 @@ this.elem.setSelection({line: cursor.line, ch: word.start}, {line: cursor.line, ch: word.end}); } break; + case "copyHTML": + converter = new Showdown.converter(); + md = converter.makeHtml(text); + window.prompt("Copy to clipboard: Ctrl+C, Enter", md); + pass = false; + break; case "list": md = text.replace(/^/gm, "* "); this.elem.replaceSelection("\n" + md + "\n", "end"); diff --git a/core/client/views/editor.js b/core/client/views/editor.js index 547905e18b..1a74cc3177 100644 --- a/core/client/views/editor.js +++ b/core/client/views/editor.js @@ -28,7 +28,9 @@ {'key': 'Ctrl+Shift+U', 'style': 'lowercase'}, {'key': 'Ctrl+Alt+Shift+U', 'style': 'titlecase'}, {'key': 'Ctrl+Alt+W', 'style': 'selectword'}, - {'key': 'Ctrl+L', 'style': 'list'} + {'key': 'Ctrl+L', 'style': 'list'}, + {'key': 'Ctrl+Alt+C', 'style': 'copyHTML'}, + {'key': 'CMD+Alt+C', 'style': 'copyHTML'} ]; // The publish bar associated with a post, which has the TagWidget and