--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_skin/resources/js/ext/tinymce/dev/plugins/textpattern/plugin.js Wed Jun 17 10:00:10 2015 +0200
@@ -0,0 +1,268 @@
+/**
+ * plugin.js
+ *
+ * Copyright, Moxiecode Systems AB
+ * Released under LGPL License.
+ *
+ * License: http://www.tinymce.com/license
+ * Contributing: http://www.tinymce.com/contributing
+ */
+
+/*global tinymce:true */
+
+tinymce.PluginManager.add('textpattern', function(editor) {
+ var isPatternsDirty = true, patterns;
+
+ patterns = editor.settings.textpattern_patterns || [
+ {start: '*', end: '*', format: 'italic'},
+ {start: '**', end: '**', format: 'bold'},
+ {start: '#', format: 'h1'},
+ {start: '##', format: 'h2'},
+ {start: '###', format: 'h3'},
+ {start: '####', format: 'h4'},
+ {start: '#####', format: 'h5'},
+ {start: '######', format: 'h6'},
+ {start: '1. ', cmd: 'InsertOrderedList'},
+ {start: '* ', cmd: 'InsertUnorderedList'},
+ {start: '- ', cmd: 'InsertUnorderedList'}
+ ];
+
+ // Returns a sorted patterns list, ordered descending by start length
+ function getPatterns() {
+ if (isPatternsDirty) {
+ patterns.sort(function(a, b) {
+ if (a.start.length > b.start.length) {
+ return -1;
+ }
+
+ if (a.start.length < b.start.length) {
+ return 1;
+ }
+
+ return 0;
+ });
+
+ isPatternsDirty = false;
+ }
+
+ return patterns;
+ }
+
+ // Finds a matching pattern to the specified text
+ function findPattern(text) {
+ var patterns = getPatterns();
+
+ for (var i = 0; i < patterns.length; i++) {
+ if (text.indexOf(patterns[i].start) !== 0) {
+ continue;
+ }
+
+ if (patterns[i].end && text.lastIndexOf(patterns[i].end) != text.length - patterns[i].end.length) {
+ continue;
+ }
+
+ return patterns[i];
+ }
+ }
+
+ // Finds the best matching end pattern
+ function findEndPattern(text, offset, delta) {
+ var patterns, pattern, i;
+
+ // Find best matching end
+ patterns = getPatterns();
+ for (i = 0; i < patterns.length; i++) {
+ pattern = patterns[i];
+ if (pattern.end && text.substr(offset - pattern.end.length - delta, pattern.end.length) == pattern.end) {
+ return pattern;
+ }
+ }
+ }
+
+ // Handles inline formats like *abc* and **abc**
+ function applyInlineFormat(space) {
+ var selection, dom, rng, container, offset, startOffset, text, patternRng, pattern, delta, format;
+
+ function splitContainer() {
+ // Split text node and remove start/end from text node
+ container = container.splitText(startOffset);
+ container.splitText(offset - startOffset - delta);
+ container.deleteData(0, pattern.start.length);
+ container.deleteData(container.data.length - pattern.end.length, pattern.end.length);
+ }
+
+ selection = editor.selection;
+ dom = editor.dom;
+
+ if (!selection.isCollapsed()) {
+ return;
+ }
+
+ rng = selection.getRng(true);
+ container = rng.startContainer;
+ offset = rng.startOffset;
+ text = container.data;
+ delta = space ? 1 : 0;
+
+ if (container.nodeType != 3) {
+ return;
+ }
+
+ // Find best matching end
+ pattern = findEndPattern(text, offset, delta);
+ if (!pattern) {
+ return;
+ }
+
+ // Find start of matched pattern
+ // TODO: Might need to improve this if there is nested formats
+ startOffset = Math.max(0, offset - delta);
+ startOffset = text.lastIndexOf(pattern.start, startOffset - pattern.end.length - 1);
+
+ if (startOffset === -1) {
+ return;
+ }
+
+ // Setup a range for the matching word
+ patternRng = dom.createRng();
+ patternRng.setStart(container, startOffset);
+ patternRng.setEnd(container, offset - delta);
+ pattern = findPattern(patternRng.toString());
+
+ if (!pattern || !pattern.end) {
+ return;
+ }
+
+ // If container match doesn't have anything between start/end then do nothing
+ if (container.data.length <= pattern.start.length + pattern.end.length) {
+ return;
+ }
+
+ format = editor.formatter.get(pattern.format);
+ if (format && format[0].inline) {
+ splitContainer();
+ editor.formatter.apply(pattern.format, {}, container);
+ return container;
+ }
+ }
+
+ // Handles block formats like ##abc or 1. abc
+ function applyBlockFormat() {
+ var selection, dom, container, firstTextNode, node, format, textBlockElm, pattern, walker, rng, offset;
+
+ selection = editor.selection;
+ dom = editor.dom;
+
+ if (!selection.isCollapsed()) {
+ return;
+ }
+
+ textBlockElm = dom.getParent(selection.getStart(), 'p');
+ if (textBlockElm) {
+ walker = new tinymce.dom.TreeWalker(textBlockElm, textBlockElm);
+ while ((node = walker.next())) {
+ if (node.nodeType == 3) {
+ firstTextNode = node;
+ break;
+ }
+ }
+
+ if (firstTextNode) {
+ pattern = findPattern(firstTextNode.data);
+ if (!pattern) {
+ return;
+ }
+
+ rng = selection.getRng(true);
+ container = rng.startContainer;
+ offset = rng.startOffset;
+
+ if (firstTextNode == container) {
+ offset = Math.max(0, offset - pattern.start.length);
+ }
+
+ if (tinymce.trim(firstTextNode.data).length == pattern.start.length) {
+ return;
+ }
+
+ if (pattern.format) {
+ format = editor.formatter.get(pattern.format);
+ if (format && format[0].block) {
+ firstTextNode.deleteData(0, pattern.start.length);
+ editor.formatter.apply(pattern.format, {}, firstTextNode);
+
+ rng.setStart(container, offset);
+ rng.collapse(true);
+ selection.setRng(rng);
+ }
+ }
+
+ if (pattern.cmd) {
+ editor.undoManager.transact(function() {
+ firstTextNode.deleteData(0, pattern.start.length);
+ editor.execCommand(pattern.cmd);
+ });
+ }
+ }
+ }
+ }
+
+ function handleEnter() {
+ var rng, wrappedTextNode;
+
+ wrappedTextNode = applyInlineFormat();
+ if (wrappedTextNode) {
+ rng = editor.dom.createRng();
+ rng.setStart(wrappedTextNode, wrappedTextNode.data.length);
+ rng.setEnd(wrappedTextNode, wrappedTextNode.data.length);
+ editor.selection.setRng(rng);
+ }
+
+ applyBlockFormat();
+ }
+
+ function handleSpace() {
+ var wrappedTextNode, lastChar, lastCharNode, rng, dom;
+
+ wrappedTextNode = applyInlineFormat(true);
+ if (wrappedTextNode) {
+ dom = editor.dom;
+ lastChar = wrappedTextNode.data.slice(-1);
+
+ // Move space after the newly formatted node
+ if (/[\u00a0 ]/.test(lastChar)) {
+ wrappedTextNode.deleteData(wrappedTextNode.data.length - 1, 1);
+ lastCharNode = dom.doc.createTextNode(lastChar);
+
+ if (wrappedTextNode.nextSibling) {
+ dom.insertAfter(lastCharNode, wrappedTextNode.nextSibling);
+ } else {
+ wrappedTextNode.parentNode.appendChild(lastCharNode);
+ }
+
+ rng = dom.createRng();
+ rng.setStart(lastCharNode, 1);
+ rng.setEnd(lastCharNode, 1);
+ editor.selection.setRng(rng);
+ }
+ }
+ }
+
+ editor.on('keydown', function(e) {
+ if (e.keyCode == 13 && !tinymce.util.VK.modifierPressed(e)) {
+ handleEnter();
+ }
+ }, true);
+
+ editor.on('keyup', function(e) {
+ if (e.keyCode == 32 && !tinymce.util.VK.modifierPressed(e)) {
+ handleSpace();
+ }
+ });
+
+ this.getPatterns = getPatterns;
+ this.setPatterns = function(newPatterns) {
+ patterns = newPatterns;
+ isPatternsDirty = true;
+ };
+});
\ No newline at end of file