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 11157ec743..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,10 +15,58 @@
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, converter;
+ 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.toTitleCase();
+ 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 "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");
+ 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 e0878de712..b295900c49 100644
--- a/core/client/views/editor.js
+++ b/core/client/views/editor.js
@@ -23,7 +23,14 @@
{'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'},
+ {'key': 'Ctrl+Alt+C', 'style': 'copyHTML'},
+ {'key': 'CMD+Alt+C', 'style': 'copyHTML'}
];
// The publish bar associated with a post, which has the TagWidget and
diff --git a/core/server/views/default.hbs b/core/server/views/default.hbs
index 6221e2b209..92373d9ee6 100644
--- a/core/server/views/default.hbs
+++ b/core/server/views/default.hbs
@@ -45,6 +45,7 @@
+