From f6f095b3816da7d3b1cbd45106af0065a79a9f5c 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 --- ghost/admin/markdown-actions.js | 50 ++++++++++++++++++++++++++++++--- ghost/admin/views/editor.js | 7 ++++- 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/ghost/admin/markdown-actions.js b/ghost/admin/markdown-actions.js index 11157ec743..3c2325470b 100644 --- a/ghost/admin/markdown-actions.js +++ b/ghost/admin/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/ghost/admin/views/editor.js b/ghost/admin/views/editor.js index 3e89b03235..547905e18b 100644 --- a/ghost/admin/views/editor.js +++ b/ghost/admin/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 3fccf8ad5daca86d6efd1ac145d734a23b795496 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 --- ghost/admin/assets/vendor/to-title-case.js | 22 ++++++++++++++++++++++ ghost/admin/markdown-actions.js | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 ghost/admin/assets/vendor/to-title-case.js diff --git a/ghost/admin/assets/vendor/to-title-case.js b/ghost/admin/assets/vendor/to-title-case.js new file mode 100644 index 0000000000..cdb561e718 --- /dev/null +++ b/ghost/admin/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/ghost/admin/markdown-actions.js b/ghost/admin/markdown-actions.js index 3c2325470b..bc8ce43cef 100644 --- a/ghost/admin/markdown-actions.js +++ b/ghost/admin/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(); From cd1835a3cfece542ba3a5e3df0ec747c2f00a035 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. --- ghost/admin/markdown-actions.js | 10 ++++++++-- ghost/admin/views/editor.js | 4 +++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/ghost/admin/markdown-actions.js b/ghost/admin/markdown-actions.js index bc8ce43cef..bf14ab3447 100644 --- a/ghost/admin/markdown-actions.js +++ b/ghost/admin/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/ghost/admin/views/editor.js b/ghost/admin/views/editor.js index 547905e18b..1a74cc3177 100644 --- a/ghost/admin/views/editor.js +++ b/ghost/admin/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