Commit cde00c55 authored by Robert Lyon's avatar Robert Lyon Committed by Gerrit Code Review

Merge changes I1feb6047,I13901c30

* changes:
  Bug 1672893: Upgrading tinyMCE to v4.5.5, adding customizations
  Bug 1672893: Upgrading TinyMCE library to v4.5.5
parents 8df92d8f b2b23894
......@@ -2,18 +2,27 @@ TinyMCE
========
Website: http://tinymce.moxiecode.com/
Version: 4.3.3
Version: 4.5.5
Based on development version
Changes:
* Added all of the language packs
* Added all of the language packs (original commit: 259a86431ad1140e15288d39702cea885c08f3fe)
* Removed all .min.js and .dev.js files
* Removed all files in 'classes' directory since they're packaged into tinymce.js
* Removed all .less files from skin
* Added code to spellchecker/spellchecker.rpc to use $CFG->spellcheckerengine
* Adjusted the charmap plugin to contain Māori macrons
* Adding the 'aria-hidden="true"' to presentation icons
* Bug 1605110: Modified the "table" plugin to style the table through CSS instead of HTML attributes
* Add TinyMCE imagebrowser plugin: plugins/imagebrowser/plugin.js
\ No newline at end of file
* Removed all .less files from skin (original commit: 442ade4e7c7cf991a4001ab8f7cc9d15e2b25890)
* Added code to spellchecker/spellchecker.rpc to use $CFG->spellcheckerengine (original commit: a42e68b43e4a63db19569facae61898af1b86d3f)
* Adding the 'aria-hidden="true"' to presentation icons (original commit: 4ac89c31a719a9f63be6555c4d1a094fd2b09d0e)
* Bug 1605110: Modified the "table" plugin to style the table through CSS instead of HTML attributes (original commit: 63f91a7ea8bd60c102e257c05678cc6d55e21683)
* Add TinyMCE imagebrowser plugin: plugins/imagebrowser/plugin.js
* Removed
plugins/layer removed in v4.5.0
plugins/media/moxieplayer.swf removed in v4.5.0
tinymce.jquery.js removed in v4.3.4
* Added
plugins/imagebrowser (originally added in commit 36bc9f7d26076d74ebc6cd0672441eed8ed9cd2d)
plugins/mathslate (originally added in commit 325cdfac3dfba40efbbad8cd306dcfb385674709)
plugins/tooltoggle (originally added in commit 2c490a70bfff677c0b95c0565d39162c8c9bc10d)
skins/light (we use it but it's not included in new versions any more)
......@@ -11,20 +11,33 @@
/*global tinymce:true */
tinymce.PluginManager.add('advlist', function(editor) {
var olMenuItems, ulMenuItems, lastStyles = {};
var olMenuItems, ulMenuItems;
var hasPlugin = function (editor, plugin) {
var plugins = editor.settings.plugins ? editor.settings.plugins : '';
return tinymce.util.Tools.inArray(plugins.split(/[ ,]/), plugin) !== -1;
};
function isChildOfBody(elm) {
return editor.$.contains(editor.getBody(), elm);
}
function isListNode(node) {
return node && (/^(OL|UL|DL)$/).test(node.nodeName) && isChildOfBody(node);
}
function buildMenuItems(listName, styleValues) {
var items = [];
tinymce.each(styleValues.split(/[ ,]/), function(styleValue) {
items.push({
text: styleValue.replace(/\-/g, ' ').replace(/\b\w/g, function(chr) {
return chr.toUpperCase();
}),
data: styleValue == 'default' ? '' : styleValue
if (styleValues) {
tinymce.each(styleValues.split(/[ ,]/), function(styleValue) {
items.push({
text: styleValue.replace(/\-/g, ' ').replace(/\b\w/g, function(chr) {
return chr.toUpperCase();
}),
data: styleValue == 'default' ? '' : styleValue
});
});
});
}
return items;
}
......@@ -44,17 +57,23 @@ tinymce.PluginManager.add('advlist', function(editor) {
// Switch/add list type if needed
if (!list || list.nodeName != listName || styleValue === false) {
editor.execCommand(listName == 'UL' ? 'InsertUnorderedList' : 'InsertOrderedList');
}
var detail = {
'list-style-type': styleValue ? styleValue : ''
};
// Set style
styleValue = styleValue === false ? lastStyles[listName] : styleValue;
lastStyles[listName] = styleValue;
editor.execCommand(listName == 'UL' ? 'InsertUnorderedList' : 'InsertOrderedList', false, detail);
}
list = dom.getParent(sel.getNode(), 'ol,ul');
if (list) {
dom.setStyle(list, 'listStyleType', styleValue ? styleValue : null);
list.removeAttribute('data-mce-style');
tinymce.util.Tools.each(dom.select('ol,ul', list).concat([list]), function (list) {
if (list.nodeName !== listName && styleValue !== false) {
list = dom.rename(list, listName);
}
dom.setStyle(list, 'listStyleType', styleValue ? styleValue : null);
list.removeAttribute('data-mce-style');
});
}
editor.focus();
......@@ -69,29 +88,52 @@ tinymce.PluginManager.add('advlist', function(editor) {
});
}
editor.addButton('numlist', {
type: 'splitbutton',
tooltip: 'Numbered list',
menu: olMenuItems,
onshow: updateSelection,
onselect: function(e) {
applyListFormat('OL', e.control.settings.data);
},
onclick: function() {
applyListFormat('OL', false);
}
});
editor.addButton('bullist', {
type: 'splitbutton',
tooltip: 'Bullet list',
menu: ulMenuItems,
onshow: updateSelection,
onselect: function(e) {
applyListFormat('UL', e.control.settings.data);
},
onclick: function() {
applyListFormat('UL', false);
}
});
});
\ No newline at end of file
var listState = function (listName) {
return function () {
var self = this;
editor.on('NodeChange', function (e) {
var lists = tinymce.util.Tools.grep(e.parents, isListNode);
self.active(lists.length > 0 && lists[0].nodeName === listName);
});
};
};
if (hasPlugin(editor, "lists")) {
editor.addCommand('ApplyUnorderedListStyle', function (ui, value) {
applyListFormat('UL', value['list-style-type']);
});
editor.addCommand('ApplyOrderedListStyle', function (ui, value) {
applyListFormat('OL', value['list-style-type']);
});
editor.addButton('numlist', {
type: (olMenuItems.length > 0) ? 'splitbutton' : 'button',
tooltip: 'Numbered list',
menu: olMenuItems,
onPostRender: listState('OL'),
onshow: updateSelection,
onselect: function(e) {
applyListFormat('OL', e.control.settings.data);
},
onclick: function() {
applyListFormat('OL', false);
}
});
editor.addButton('bullist', {
type: (ulMenuItems.length > 0) ? 'splitbutton' : 'button',
tooltip: 'Bullet list',
onPostRender: listState('UL'),
menu: ulMenuItems,
onshow: updateSelection,
onselect: function(e) {
applyListFormat('UL', e.control.settings.data);
},
onclick: function() {
applyListFormat('UL', false);
}
});
}
});
......@@ -11,21 +11,50 @@
/*global tinymce:true */
tinymce.PluginManager.add('anchor', function(editor) {
function showDialog() {
var selectedNode = editor.selection.getNode(), name = '';
var isAnchorNode = function (node) {
return !node.attr('href') && (node.attr('id') || node.attr('name')) && !node.firstChild;
};
var setContentEditable = function (state) {
return function (nodes) {
for (var i = 0; i < nodes.length; i++) {
if (isAnchorNode(nodes[i])) {
nodes[i].attr('contenteditable', state);
}
}
};
};
var isValidId = function (id) {
// Follows HTML4 rules: https://www.w3.org/TR/html401/types.html#type-id
return /^[A-Za-z][A-Za-z0-9\-:._]*$/.test(id);
};
var showDialog = function () {
var selectedNode = editor.selection.getNode();
var isAnchor = selectedNode.tagName == 'A' && editor.dom.getAttrib(selectedNode, 'href') === '';
var value = '';
if (isAnchor) {
name = selectedNode.name || selectedNode.id || '';
value = selectedNode.id || selectedNode.name || '';
}
editor.windowManager.open({
title: 'Anchor',
body: {type: 'textbox', name: 'name', size: 40, label: 'Name', value: name},
body: {type: 'textbox', name: 'id', size: 40, label: 'Id', value: value},
onsubmit: function(e) {
var id = e.data.name;
var id = e.data.id;
if (!isValidId(id)) {
e.preventDefault();
editor.windowManager.alert(
'Id should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.'
);
return;
}
if (isAnchor) {
selectedNode.removeAttribute('name');
selectedNode.id = id;
} else {
editor.selection.collapse(true);
......@@ -35,6 +64,13 @@ tinymce.PluginManager.add('anchor', function(editor) {
}
}
});
};
if (tinymce.Env.ceFalse) {
editor.on('PreInit', function () {
editor.parser.addNodeFilter('a', setContentEditable('false'));
editor.serializer.addNodeFilter('a', setContentEditable(null));
});
}
editor.addCommand('mceAnchor', showDialog);
......
......@@ -197,6 +197,11 @@ tinymce.PluginManager.add('autolink', function(editor) {
editor.selection.setRng(rng);
editor.execCommand('createlink', false, matches[1] + matches[2]);
if (editor.settings.default_link_target) {
editor.dom.setAttrib(editor.selection.getNode(), 'target', editor.settings.default_link_target);
}
editor.selection.moveToBookmark(bookmark);
editor.nodeChanged();
}
......
......@@ -111,82 +111,84 @@ tinymce.PluginManager.add('charmap', function(editor) {
['8224', 'dagger'],
['8225', 'double dagger'],
// alphabetical special chars
['256', 'A - macron'],
['192', 'A - grave'],
['193', 'A - acute'],
['194', 'A - circumflex'],
['195', 'A - tilde'],
['196', 'A - diaeresis'],
['197', 'A - ring above'],
['256', 'A - macron'],
['198', 'ligature AE'],
['199', 'C - cedilla'],
['274', 'E - macron'],
['200', 'E - grave'],
['201', 'E - acute'],
['202', 'E - circumflex'],
['203', 'E - diaeresis'],
['298', 'I - macron'],
['274', 'E - macron'],
['204', 'I - grave'],
['205', 'I - acute'],
['206', 'I - circumflex'],
['207', 'I - diaeresis'],
['298', 'I - macron'],
['208', 'ETH'],
['209', 'N - tilde'],
['332', 'O - macron'],
['210', 'O - grave'],
['211', 'O - acute'],
['212', 'O - circumflex'],
['213', 'O - tilde'],
['214', 'O - diaeresis'],
['216', 'O - slash'],
['332', 'O - macron'],
['338', 'ligature OE'],
['352', 'S - caron'],
['362', 'U - macron'],
['217', 'U - grave'],
['218', 'U - acute'],
['219', 'U - circumflex'],
['220', 'U - diaeresis'],
['362', 'U - macron'],
['221', 'Y - acute'],
['376', 'Y - diaeresis'],
['562', 'Y - macron'],
['222', 'THORN'],
['257', 'a - macron'],
['224', 'a - grave'],
['225', 'a - acute'],
['226', 'a - circumflex'],
['227', 'a - tilde'],
['228', 'a - diaeresis'],
['229', 'a - ring above'],
['257', 'a - macron'],
['230', 'ligature ae'],
['231', 'c - cedilla'],
['275', 'e - macron'],
['232', 'e - grave'],
['233', 'e - acute'],
['234', 'e - circumflex'],
['235', 'e - diaeresis'],
['299', 'i - macron'],
['275', 'e - macron'],
['236', 'i - grave'],
['237', 'i - acute'],
['238', 'i - circumflex'],
['239', 'i - diaeresis'],
['299', 'i - macron'],
['240', 'eth'],
['241', 'n - tilde'],
['333', 'o - macron'],
['242', 'o - grave'],
['243', 'o - acute'],
['244', 'o - circumflex'],
['245', 'o - tilde'],
['246', 'o - diaeresis'],
['248', 'o slash'],
['333', 'o macron'],
['339', 'ligature oe'],
['353', 's - caron'],
['363', 'u - macron'],
['249', 'u - grave'],
['250', 'u - acute'],
['251', 'u - circumflex'],
['252', 'u - diaeresis'],
['363', 'u - macron'],
['253', 'y - acute'],
['254', 'thorn'],
['255', 'y - diaeresis'],
['563', 'y - macron'],
['913', 'Alpha'],
['914', 'Beta'],
['915', 'Gamma'],
......@@ -340,7 +342,7 @@ tinymce.PluginManager.add('charmap', function(editor) {
}
}
gridHtml = '<table role="presentation" cellspacing="0" class="mce-charmap"><tbody>';
gridHtml = '<table role="presentation" aria-hidden="true" cellspacing="0" class="mce-charmap"><tbody>';
var charmap = getCharMap();
var width = Math.min(charmap.length, 25);
......@@ -352,9 +354,13 @@ tinymce.PluginManager.add('charmap', function(editor) {
var index = y * width + x;
if (index < charmap.length) {
var chr = charmap[index];
var chrText = chr ? String.fromCharCode(parseInt(chr[0], 10)) : '&nbsp;';
gridHtml += '<td title="' + chr[1] + '"><div tabindex="-1" title="' + chr[1] + '" role="button">' +
(chr ? String.fromCharCode(parseInt(chr[0], 10)) : '&nbsp;') + '</div></td>';
gridHtml += (
'<td title="' + chr[1] + '"><div tabindex="-1" title="' + chr[1] + '" role="button" data-chr="' + chrText + '">' +
chrText +
'</div></td>'
);
} else {
gridHtml += '<td />';
}
......@@ -373,7 +379,7 @@ tinymce.PluginManager.add('charmap', function(editor) {
if (/^(TD|DIV)$/.test(target.nodeName)) {
if (getParentTd(target).firstChild) {
insertChar(tinymce.trim(target.innerText || target.textContent));
insertChar(target.getAttribute('data-chr'));
if (!e.ctrlKey) {
win.close();
......
......@@ -21,18 +21,23 @@ define("tinymce/codesampleplugin/Dialog", [
], function(DOMUtils, Utils, Prism) {
var DOM = DOMUtils.DOM;
var languages = [
{text: 'HTML/XML', value: 'markup'},
{text: 'JavaScript', value: 'javascript'},
{text: 'CSS', value: 'css'},
{text: 'PHP', value: 'php'},
{text: 'Ruby', value: 'ruby'},
{text: 'Python', value: 'python'},
{text: 'Java', value: 'java'},
{text: 'C', value: 'c'},
{text: 'C#', value: 'csharp'},
{text: 'C++', value: 'cpp'}
];
function getLanguages(editor) {
var defaultLanguages = [
{text: 'HTML/XML', value: 'markup'},
{text: 'JavaScript', value: 'javascript'},
{text: 'CSS', value: 'css'},
{text: 'PHP', value: 'php'},
{text: 'Ruby', value: 'ruby'},
{text: 'Python', value: 'python'},
{text: 'Java', value: 'java'},
{text: 'C', value: 'c'},
{text: 'C#', value: 'csharp'},
{text: 'C++', value: 'cpp'}
];
var customLanguages = editor.settings.codesample_languages;
return customLanguages ? customLanguages : defaultLanguages;
}
function insertCodeSample(editor, language, code) {
editor.undoManager.transact(function() {
......@@ -87,9 +92,11 @@ define("tinymce/codesampleplugin/Dialog", [
open: function(editor) {
editor.windowManager.open({
title: "Insert/Edit code sample",
minWidth: Math.min(DOM.getViewPort().w, 800),
minHeight: Math.min(DOM.getViewPort().h, 650),
layout: 'fit',
minWidth: Math.min(DOM.getViewPort().w, editor.getParam('codesample_dialog_width', 800)),
minHeight: Math.min(DOM.getViewPort().h, editor.getParam('codesample_dialog_height', 650)),
layout: 'flex',
direction: 'column',
align: 'stretch',
body: [
{
type: 'listbox',
......@@ -97,7 +104,7 @@ define("tinymce/codesampleplugin/Dialog", [
label: 'Language',
maxWidth: 200,
value: getCurrentLanguage(editor),
values: languages
values: getLanguages(editor)
},
{
......@@ -109,7 +116,8 @@ define("tinymce/codesampleplugin/Dialog", [
flex: 1,
style: 'direction: ltr; text-align: left',
classes: 'monospace',
value: getCurrentCode(editor)
value: getCurrentCode(editor),
autofocus: true
}
],
onSubmit: function(e) {
......
......@@ -21,23 +21,37 @@ define("tinymce/codesampleplugin/Plugin", [
"tinymce/codesampleplugin/Dialog",
"tinymce/codesampleplugin/Utils"
], function(Env, PluginManager, Prism, Dialog, Utils) {
var addedCss, trimArg = Utils.trimArg;
var addedInlineCss, trimArg = Utils.trimArg;
PluginManager.add('codesample', function(editor, pluginUrl) {
var $ = editor.$;
var $ = editor.$, addedCss;
if (!Env.ceFalse) {
return;
}
// Todo: use a proper css loader here
function loadCss() {
var linkElm;
var linkElm, contentCss = editor.settings.codesample_content_css;
if (!addedCss) {
if (editor.inline && addedInlineCss) {
return;
}
if (!editor.inline && addedCss) {
return;
}
if (editor.inline) {
addedInlineCss = true;
} else {
addedCss = true;
}
if (contentCss !== false) {
linkElm = editor.dom.create('link', {
rel: 'stylesheet',
href: pluginUrl + '/css/prism.css'
href: contentCss ? contentCss : pluginUrl + '/css/prism.css'
});
editor.getDoc().getElementsByTagName('head')[0].appendChild(linkElm);
......@@ -82,7 +96,12 @@ define("tinymce/codesampleplugin/Plugin", [
});
editor.addCommand('codesample', function() {
Dialog.open(editor);
var node = editor.selection.getNode();
if (editor.selection.isCollapsed() || Utils.isCodeSample(node)) {
Dialog.open(editor);
} else {
editor.formatter.toggle('code');
}
});
editor.addButton('codesample', {
......
......@@ -80,7 +80,7 @@
target[fragments[fragments.length - 1]] = modules[id];
}
// Expose private modules for unit tests
if (exports.AMDLC_TESTS) {
privateModules = exports.privateModules || {};
......@@ -1098,18 +1098,23 @@ define("tinymce/codesampleplugin/Dialog", [
], function(DOMUtils, Utils, Prism) {
var DOM = DOMUtils.DOM;
var languages = [
{text: 'HTML/XML', value: 'markup'},
{text: 'JavaScript', value: 'javascript'},
{text: 'CSS', value: 'css'},
{text: 'PHP', value: 'php'},
{text: 'Ruby', value: 'ruby'},
{text: 'Python', value: 'python'},
{text: 'Java', value: 'java'},
{text: 'C', value: 'c'},
{text: 'C#', value: 'csharp'},
{text: 'C++', value: 'cpp'}
];
function getLanguages(editor) {
var defaultLanguages = [
{text: 'HTML/XML', value: 'markup'},
{text: 'JavaScript', value: 'javascript'},
{text: 'CSS', value: 'css'},
{text: 'PHP', value: 'php'},
{text: 'Ruby', value: 'ruby'},
{text: 'Python', value: 'python'},
{text: 'Java', value: 'java'},
{text: 'C', value: 'c'},
{text: 'C#', value: 'csharp'},
{text: 'C++', value: 'cpp'}
];
var customLanguages = editor.settings.codesample_languages;
return customLanguages ? customLanguages : defaultLanguages;
}
function insertCodeSample(editor, language, code) {
editor.undoManager.transact(function() {
......@@ -1164,9 +1169,11 @@ define("tinymce/codesampleplugin/Dialog", [
open: function(editor) {
editor.windowManager.open({
title: "Insert/Edit code sample",
minWidth: Math.min(DOM.getViewPort().w, 800),
minHeight: Math.min(DOM.getViewPort().h, 650),
layout: 'fit',
minWidth: Math.min(DOM.getViewPort().w, editor.getParam('codesample_dialog_width', 800)),
minHeight: Math.min(DOM.getViewPort().h, editor.getParam('codesample_dialog_height', 650)),
layout: 'flex',
direction: 'column',
align: 'stretch',
body: [
{
type: 'listbox',
......@@ -1174,7 +1181,7 @@ define("tinymce/codesampleplugin/Dialog", [
label: 'Language',
maxWidth: 200,
value: getCurrentLanguage(editor),
values: languages
values: getLanguages(editor)
},
{
......@@ -1186,7 +1193,8 @@ define("tinymce/codesampleplugin/Dialog", [
flex: 1,
style: 'direction: ltr; text-align: left',
classes: 'monospace',
value: getCurrentCode(editor)
value: getCurrentCode(editor),
autofocus: true
}
],
onSubmit: function(e) {
......@@ -1222,23 +1230,37 @@ define("tinymce/codesampleplugin/Plugin", [
"tinymce/codesampleplugin/Dialog",
"tinymce/codesampleplugin/Utils"
], function(Env, PluginManager, Prism, Dialog, Utils) {
var addedCss, trimArg = Utils.trimArg;
var addedInlineCss, trimArg = Utils.trimArg;
PluginManager.add('codesample', function(editor, pluginUrl) {
var $ = editor.$;
var $ = editor.$, addedCss;