add sppd to git repo
This commit is contained in:
5
plugins/tinymce/themes/inlite/config/bolt/atomic.js
Normal file
5
plugins/tinymce/themes/inlite/config/bolt/atomic.js
Normal file
@@ -0,0 +1,5 @@
|
||||
configure({
|
||||
configs: [
|
||||
'./prod.js'
|
||||
]
|
||||
});
|
||||
1491
plugins/tinymce/themes/inlite/config/bolt/bootstrap-atomic.js
vendored
Normal file
1491
plugins/tinymce/themes/inlite/config/bolt/bootstrap-atomic.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1491
plugins/tinymce/themes/inlite/config/bolt/bootstrap-browser.js
vendored
Normal file
1491
plugins/tinymce/themes/inlite/config/bolt/bootstrap-browser.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1491
plugins/tinymce/themes/inlite/config/bolt/bootstrap-demo.js
vendored
Normal file
1491
plugins/tinymce/themes/inlite/config/bolt/bootstrap-demo.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1491
plugins/tinymce/themes/inlite/config/bolt/bootstrap-prod.js
vendored
Normal file
1491
plugins/tinymce/themes/inlite/config/bolt/bootstrap-prod.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
10
plugins/tinymce/themes/inlite/config/bolt/browser.js
Normal file
10
plugins/tinymce/themes/inlite/config/bolt/browser.js
Normal file
@@ -0,0 +1,10 @@
|
||||
configure({
|
||||
configs: [
|
||||
'./prod.js'
|
||||
],
|
||||
sources: [
|
||||
source('amd', 'ephox/tinymce', '', mapper.constant('../../../../../tinymce')),
|
||||
source('amd', 'ephox.mcagar', '../../lib/test', mapper.flat),
|
||||
source('amd', 'ephox', '../../lib/test', mapper.flat)
|
||||
]
|
||||
});
|
||||
8
plugins/tinymce/themes/inlite/config/bolt/demo.js
Normal file
8
plugins/tinymce/themes/inlite/config/bolt/demo.js
Normal file
@@ -0,0 +1,8 @@
|
||||
configure({
|
||||
configs: [
|
||||
'./prod.js'
|
||||
],
|
||||
sources: [
|
||||
source('amd', 'tinymce/inlite/Demo', '../../src/demo/js', mapper.hierarchical)
|
||||
]
|
||||
});
|
||||
5
plugins/tinymce/themes/inlite/config/bolt/prod.js
Normal file
5
plugins/tinymce/themes/inlite/config/bolt/prod.js
Normal file
@@ -0,0 +1,5 @@
|
||||
configure({
|
||||
sources: [
|
||||
source('amd', 'tinymce/inlite', '../../src/main/js', mapper.hierarchical)
|
||||
]
|
||||
});
|
||||
21
plugins/tinymce/themes/inlite/config/dent/depend.js
Normal file
21
plugins/tinymce/themes/inlite/config/dent/depend.js
Normal file
@@ -0,0 +1,21 @@
|
||||
var lib = 'lib';
|
||||
var run = lib + '/run';
|
||||
var depend = run + '/depend';
|
||||
var licenses = run + '/licenses';
|
||||
var demo = lib + '/demo';
|
||||
var test = lib + '/test';
|
||||
var config = lib + '/config';
|
||||
|
||||
var cleanDirs = [ lib ];
|
||||
|
||||
var dependencies = [
|
||||
{
|
||||
name: 'mcagar',
|
||||
repository: 'buildrepo2',
|
||||
source: 'mcagar.zip',
|
||||
targets: [
|
||||
{ name: 'module/*.js', path: test },
|
||||
{ name: 'depend/*.js', path: test }
|
||||
]
|
||||
}
|
||||
];
|
||||
1526
plugins/tinymce/themes/inlite/scratch/compile/bootstrap.js
vendored
Normal file
1526
plugins/tinymce/themes/inlite/scratch/compile/bootstrap.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1594
plugins/tinymce/themes/inlite/scratch/compile/theme.js
Normal file
1594
plugins/tinymce/themes/inlite/scratch/compile/theme.js
Normal file
File diff suppressed because it is too large
Load Diff
1679
plugins/tinymce/themes/inlite/scratch/inline/theme.js
Normal file
1679
plugins/tinymce/themes/inlite/scratch/inline/theme.js
Normal file
File diff suppressed because it is too large
Load Diff
1679
plugins/tinymce/themes/inlite/scratch/inline/theme.raw.js
Normal file
1679
plugins/tinymce/themes/inlite/scratch/inline/theme.raw.js
Normal file
File diff suppressed because it is too large
Load Diff
25
plugins/tinymce/themes/inlite/src/demo/css/demo.css
Normal file
25
plugins/tinymce/themes/inlite/src/demo/css/demo.css
Normal file
@@ -0,0 +1,25 @@
|
||||
blockquote {
|
||||
border-left: 3px solid rgba(0,0,0,.8);
|
||||
padding-left: 20px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.mce-edit-focus {
|
||||
outline: 1px solid blue;
|
||||
}
|
||||
|
||||
.tinymce {
|
||||
margin: 10px;
|
||||
padding: 10px;
|
||||
overflow: auto;
|
||||
border: 1px solid gray;
|
||||
}
|
||||
|
||||
table, td {
|
||||
border: 1px dashed gray;
|
||||
}
|
||||
|
||||
/*.mce-tinymce-inline {
|
||||
transition: left 50ms ease-in-out, top 50ms ease-in-out;
|
||||
}
|
||||
*/
|
||||
69
plugins/tinymce/themes/inlite/src/demo/html/demo.html
Normal file
69
plugins/tinymce/themes/inlite/src/demo/html/demo.html
Normal file
@@ -0,0 +1,69 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>inlite-theme Demo Page</title>
|
||||
<link href="../css/demo.css" rel="stylesheet">
|
||||
<script src="../../../../../tinymce.dev.js"></script>
|
||||
<script src="../../../config/bolt/bootstrap-demo.js"></script>
|
||||
<script>
|
||||
ephox.bolt.module.api.main('tinymce/inlite/Demo');
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h2>inlite-theme Demo Page</h2>
|
||||
<div id="ephox-ui">
|
||||
<div class="tinymce" style="width: 900px; min-height: 100px">
|
||||
<p>
|
||||
<img src="https://www.tinymce.com/images/glyph-tinymce@2x.png" style="width: 100px; float: right">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi ultricies posuere felis sed interdum. Quisque nec diam
|
||||
nec purus gravida dapibus
|
||||
</p>
|
||||
<p>
|
||||
eget non <a href="http://www.tinymce.com">nulla</a>. Ut eu vestibulum libero. Vestibulum pretium est vitae metus auctor, quis fermentum mi
|
||||
luctus. Fusce aliquet tincidunt massa vitae scelerisque. Vivamus in tellus risus. Mauris auctor metus ut gravida feugiat.
|
||||
Nunc consequat urna eu augue commodo, eget malesuada odio fringilla. Morbi vitae turpis in elit laoreet malesuada a nec massa.
|
||||
</p>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Lorem ipsum dolor sit amet</td>
|
||||
<td>Lorem ipsum dolor sit amet</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Vivamus in tellus risus</td>
|
||||
<td>Vivamus in tellus risus</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div style="height: 3000px"></div>
|
||||
|
||||
<div class="tinymce" style="width: 900px; min-height: 100px; margin: 20px; border: 20px solid black; padding: 20px">
|
||||
<p>
|
||||
<img src="https://www.tinymce.com/images/glyph-tinymce@2x.png" style="width: 100px; float: right">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi ultricies posuere felis sed interdum. Quisque nec diam
|
||||
nec purus gravida dapibus
|
||||
</p>
|
||||
<p>
|
||||
eget non <a href="http://www.tinymce.com">nulla</a>. Ut eu vestibulum libero. Vestibulum pretium est vitae metus auctor, quis fermentum mi
|
||||
luctus. Fusce aliquet tincidunt massa vitae scelerisque. Vivamus in tellus risus. Mauris auctor metus ut gravida feugiat.
|
||||
Nunc consequat urna eu augue commodo, eget malesuada odio fringilla. Morbi vitae turpis in elit laoreet malesuada a nec massa.
|
||||
</p>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Lorem ipsum dolor sit amet</td>
|
||||
<td>Lorem ipsum dolor sit amet</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Vivamus in tellus risus</td>
|
||||
<td>Vivamus in tellus risus</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Demo.js
|
||||
*
|
||||
* Released under LGPL License.
|
||||
* Copyright (c) 1999-2016 Ephox Corp. All rights reserved
|
||||
*
|
||||
* License: http://www.tinymce.com/license
|
||||
* Contributing: http://www.tinymce.com/contributing
|
||||
*/
|
||||
|
||||
/*eslint no-console:0 */
|
||||
|
||||
define('tinymce/inlite/Demo', [
|
||||
'tinymce/inlite/Theme',
|
||||
'global!tinymce'
|
||||
], function(Theme, tinymce) {
|
||||
tinymce.init({
|
||||
selector: 'div.tinymce',
|
||||
theme: 'inlite',
|
||||
plugins: 'image table link paste contextmenu textpattern autolink',
|
||||
insert_toolbar: 'quickimage quicktable',
|
||||
selection_toolbar: 'bold italic | quicklink h2 h3 blockquote',
|
||||
inline: true,
|
||||
paste_data_images: true
|
||||
});
|
||||
|
||||
return function() {};
|
||||
});
|
||||
@@ -0,0 +1,150 @@
|
||||
/**
|
||||
* Theme.js
|
||||
*
|
||||
* Released under LGPL License.
|
||||
* Copyright (c) 1999-2016 Ephox Corp. All rights reserved
|
||||
*
|
||||
* License: http://www.tinymce.com/license
|
||||
* Contributing: http://www.tinymce.com/contributing
|
||||
*/
|
||||
|
||||
define('tinymce/inlite/Theme', [
|
||||
'global!tinymce.ThemeManager',
|
||||
'global!tinymce.util.Delay',
|
||||
'tinymce/inlite/ui/Panel',
|
||||
'tinymce/inlite/ui/Buttons',
|
||||
'tinymce/inlite/core/SkinLoader',
|
||||
'tinymce/inlite/core/SelectionMatcher',
|
||||
'tinymce/inlite/core/ElementMatcher',
|
||||
'tinymce/inlite/core/Matcher',
|
||||
'tinymce/inlite/alien/Arr',
|
||||
'tinymce/inlite/core/PredicateId'
|
||||
], function(ThemeManager, Delay, Panel, Buttons, SkinLoader, SelectionMatcher, ElementMatcher, Matcher, Arr, PredicateId) {
|
||||
var getSelectionElements = function (editor) {
|
||||
var node = editor.selection.getNode();
|
||||
var elms = editor.dom.getParents(node);
|
||||
return elms;
|
||||
};
|
||||
|
||||
var createToolbar = function (editor, selector, id, items) {
|
||||
var selectorPredicate = function (elm) {
|
||||
return editor.dom.is(elm, selector);
|
||||
};
|
||||
|
||||
return {
|
||||
predicate: selectorPredicate,
|
||||
id: id,
|
||||
items: items
|
||||
};
|
||||
};
|
||||
|
||||
var getToolbars = function (editor) {
|
||||
var contextToolbars = editor.contextToolbars;
|
||||
|
||||
return Arr.flatten([
|
||||
contextToolbars ? contextToolbars : [],
|
||||
createToolbar(editor, 'img', 'image', 'alignleft aligncenter alignright')
|
||||
]);
|
||||
};
|
||||
|
||||
var findMatchResult = function (editor, toolbars) {
|
||||
var result, elements, contextToolbarsPredicateIds;
|
||||
|
||||
elements = getSelectionElements(editor);
|
||||
contextToolbarsPredicateIds = PredicateId.fromContextToolbars(toolbars);
|
||||
|
||||
result = Matcher.match(editor, [
|
||||
ElementMatcher.element(elements[0], contextToolbarsPredicateIds),
|
||||
SelectionMatcher.textSelection('text'),
|
||||
SelectionMatcher.emptyTextBlock(elements, 'insert'),
|
||||
ElementMatcher.parent(elements, contextToolbarsPredicateIds)
|
||||
]);
|
||||
|
||||
return result && result.rect ? result : null;
|
||||
};
|
||||
|
||||
var togglePanel = function (editor, panel) {
|
||||
var toggle = function () {
|
||||
var toolbars = getToolbars(editor);
|
||||
var result = findMatchResult(editor, toolbars);
|
||||
|
||||
if (result) {
|
||||
panel.show(editor, result.id, result.rect, toolbars);
|
||||
} else {
|
||||
panel.hide();
|
||||
}
|
||||
};
|
||||
|
||||
return function () {
|
||||
if (!editor.removed) {
|
||||
toggle();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
var ignoreWhenFormIsVisible = function (panel, f) {
|
||||
return function () {
|
||||
if (!panel.inForm()) {
|
||||
f();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
var bindContextualToolbarsEvents = function (editor, panel) {
|
||||
var throttledTogglePanel = Delay.throttle(togglePanel(editor, panel), 0);
|
||||
var throttledTogglePanelWhenNotInForm = Delay.throttle(ignoreWhenFormIsVisible(panel, togglePanel(editor, panel)), 0);
|
||||
|
||||
editor.on('blur hide ObjectResizeStart', panel.hide);
|
||||
editor.on('click', throttledTogglePanel);
|
||||
editor.on('nodeChange mouseup', throttledTogglePanelWhenNotInForm);
|
||||
editor.on('ResizeEditor ResizeWindow keyup', throttledTogglePanel);
|
||||
editor.on('remove', panel.remove);
|
||||
|
||||
editor.shortcuts.add('Alt+F10', '', panel.focus);
|
||||
};
|
||||
|
||||
var overrideLinkShortcut = function (editor, panel) {
|
||||
editor.shortcuts.remove('meta+k');
|
||||
editor.shortcuts.add('meta+k', '', function () {
|
||||
var toolbars = getToolbars(editor);
|
||||
var result = result = Matcher.match(editor, [
|
||||
SelectionMatcher.textSelection('quicklink')
|
||||
]);
|
||||
|
||||
if (result) {
|
||||
panel.show(editor, result.id, result.rect, toolbars);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var renderInlineUI = function (editor, panel) {
|
||||
var skinName = editor.settings.skin || 'lightgray';
|
||||
|
||||
SkinLoader.load(editor, skinName, function () {
|
||||
bindContextualToolbarsEvents(editor, panel);
|
||||
overrideLinkShortcut(editor, panel);
|
||||
});
|
||||
|
||||
return {};
|
||||
};
|
||||
|
||||
var fail = function (message) {
|
||||
throw new Error(message);
|
||||
};
|
||||
|
||||
ThemeManager.add('inlite', function (editor) {
|
||||
var panel = new Panel();
|
||||
|
||||
Buttons.addToEditor(editor, panel);
|
||||
|
||||
var renderUI = function () {
|
||||
return editor.inline ? renderInlineUI(editor, panel) : fail('inlite theme only supports inline mode.');
|
||||
};
|
||||
|
||||
return {
|
||||
renderUI: renderUI
|
||||
};
|
||||
});
|
||||
|
||||
return function() {};
|
||||
});
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Arr.js
|
||||
*
|
||||
* Released under LGPL License.
|
||||
* Copyright (c) 1999-2016 Ephox Corp. All rights reserved
|
||||
*
|
||||
* License: http://www.tinymce.com/license
|
||||
* Contributing: http://www.tinymce.com/contributing
|
||||
*/
|
||||
|
||||
define('tinymce/inlite/alien/Arr', [
|
||||
], function () {
|
||||
var flatten = function (arr) {
|
||||
return arr.reduce(function (results, item) {
|
||||
return Array.isArray(item) ? results.concat(flatten(item)) : results.concat(item);
|
||||
}, []);
|
||||
};
|
||||
|
||||
return {
|
||||
flatten: flatten
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,130 @@
|
||||
/**
|
||||
* Bookmark.js
|
||||
*
|
||||
* Released under LGPL License.
|
||||
* Copyright (c) 1999-2016 Ephox Corp. All rights reserved
|
||||
*
|
||||
* License: http://www.tinymce.com/license
|
||||
* Contributing: http://www.tinymce.com/contributing
|
||||
*/
|
||||
|
||||
define('tinymce/inlite/alien/Bookmark', [
|
||||
], function () {
|
||||
/**
|
||||
* Returns a range bookmark. This will convert indexed bookmarks into temporary span elements with
|
||||
* index 0 so that they can be restored properly after the DOM has been modified. Text bookmarks will not have spans
|
||||
* added to them since they can be restored after a dom operation.
|
||||
*
|
||||
* So this: <p><b>|</b><b>|</b></p>
|
||||
* becomes: <p><b><span data-mce-type="bookmark">|</span></b><b data-mce-type="bookmark">|</span></b></p>
|
||||
*
|
||||
* @param {DOMRange} rng DOM Range to get bookmark on.
|
||||
* @return {Object} Bookmark object.
|
||||
*/
|
||||
var create = function (dom, rng) {
|
||||
var bookmark = {};
|
||||
|
||||
function setupEndPoint(start) {
|
||||
var offsetNode, container, offset;
|
||||
|
||||
container = rng[start ? 'startContainer' : 'endContainer'];
|
||||
offset = rng[start ? 'startOffset' : 'endOffset'];
|
||||
|
||||
if (container.nodeType == 1) {
|
||||
offsetNode = dom.create('span', {'data-mce-type': 'bookmark'});
|
||||
|
||||
if (container.hasChildNodes()) {
|
||||
offset = Math.min(offset, container.childNodes.length - 1);
|
||||
|
||||
if (start) {
|
||||
container.insertBefore(offsetNode, container.childNodes[offset]);
|
||||
} else {
|
||||
dom.insertAfter(offsetNode, container.childNodes[offset]);
|
||||
}
|
||||
} else {
|
||||
container.appendChild(offsetNode);
|
||||
}
|
||||
|
||||
container = offsetNode;
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
bookmark[start ? 'startContainer' : 'endContainer'] = container;
|
||||
bookmark[start ? 'startOffset' : 'endOffset'] = offset;
|
||||
}
|
||||
|
||||
setupEndPoint(true);
|
||||
|
||||
if (!rng.collapsed) {
|
||||
setupEndPoint();
|
||||
}
|
||||
|
||||
return bookmark;
|
||||
};
|
||||
|
||||
/**
|
||||
* Moves the selection to the current bookmark and removes any selection container wrappers.
|
||||
*
|
||||
* @param {Object} bookmark Bookmark object to move selection to.
|
||||
*/
|
||||
var resolve = function (dom, bookmark) {
|
||||
function restoreEndPoint(start) {
|
||||
var container, offset, node;
|
||||
|
||||
function nodeIndex(container) {
|
||||
var node = container.parentNode.firstChild, idx = 0;
|
||||
|
||||
while (node) {
|
||||
if (node == container) {
|
||||
return idx;
|
||||
}
|
||||
|
||||
// Skip data-mce-type=bookmark nodes
|
||||
if (node.nodeType != 1 || node.getAttribute('data-mce-type') != 'bookmark') {
|
||||
idx++;
|
||||
}
|
||||
|
||||
node = node.nextSibling;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
container = node = bookmark[start ? 'startContainer' : 'endContainer'];
|
||||
offset = bookmark[start ? 'startOffset' : 'endOffset'];
|
||||
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (container.nodeType == 1) {
|
||||
offset = nodeIndex(container);
|
||||
container = container.parentNode;
|
||||
dom.remove(node);
|
||||
}
|
||||
|
||||
bookmark[start ? 'startContainer' : 'endContainer'] = container;
|
||||
bookmark[start ? 'startOffset' : 'endOffset'] = offset;
|
||||
}
|
||||
|
||||
restoreEndPoint(true);
|
||||
restoreEndPoint();
|
||||
|
||||
var rng = dom.createRng();
|
||||
|
||||
rng.setStart(bookmark.startContainer, bookmark.startOffset);
|
||||
|
||||
if (bookmark.endContainer) {
|
||||
rng.setEnd(bookmark.endContainer, bookmark.endOffset);
|
||||
}
|
||||
|
||||
return rng;
|
||||
};
|
||||
|
||||
return {
|
||||
create: create,
|
||||
resolve: resolve
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* Unlink.js
|
||||
*
|
||||
* Released under LGPL License.
|
||||
* Copyright (c) 1999-2016 Ephox Corp. All rights reserved
|
||||
*
|
||||
* License: http://www.tinymce.com/license
|
||||
* Contributing: http://www.tinymce.com/contributing
|
||||
*/
|
||||
|
||||
/**
|
||||
* Unlink implementation that doesn't leave partial links for example it would produce:
|
||||
* a[b<a href="x">c]d</a>e -> a[bc]de
|
||||
* instead of:
|
||||
* a[b<a href="x">c]d</a>e -> a[bc]<a href="x">d</a>e
|
||||
*/
|
||||
define("tinymce/inlite/alien/Unlink", [
|
||||
'tinymce/inlite/alien/Bookmark',
|
||||
'global!tinymce.util.Tools',
|
||||
'global!tinymce.dom.TreeWalker',
|
||||
'global!tinymce.dom.RangeUtils'
|
||||
], function (Bookmark, Tools, TreeWalker, RangeUtils) {
|
||||
var getSelectedElements = function (rootElm, startNode, endNode) {
|
||||
var walker, node, elms = [];
|
||||
|
||||
walker = new TreeWalker(startNode, rootElm);
|
||||
for (node = startNode; node; node = walker.next()) {
|
||||
if (node.nodeType === 1) {
|
||||
elms.push(node);
|
||||
}
|
||||
|
||||
if (node === endNode) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return elms;
|
||||
};
|
||||
|
||||
var unwrapElements = function (editor, elms) {
|
||||
var bookmark, dom, selection;
|
||||
|
||||
dom = editor.dom;
|
||||
selection = editor.selection;
|
||||
bookmark = Bookmark.create(dom, selection.getRng());
|
||||
|
||||
Tools.each(elms, function (elm) {
|
||||
editor.dom.remove(elm, true);
|
||||
});
|
||||
|
||||
selection.setRng(Bookmark.resolve(dom, bookmark));
|
||||
};
|
||||
|
||||
var isLink = function (elm) {
|
||||
return elm.nodeName === 'A' && elm.hasAttribute('href');
|
||||
};
|
||||
|
||||
var getParentAnchorOrSelf = function (dom, elm) {
|
||||
var anchorElm = dom.getParent(elm, isLink);
|
||||
return anchorElm ? anchorElm : elm;
|
||||
};
|
||||
|
||||
var getSelectedAnchors = function (editor) {
|
||||
var startElm, endElm, rootElm, anchorElms, selection, dom, rng;
|
||||
|
||||
selection = editor.selection;
|
||||
dom = editor.dom;
|
||||
rng = selection.getRng();
|
||||
startElm = getParentAnchorOrSelf(dom, RangeUtils.getNode(rng.startContainer, rng.startOffset));
|
||||
endElm = RangeUtils.getNode(rng.endContainer, rng.endOffset);
|
||||
rootElm = editor.getBody();
|
||||
anchorElms = Tools.grep(getSelectedElements(rootElm, startElm, endElm), isLink);
|
||||
|
||||
return anchorElms;
|
||||
};
|
||||
|
||||
var unlinkSelection = function (editor) {
|
||||
unwrapElements(editor, getSelectedAnchors(editor));
|
||||
};
|
||||
|
||||
return {
|
||||
unlinkSelection: unlinkSelection
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Uuid.js
|
||||
*
|
||||
* Released under LGPL License.
|
||||
* Copyright (c) 1999-2016 Ephox Corp. All rights reserved
|
||||
*
|
||||
* License: http://www.tinymce.com/license
|
||||
* Contributing: http://www.tinymce.com/contributing
|
||||
*/
|
||||
|
||||
/**
|
||||
* Generates unique ids this is the same as in core but since
|
||||
* it's not exposed as a global we can't access it.
|
||||
*/
|
||||
define("tinymce/inlite/alien/Uuid", [
|
||||
], function() {
|
||||
var count = 0;
|
||||
|
||||
var seed = function () {
|
||||
var rnd = function () {
|
||||
return Math.round(Math.random() * 0xFFFFFFFF).toString(36);
|
||||
};
|
||||
|
||||
return 's' + Date.now().toString(36) + rnd() + rnd() + rnd();
|
||||
};
|
||||
|
||||
var uuid = function (prefix) {
|
||||
return prefix + (count++) + seed();
|
||||
};
|
||||
|
||||
return {
|
||||
uuid: uuid
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* Actions.js
|
||||
*
|
||||
* Released under LGPL License.
|
||||
* Copyright (c) 1999-2016 Ephox Corp. All rights reserved
|
||||
*
|
||||
* License: http://www.tinymce.com/license
|
||||
* Contributing: http://www.tinymce.com/contributing
|
||||
*/
|
||||
|
||||
define('tinymce/inlite/core/Actions', [
|
||||
'tinymce/inlite/alien/Uuid',
|
||||
'tinymce/inlite/alien/Unlink'
|
||||
], function (Uuid, Unlink) {
|
||||
var createTableHtml = function (cols, rows) {
|
||||
var x, y, html;
|
||||
|
||||
html = '<table data-mce-id="mce" style="width: 100%">';
|
||||
html += '<tbody>';
|
||||
|
||||
for (y = 0; y < rows; y++) {
|
||||
html += '<tr>';
|
||||
|
||||
for (x = 0; x < cols; x++) {
|
||||
html += '<td><br></td>';
|
||||
}
|
||||
|
||||
html += '</tr>';
|
||||
}
|
||||
|
||||
html += '</tbody>';
|
||||
html += '</table>';
|
||||
|
||||
return html;
|
||||
};
|
||||
|
||||
var getInsertedElement = function (editor) {
|
||||
var elms = editor.dom.select('*[data-mce-id]');
|
||||
return elms[0];
|
||||
};
|
||||
|
||||
var insertTable = function (editor, cols, rows) {
|
||||
editor.undoManager.transact(function () {
|
||||
var tableElm, cellElm;
|
||||
|
||||
editor.insertContent(createTableHtml(cols, rows));
|
||||
|
||||
tableElm = getInsertedElement(editor);
|
||||
tableElm.removeAttribute('data-mce-id');
|
||||
cellElm = editor.dom.select('td,th', tableElm);
|
||||
editor.selection.setCursorLocation(cellElm[0], 0);
|
||||
});
|
||||
};
|
||||
|
||||
var formatBlock = function (editor, formatName) {
|
||||
editor.execCommand('FormatBlock', false, formatName);
|
||||
};
|
||||
|
||||
var insertBlob = function (editor, base64, blob) {
|
||||
var blobCache, blobInfo;
|
||||
|
||||
blobCache = editor.editorUpload.blobCache;
|
||||
blobInfo = blobCache.create(Uuid.uuid('mceu'), blob, base64);
|
||||
blobCache.add(blobInfo);
|
||||
|
||||
editor.insertContent(editor.dom.createHTML('img', {src: blobInfo.blobUri()}));
|
||||
};
|
||||
|
||||
var collapseSelectionToEnd = function (editor) {
|
||||
editor.selection.collapse(false);
|
||||
};
|
||||
|
||||
var unlink = function (editor) {
|
||||
editor.focus();
|
||||
Unlink.unlinkSelection(editor);
|
||||
collapseSelectionToEnd(editor);
|
||||
};
|
||||
|
||||
var changeHref = function (editor, elm, url) {
|
||||
editor.focus();
|
||||
editor.dom.setAttrib(elm, 'href', url);
|
||||
collapseSelectionToEnd(editor);
|
||||
};
|
||||
|
||||
var insertLink = function (editor, url) {
|
||||
editor.execCommand('mceInsertLink', false, {href: url});
|
||||
collapseSelectionToEnd(editor);
|
||||
};
|
||||
|
||||
var updateOrInsertLink = function (editor, url) {
|
||||
var elm = editor.dom.getParent(editor.selection.getStart(), 'a[href]');
|
||||
elm ? changeHref(editor, elm, url) : insertLink(editor, url);
|
||||
};
|
||||
|
||||
var createLink = function (editor, url) {
|
||||
url.trim().length === 0 ? unlink(editor) : updateOrInsertLink(editor, url);
|
||||
};
|
||||
|
||||
return {
|
||||
insertTable: insertTable,
|
||||
formatBlock: formatBlock,
|
||||
insertBlob: insertBlob,
|
||||
createLink: createLink,
|
||||
unlink: unlink
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Convert.js
|
||||
*
|
||||
* Released under LGPL License.
|
||||
* Copyright (c) 1999-2016 Ephox Corp. All rights reserved
|
||||
*
|
||||
* License: http://www.tinymce.com/license
|
||||
* Contributing: http://www.tinymce.com/contributing
|
||||
*/
|
||||
|
||||
define('tinymce/inlite/core/Convert', [
|
||||
], function () {
|
||||
var fromClientRect = function (clientRect) {
|
||||
return {
|
||||
x: clientRect.left,
|
||||
y: clientRect.top,
|
||||
w: clientRect.width,
|
||||
h: clientRect.height
|
||||
};
|
||||
};
|
||||
|
||||
var toClientRect = function (geomRect) {
|
||||
return {
|
||||
left: geomRect.x,
|
||||
top: geomRect.y,
|
||||
width: geomRect.w,
|
||||
height: geomRect.h,
|
||||
right: geomRect.x + geomRect.w,
|
||||
bottom: geomRect.y + geomRect.h
|
||||
};
|
||||
};
|
||||
|
||||
return {
|
||||
fromClientRect: fromClientRect,
|
||||
toClientRect: toClientRect
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* ElementMatcher.js
|
||||
*
|
||||
* Released under LGPL License.
|
||||
* Copyright (c) 1999-2016 Ephox Corp. All rights reserved
|
||||
*
|
||||
* License: http://www.tinymce.com/license
|
||||
* Contributing: http://www.tinymce.com/contributing
|
||||
*/
|
||||
|
||||
define('tinymce/inlite/core/ElementMatcher', [
|
||||
'tinymce/inlite/core/Matcher',
|
||||
'tinymce/inlite/core/Measure'
|
||||
], function (Matcher, Measure) {
|
||||
// element :: Element, [PredicateId] -> (Editor -> Matcher.result | Null)
|
||||
var element = function (element, predicateIds) {
|
||||
return function (editor) {
|
||||
for (var i = 0; i < predicateIds.length; i++) {
|
||||
if (predicateIds[i].predicate(element)) {
|
||||
return Matcher.result(predicateIds[i].id, Measure.getElementRect(editor, element));
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
};
|
||||
|
||||
// parent :: [Elements], [PredicateId] -> (Editor -> Matcher.result | Null)
|
||||
var parent = function (elements, predicateIds) {
|
||||
return function (editor) {
|
||||
for (var i = 0; i < elements.length; i++) {
|
||||
for (var x = 0; x < predicateIds.length; x++) {
|
||||
if (predicateIds[x].predicate(elements[i])) {
|
||||
return Matcher.result(predicateIds[x].id, Measure.getElementRect(editor, elements[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
};
|
||||
|
||||
return {
|
||||
element: element,
|
||||
parent: parent
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* Layout.js
|
||||
*
|
||||
* Released under LGPL License.
|
||||
* Copyright (c) 1999-2016 Ephox Corp. All rights reserved
|
||||
*
|
||||
* License: http://www.tinymce.com/license
|
||||
* Contributing: http://www.tinymce.com/contributing
|
||||
*/
|
||||
|
||||
define('tinymce/inlite/core/Layout', [
|
||||
'global!tinymce.geom.Rect',
|
||||
'tinymce/inlite/core/Convert'
|
||||
], function (Rect, Convert) {
|
||||
var result = function (rect, position) {
|
||||
return {
|
||||
rect: rect,
|
||||
position: position
|
||||
};
|
||||
};
|
||||
|
||||
var moveTo = function (rect, toRect) {
|
||||
return {x: toRect.x, y: toRect.y, w: rect.w, h: rect.h};
|
||||
};
|
||||
|
||||
var calcByPositions = function (testPositions1, testPositions2, targetRect, contentAreaRect, panelRect) {
|
||||
var relPos, relRect, outputPanelRect;
|
||||
|
||||
relPos = Rect.findBestRelativePosition(panelRect, targetRect, contentAreaRect, testPositions1);
|
||||
targetRect = Rect.clamp(targetRect, contentAreaRect);
|
||||
|
||||
if (relPos) {
|
||||
relRect = Rect.relativePosition(panelRect, targetRect, relPos);
|
||||
outputPanelRect = moveTo(panelRect, relRect);
|
||||
return result(outputPanelRect, relPos);
|
||||
}
|
||||
|
||||
targetRect = Rect.intersect(contentAreaRect, targetRect);
|
||||
if (targetRect) {
|
||||
relPos = Rect.findBestRelativePosition(panelRect, targetRect, contentAreaRect, testPositions2);
|
||||
if (relPos) {
|
||||
relRect = Rect.relativePosition(panelRect, targetRect, relPos);
|
||||
outputPanelRect = moveTo(panelRect, relRect);
|
||||
return result(outputPanelRect, relPos);
|
||||
}
|
||||
|
||||
outputPanelRect = moveTo(panelRect, targetRect);
|
||||
return result(outputPanelRect, relPos);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
var calcInsert = function (targetRect, contentAreaRect, panelRect) {
|
||||
return calcByPositions(
|
||||
['cr-cl', 'cl-cr'],
|
||||
['bc-tc', 'bl-tl', 'br-tr'],
|
||||
targetRect,
|
||||
contentAreaRect,
|
||||
panelRect
|
||||
);
|
||||
};
|
||||
|
||||
var calc = function (targetRect, contentAreaRect, panelRect) {
|
||||
return calcByPositions(
|
||||
['tc-bc', 'bc-tc', 'tl-bl', 'bl-tl', 'tr-br', 'br-tr'],
|
||||
['bc-tc', 'bl-tl', 'br-tr'],
|
||||
targetRect,
|
||||
contentAreaRect,
|
||||
panelRect
|
||||
);
|
||||
};
|
||||
|
||||
var userConstrain = function (handler, targetRect, contentAreaRect, panelRect) {
|
||||
var userConstrainedPanelRect;
|
||||
|
||||
if (typeof handler === 'function') {
|
||||
userConstrainedPanelRect = handler({
|
||||
elementRect: Convert.toClientRect(targetRect),
|
||||
contentAreaRect: Convert.toClientRect(contentAreaRect),
|
||||
panelRect: Convert.toClientRect(panelRect)
|
||||
});
|
||||
|
||||
return Convert.fromClientRect(userConstrainedPanelRect);
|
||||
}
|
||||
|
||||
return panelRect;
|
||||
};
|
||||
|
||||
return {
|
||||
calcInsert: calcInsert,
|
||||
calc: calc,
|
||||
userConstrain: userConstrain
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Matcher.js
|
||||
*
|
||||
* Released under LGPL License.
|
||||
* Copyright (c) 1999-2016 Ephox Corp. All rights reserved
|
||||
*
|
||||
* License: http://www.tinymce.com/license
|
||||
* Contributing: http://www.tinymce.com/contributing
|
||||
*/
|
||||
|
||||
define('tinymce/inlite/core/Matcher', [
|
||||
], function () {
|
||||
// result :: String, Rect -> Matcher.result
|
||||
var result = function (id, rect) {
|
||||
return {
|
||||
id: id,
|
||||
rect: rect
|
||||
};
|
||||
};
|
||||
|
||||
// match :: Editor, [(Editor -> Matcher.result | Null)] -> Matcher.result | Null
|
||||
var match = function (editor, matchers) {
|
||||
for (var i = 0; i < matchers.length; i++) {
|
||||
var f = matchers[i];
|
||||
var result = f(editor);
|
||||
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
return {
|
||||
match: match,
|
||||
result: result
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* Measure.js
|
||||
*
|
||||
* Released under LGPL License.
|
||||
* Copyright (c) 1999-2016 Ephox Corp. All rights reserved
|
||||
*
|
||||
* License: http://www.tinymce.com/license
|
||||
* Contributing: http://www.tinymce.com/contributing
|
||||
*/
|
||||
|
||||
define('tinymce/inlite/core/Measure', [
|
||||
'global!tinymce.DOM',
|
||||
'global!tinymce.geom.Rect',
|
||||
'tinymce/inlite/core/Convert'
|
||||
], function (DOM, Rect, Convert) {
|
||||
var toAbsolute = function (rect) {
|
||||
var vp = DOM.getViewPort();
|
||||
|
||||
return {
|
||||
x: rect.x + vp.x,
|
||||
y: rect.y + vp.y,
|
||||
w: rect.w,
|
||||
h: rect.h
|
||||
};
|
||||
};
|
||||
|
||||
var measureElement = function (elm) {
|
||||
var clientRect = elm.getBoundingClientRect();
|
||||
|
||||
return toAbsolute({
|
||||
x: clientRect.left,
|
||||
y: clientRect.top,
|
||||
w: Math.max(elm.clientWidth, elm.offsetWidth),
|
||||
h: Math.max(elm.clientHeight, elm.offsetHeight)
|
||||
});
|
||||
};
|
||||
|
||||
var getElementRect = function (editor, elm) {
|
||||
return measureElement(elm);
|
||||
};
|
||||
|
||||
var getPageAreaRect = function (editor) {
|
||||
return measureElement(editor.getElement().ownerDocument.body);
|
||||
};
|
||||
|
||||
var getContentAreaRect = function (editor) {
|
||||
return measureElement(editor.getContentAreaContainer() || editor.getBody());
|
||||
};
|
||||
|
||||
var getSelectionRect = function (editor) {
|
||||
var clientRect = editor.selection.getBoundingClientRect();
|
||||
return clientRect ? toAbsolute(Convert.fromClientRect(clientRect)) : null;
|
||||
};
|
||||
|
||||
return {
|
||||
getElementRect: getElementRect,
|
||||
getPageAreaRect: getPageAreaRect,
|
||||
getContentAreaRect: getContentAreaRect,
|
||||
getSelectionRect: getSelectionRect
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* PredicateId.js
|
||||
*
|
||||
* Released under LGPL License.
|
||||
* Copyright (c) 1999-2016 Ephox Corp. All rights reserved
|
||||
*
|
||||
* License: http://www.tinymce.com/license
|
||||
* Contributing: http://www.tinymce.com/contributing
|
||||
*/
|
||||
|
||||
define('tinymce/inlite/core/PredicateId', [
|
||||
'global!tinymce.util.Tools'
|
||||
], function (Tools) {
|
||||
var create = function (id, predicate) {
|
||||
return {
|
||||
id: id,
|
||||
predicate: predicate
|
||||
};
|
||||
};
|
||||
|
||||
// fromContextToolbars :: [ContextToolbar] -> [PredicateId]
|
||||
var fromContextToolbars = function (toolbars) {
|
||||
return Tools.map(toolbars, function (toolbar) {
|
||||
return create(toolbar.id, toolbar.predicate);
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
create: create,
|
||||
fromContextToolbars: fromContextToolbars
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* SelectionMatcher.js
|
||||
*
|
||||
* Released under LGPL License.
|
||||
* Copyright (c) 1999-2016 Ephox Corp. All rights reserved
|
||||
*
|
||||
* License: http://www.tinymce.com/license
|
||||
* Contributing: http://www.tinymce.com/contributing
|
||||
*/
|
||||
|
||||
define('tinymce/inlite/core/SelectionMatcher', [
|
||||
'tinymce/inlite/core/Matcher',
|
||||
'tinymce/inlite/core/Measure'
|
||||
], function (Matcher, Measure) {
|
||||
// textSelection :: String -> (Editor -> Matcher.result | Null)
|
||||
var textSelection = function (id) {
|
||||
return function (editor) {
|
||||
if (!editor.selection.isCollapsed()) {
|
||||
return Matcher.result(id, Measure.getSelectionRect(editor));
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
};
|
||||
|
||||
// emptyTextBlock :: [Elements], String -> (Editor -> Matcher.result | Null)
|
||||
var emptyTextBlock = function (elements, id) {
|
||||
return function (editor) {
|
||||
var i, textBlockElementsMap = editor.schema.getTextBlockElements();
|
||||
|
||||
for (i = 0; i < elements.length; i++) {
|
||||
if (elements[i].nodeName === 'TABLE') {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < elements.length; i++) {
|
||||
if (elements[i].nodeName in textBlockElementsMap) {
|
||||
if (editor.dom.isEmpty(elements[i])) {
|
||||
return Matcher.result(id, Measure.getSelectionRect(editor));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
};
|
||||
|
||||
return {
|
||||
textSelection: textSelection,
|
||||
emptyTextBlock: emptyTextBlock
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* SkinLoader.js
|
||||
*
|
||||
* Released under LGPL License.
|
||||
* Copyright (c) 1999-2016 Ephox Corp. All rights reserved
|
||||
*
|
||||
* License: http://www.tinymce.com/license
|
||||
* Contributing: http://www.tinymce.com/contributing
|
||||
*/
|
||||
|
||||
define('tinymce/inlite/core/SkinLoader', [
|
||||
'global!tinymce.EditorManager',
|
||||
'global!tinymce.DOM'
|
||||
], function (EditorManager, DOM) {
|
||||
var fireSkinLoaded = function (editor, callback) {
|
||||
var done = function () {
|
||||
editor.fire('SkinLoaded');
|
||||
callback();
|
||||
};
|
||||
|
||||
if (editor.initialized) {
|
||||
done();
|
||||
} else {
|
||||
editor.on('init', done);
|
||||
}
|
||||
};
|
||||
|
||||
var load = function (editor, skin, callback) {
|
||||
var baseUrl = EditorManager.baseURL;
|
||||
var skinUrl = baseUrl + '/skins/' + skin;
|
||||
|
||||
var done = function () {
|
||||
fireSkinLoaded(editor, callback);
|
||||
};
|
||||
|
||||
DOM.styleSheetLoader.load(skinUrl + '/skin.min.css', done);
|
||||
editor.contentCSS.push(skinUrl + '/content.inline.min.css');
|
||||
};
|
||||
|
||||
return {
|
||||
load: load
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* UrlType.js
|
||||
*
|
||||
* Released under LGPL License.
|
||||
* Copyright (c) 1999-2016 Ephox Corp. All rights reserved
|
||||
*
|
||||
* License: http://www.tinymce.com/license
|
||||
* Contributing: http://www.tinymce.com/contributing
|
||||
*/
|
||||
|
||||
define('tinymce/inlite/core/UrlType', [
|
||||
], function () {
|
||||
var isDomainLike = function (href) {
|
||||
return /^www\.|\.(com|org|edu|gov|uk|net|ca|de|jp|fr|au|us|ru|ch|it|nl|se|no|es|mil)$/i.test(href.trim());
|
||||
};
|
||||
|
||||
var isAbsolute = function (href) {
|
||||
return /^https?:\/\//.test(href.trim());
|
||||
};
|
||||
|
||||
return {
|
||||
isDomainLike: isDomainLike,
|
||||
isAbsolute: isAbsolute
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Conversions.js
|
||||
*
|
||||
* Released under LGPL License.
|
||||
* Copyright (c) 1999-2016 Ephox Corp. All rights reserved
|
||||
*
|
||||
* License: http://www.tinymce.com/license
|
||||
* Contributing: http://www.tinymce.com/contributing
|
||||
*/
|
||||
|
||||
define('tinymce/inlite/file/Conversions', [
|
||||
'global!tinymce.util.Promise'
|
||||
], function (Promise) {
|
||||
var blobToBase64 = function (blob) {
|
||||
return new Promise(function(resolve) {
|
||||
var reader = new FileReader();
|
||||
|
||||
reader.onloadend = function() {
|
||||
resolve(reader.result.split(',')[1]);
|
||||
};
|
||||
|
||||
reader.readAsDataURL(blob);
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
blobToBase64: blobToBase64
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Picker.js
|
||||
*
|
||||
* Released under LGPL License.
|
||||
* Copyright (c) 1999-2016 Ephox Corp. All rights reserved
|
||||
*
|
||||
* License: http://www.tinymce.com/license
|
||||
* Contributing: http://www.tinymce.com/contributing
|
||||
*/
|
||||
|
||||
define('tinymce/inlite/file/Picker', [
|
||||
'global!tinymce.util.Promise'
|
||||
], function (Promise) {
|
||||
var pickFile = function () {
|
||||
return new Promise(function (resolve) {
|
||||
var fileInput;
|
||||
|
||||
fileInput = document.createElement("input");
|
||||
fileInput.type = "file";
|
||||
fileInput.style.position = 'fixed';
|
||||
fileInput.style.left = 0;
|
||||
fileInput.style.top = 0;
|
||||
fileInput.style.opacity = 0.001;
|
||||
document.body.appendChild(fileInput);
|
||||
|
||||
fileInput.onchange = function(e) {
|
||||
resolve(Array.prototype.slice.call(e.target.files));
|
||||
};
|
||||
|
||||
fileInput.click();
|
||||
fileInput.parentNode.removeChild(fileInput);
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
pickFile: pickFile
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* Buttons.js
|
||||
*
|
||||
* Released under LGPL License.
|
||||
* Copyright (c) 1999-2016 Ephox Corp. All rights reserved
|
||||
*
|
||||
* License: http://www.tinymce.com/license
|
||||
* Contributing: http://www.tinymce.com/contributing
|
||||
*/
|
||||
|
||||
define('tinymce/inlite/ui/Buttons', [
|
||||
'tinymce/inlite/ui/Panel',
|
||||
'tinymce/inlite/file/Conversions',
|
||||
'tinymce/inlite/file/Picker',
|
||||
'tinymce/inlite/core/Actions'
|
||||
], function (Panel, Conversions, Picker, Actions) {
|
||||
var addHeaderButtons = function (editor) {
|
||||
var formatBlock = function (name) {
|
||||
return function () {
|
||||
Actions.formatBlock(editor, name);
|
||||
};
|
||||
};
|
||||
|
||||
for (var i = 1; i < 6; i++) {
|
||||
var name = 'h' + i;
|
||||
|
||||
editor.addButton(name, {
|
||||
text: name.toUpperCase(),
|
||||
tooltip: 'Heading ' + i,
|
||||
stateSelector: name,
|
||||
onclick: formatBlock(name),
|
||||
onPostRender: function () {
|
||||
// TODO: Remove this hack that produces bold H1-H6 when we have proper icons
|
||||
var span = this.getEl().firstChild.firstChild;
|
||||
span.style.fontWeight = 'bold';
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var addToEditor = function (editor, panel) {
|
||||
editor.addButton('quicklink', {
|
||||
icon: 'link',
|
||||
tooltip: 'Insert/Edit link',
|
||||
stateSelector: 'a[href]',
|
||||
onclick: function () {
|
||||
panel.showForm(editor, 'quicklink');
|
||||
}
|
||||
});
|
||||
|
||||
editor.addButton('quickimage', {
|
||||
icon: 'image',
|
||||
tooltip: 'Insert image',
|
||||
onclick: function () {
|
||||
Picker.pickFile().then(function (files) {
|
||||
var blob = files[0];
|
||||
|
||||
Conversions.blobToBase64(blob).then(function (base64) {
|
||||
Actions.insertBlob(editor, base64, blob);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
editor.addButton('quicktable', {
|
||||
icon: 'table',
|
||||
tooltip: 'Insert table',
|
||||
onclick: function () {
|
||||
panel.hide();
|
||||
Actions.insertTable(editor, 2, 2);
|
||||
}
|
||||
});
|
||||
|
||||
addHeaderButtons(editor);
|
||||
};
|
||||
|
||||
return {
|
||||
addToEditor: addToEditor
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* Forms.js
|
||||
*
|
||||
* Released under LGPL License.
|
||||
* Copyright (c) 1999-2016 Ephox Corp. All rights reserved
|
||||
*
|
||||
* License: http://www.tinymce.com/license
|
||||
* Contributing: http://www.tinymce.com/contributing
|
||||
*/
|
||||
|
||||
define('tinymce/inlite/ui/Forms', [
|
||||
'global!tinymce.util.Tools',
|
||||
'global!tinymce.ui.Factory',
|
||||
'global!tinymce.util.Promise',
|
||||
'tinymce/inlite/core/Actions',
|
||||
'tinymce/inlite/core/UrlType'
|
||||
], function (Tools, Factory, Promise, Actions, UrlType) {
|
||||
var focusFirstTextBox = function (form) {
|
||||
form.find('textbox').eq(0).each(function (ctrl) {
|
||||
ctrl.focus();
|
||||
});
|
||||
};
|
||||
|
||||
var createForm = function (name, spec) {
|
||||
var form = Factory.create(
|
||||
Tools.extend({
|
||||
type: 'form',
|
||||
layout: 'flex',
|
||||
direction: 'row',
|
||||
padding: 5,
|
||||
name: name,
|
||||
spacing: 3
|
||||
}, spec)
|
||||
);
|
||||
|
||||
form.on('show', function () {
|
||||
focusFirstTextBox(form);
|
||||
});
|
||||
|
||||
return form;
|
||||
};
|
||||
|
||||
var toggleVisibility = function (ctrl, state) {
|
||||
return state ? ctrl.show() : ctrl.hide();
|
||||
};
|
||||
|
||||
var askAboutPrefix = function (editor, href) {
|
||||
return new Promise(function (resolve) {
|
||||
editor.windowManager.confirm(
|
||||
'The URL you entered seems to be an external link. Do you want to add the required http:// prefix?',
|
||||
function (result) {
|
||||
var output = result === true ? 'http://' + href : href;
|
||||
resolve(output);
|
||||
}
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
var convertLinkToAbsolute = function (editor, href) {
|
||||
return !UrlType.isAbsolute(href) && UrlType.isDomainLike(href) ? askAboutPrefix(editor, href) : Promise.resolve(href);
|
||||
};
|
||||
|
||||
var createQuickLinkForm = function (editor, hide) {
|
||||
var unlink = function () {
|
||||
editor.focus();
|
||||
Actions.unlink(editor);
|
||||
hide();
|
||||
};
|
||||
|
||||
return createForm('quicklink', {
|
||||
items: [
|
||||
{type: 'button', name: 'unlink', icon: 'unlink', onclick: unlink, tooltip: 'Remove link'},
|
||||
{type: 'textbox', name: 'linkurl', placeholder: 'Paste or type a link'},
|
||||
{type: 'button', icon: 'checkmark', subtype: 'primary', tooltip: 'Ok', onclick: 'submit'}
|
||||
],
|
||||
onshow: function () {
|
||||
var elm, linkurl = '';
|
||||
|
||||
elm = editor.dom.getParent(editor.selection.getStart(), 'a[href]');
|
||||
if (elm) {
|
||||
linkurl = editor.dom.getAttrib(elm, 'href');
|
||||
}
|
||||
|
||||
this.fromJSON({
|
||||
linkurl: linkurl
|
||||
});
|
||||
|
||||
toggleVisibility(this.find('#unlink'), elm);
|
||||
},
|
||||
onsubmit: function (e) {
|
||||
convertLinkToAbsolute(editor, e.data.linkurl).then(function (url) {
|
||||
Actions.createLink(editor, url);
|
||||
hide();
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
createQuickLinkForm: createQuickLinkForm
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,218 @@
|
||||
/**
|
||||
* Panel.js
|
||||
*
|
||||
* Released under LGPL License.
|
||||
* Copyright (c) 1999-2016 Ephox Corp. All rights reserved
|
||||
*
|
||||
* License: http://www.tinymce.com/license
|
||||
* Contributing: http://www.tinymce.com/contributing
|
||||
*/
|
||||
|
||||
define('tinymce/inlite/ui/Panel', [
|
||||
'global!tinymce.util.Tools',
|
||||
'global!tinymce.ui.Factory',
|
||||
'global!tinymce.DOM',
|
||||
'tinymce/inlite/ui/Toolbar',
|
||||
'tinymce/inlite/ui/Forms',
|
||||
'tinymce/inlite/core/Measure',
|
||||
'tinymce/inlite/core/Layout'
|
||||
], function (Tools, Factory, DOM, Toolbar, Forms, Measure, Layout) {
|
||||
return function () {
|
||||
var DEFAULT_TEXT_SELECTION_ITEMS = 'bold italic | quicklink h2 h3 blockquote';
|
||||
var DEFAULT_INSERT_TOOLBAR_ITEMS = 'quickimage quicktable';
|
||||
var panel, currentRect;
|
||||
|
||||
var createToolbars = function (editor, toolbars) {
|
||||
return Tools.map(toolbars, function (toolbar) {
|
||||
return Toolbar.create(editor, toolbar.id, toolbar.items);
|
||||
});
|
||||
};
|
||||
|
||||
var getTextSelectionToolbarItems = function (settings) {
|
||||
var value = settings.selection_toolbar;
|
||||
return value ? value : DEFAULT_TEXT_SELECTION_ITEMS;
|
||||
};
|
||||
|
||||
var getInsertToolbarItems = function (settings) {
|
||||
var value = settings.insert_toolbar;
|
||||
return value ? value : DEFAULT_INSERT_TOOLBAR_ITEMS;
|
||||
};
|
||||
|
||||
var create = function (editor, toolbars) {
|
||||
var items, settings = editor.settings;
|
||||
|
||||
items = createToolbars(editor, toolbars);
|
||||
items = items.concat([
|
||||
Toolbar.create(editor, 'text', getTextSelectionToolbarItems(settings)),
|
||||
Toolbar.create(editor, 'insert', getInsertToolbarItems(settings)),
|
||||
Forms.createQuickLinkForm(editor, hide)
|
||||
]);
|
||||
|
||||
return Factory.create({
|
||||
type: 'floatpanel',
|
||||
role: 'dialog',
|
||||
classes: 'tinymce tinymce-inline arrow',
|
||||
ariaLabel: 'Inline toolbar',
|
||||
layout: 'flex',
|
||||
direction: 'column',
|
||||
align: 'stretch',
|
||||
autohide: false,
|
||||
autofix: true,
|
||||
fixed: true,
|
||||
border: 1,
|
||||
items: items,
|
||||
oncancel: function() {
|
||||
editor.focus();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var showPanel = function (panel) {
|
||||
if (panel) {
|
||||
panel.show();
|
||||
}
|
||||
};
|
||||
|
||||
var movePanelTo = function (panel, pos) {
|
||||
panel.moveTo(pos.x, pos.y);
|
||||
};
|
||||
|
||||
var togglePositionClass = function (panel, relPos) {
|
||||
relPos = relPos ? relPos.substr(0, 2) : '';
|
||||
|
||||
Tools.each({
|
||||
t: 'down',
|
||||
b: 'up',
|
||||
c: 'center'
|
||||
}, function(cls, pos) {
|
||||
panel.classes.toggle('arrow-' + cls, pos === relPos.substr(0, 1));
|
||||
});
|
||||
|
||||
if (relPos === 'cr') {
|
||||
panel.classes.toggle('arrow-left', true);
|
||||
panel.classes.toggle('arrow-right', false);
|
||||
} else if (relPos === 'cl') {
|
||||
panel.classes.toggle('arrow-left', true);
|
||||
panel.classes.toggle('arrow-right', true);
|
||||
} else {
|
||||
Tools.each({
|
||||
l: 'left',
|
||||
r: 'right'
|
||||
}, function(cls, pos) {
|
||||
panel.classes.toggle('arrow-' + cls, pos === relPos.substr(1, 1));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var showToolbar = function (panel, id) {
|
||||
var toolbars = panel.items().filter('#' + id);
|
||||
|
||||
if (toolbars.length > 0) {
|
||||
toolbars[0].show();
|
||||
panel.reflow();
|
||||
}
|
||||
};
|
||||
|
||||
var showPanelAt = function (panel, id, editor, targetRect) {
|
||||
var contentAreaRect, panelRect, result, userConstainHandler;
|
||||
|
||||
showPanel(panel);
|
||||
panel.items().hide();
|
||||
showToolbar(panel, id);
|
||||
|
||||
userConstainHandler = editor.settings.inline_toolbar_position_handler;
|
||||
contentAreaRect = Measure.getContentAreaRect(editor);
|
||||
panelRect = DOM.getRect(panel.getEl());
|
||||
|
||||
if (id === 'insert') {
|
||||
result = Layout.calcInsert(targetRect, contentAreaRect, panelRect);
|
||||
} else {
|
||||
result = Layout.calc(targetRect, contentAreaRect, panelRect);
|
||||
}
|
||||
|
||||
if (result) {
|
||||
panelRect = result.rect;
|
||||
currentRect = targetRect;
|
||||
movePanelTo(panel, Layout.userConstrain(userConstainHandler, targetRect, contentAreaRect, panelRect));
|
||||
|
||||
togglePositionClass(panel, result.position);
|
||||
} else {
|
||||
hide(panel);
|
||||
}
|
||||
};
|
||||
|
||||
var hasFormVisible = function () {
|
||||
return panel.items().filter('form:visible').length > 0;
|
||||
};
|
||||
|
||||
var showForm = function (editor, id) {
|
||||
if (panel) {
|
||||
panel.items().hide();
|
||||
showToolbar(panel, id);
|
||||
|
||||
var contentAreaRect, panelRect, result, userConstainHandler;
|
||||
|
||||
showPanel(panel);
|
||||
panel.items().hide();
|
||||
showToolbar(panel, id);
|
||||
|
||||
userConstainHandler = editor.settings.inline_toolbar_position_handler;
|
||||
contentAreaRect = Measure.getContentAreaRect(editor);
|
||||
panelRect = DOM.getRect(panel.getEl());
|
||||
|
||||
result = Layout.calc(currentRect, contentAreaRect, panelRect);
|
||||
|
||||
if (result) {
|
||||
panelRect = result.rect;
|
||||
movePanelTo(panel, Layout.userConstrain(userConstainHandler, currentRect, contentAreaRect, panelRect));
|
||||
|
||||
togglePositionClass(panel, result.position);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var show = function (editor, id, targetRect, toolbars) {
|
||||
if (!panel) {
|
||||
panel = create(editor, toolbars);
|
||||
panel.renderTo(document.body).reflow().moveTo(targetRect.x, targetRect.y);
|
||||
editor.nodeChanged();
|
||||
}
|
||||
|
||||
showPanelAt(panel, id, editor, targetRect);
|
||||
};
|
||||
|
||||
var hide = function () {
|
||||
if (panel) {
|
||||
panel.hide();
|
||||
}
|
||||
};
|
||||
|
||||
var focus = function () {
|
||||
if (panel) {
|
||||
panel.find('toolbar:visible').eq(0).each(function (item) {
|
||||
item.focus(true);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var remove = function () {
|
||||
if (panel) {
|
||||
panel.remove();
|
||||
panel = null;
|
||||
}
|
||||
};
|
||||
|
||||
var inForm = function () {
|
||||
return panel && panel.visible() && hasFormVisible();
|
||||
};
|
||||
|
||||
return {
|
||||
show: show,
|
||||
showForm: showForm,
|
||||
inForm: inForm,
|
||||
hide: hide,
|
||||
focus: focus,
|
||||
remove: remove
|
||||
};
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,126 @@
|
||||
/**
|
||||
* Toolbar.js
|
||||
*
|
||||
* Released under LGPL License.
|
||||
* Copyright (c) 1999-2016 Ephox Corp. All rights reserved
|
||||
*
|
||||
* License: http://www.tinymce.com/license
|
||||
* Contributing: http://www.tinymce.com/contributing
|
||||
*/
|
||||
|
||||
define('tinymce/inlite/ui/Toolbar', [
|
||||
'global!tinymce.util.Tools',
|
||||
'global!tinymce.ui.Factory'
|
||||
], function (Tools, Factory) {
|
||||
var setActiveItem = function (item, name) {
|
||||
return function(state, args) {
|
||||
var nodeName, i = args.parents.length;
|
||||
|
||||
while (i--) {
|
||||
nodeName = args.parents[i].nodeName;
|
||||
if (nodeName == 'OL' || nodeName == 'UL') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
item.active(state && nodeName == name);
|
||||
};
|
||||
};
|
||||
|
||||
var getSelectorStateResult = function (itemName, item) {
|
||||
var result = function (selector, handler) {
|
||||
return {
|
||||
selector: selector,
|
||||
handler: handler
|
||||
};
|
||||
};
|
||||
|
||||
var activeHandler = function(state) {
|
||||
item.active(state);
|
||||
};
|
||||
|
||||
var disabledHandler = function (state) {
|
||||
item.disabled(state);
|
||||
};
|
||||
|
||||
if (itemName == 'bullist') {
|
||||
return result('ul > li', setActiveItem(item, 'UL'));
|
||||
}
|
||||
|
||||
if (itemName == 'numlist') {
|
||||
return result('ol > li', setActiveItem(item, 'OL'));
|
||||
}
|
||||
|
||||
if (item.settings.stateSelector) {
|
||||
return result(item.settings.stateSelector, activeHandler);
|
||||
}
|
||||
|
||||
if (item.settings.disabledStateSelector) {
|
||||
return result(item.settings.disabledStateSelector, disabledHandler);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
var bindSelectorChanged = function (editor, itemName, item) {
|
||||
return function () {
|
||||
var result = getSelectorStateResult(itemName, item);
|
||||
if (result !== null) {
|
||||
editor.selection.selectorChanged(result.selector, result.handler);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
var create = function (editor, name, items) {
|
||||
var toolbarItems = [], buttonGroup;
|
||||
|
||||
if (!items) {
|
||||
return;
|
||||
}
|
||||
|
||||
Tools.each(items.split(/[ ,]/), function(item) {
|
||||
var itemName;
|
||||
|
||||
if (item == '|') {
|
||||
buttonGroup = null;
|
||||
} else {
|
||||
if (Factory.has(item)) {
|
||||
item = {type: item};
|
||||
toolbarItems.push(item);
|
||||
buttonGroup = null;
|
||||
} else {
|
||||
if (!buttonGroup) {
|
||||
buttonGroup = {type: 'buttongroup', items: []};
|
||||
toolbarItems.push(buttonGroup);
|
||||
}
|
||||
|
||||
if (editor.buttons[item]) {
|
||||
itemName = item;
|
||||
item = editor.buttons[itemName];
|
||||
|
||||
if (typeof item == 'function') {
|
||||
item = item();
|
||||
}
|
||||
|
||||
item.type = item.type || 'button';
|
||||
|
||||
item = Factory.create(item);
|
||||
item.on('postRender', bindSelectorChanged(editor, itemName, item));
|
||||
buttonGroup.items.push(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return Factory.create({
|
||||
type: 'toolbar',
|
||||
layout: 'flow',
|
||||
name: name,
|
||||
items: toolbarItems
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
create: create
|
||||
};
|
||||
});
|
||||
14
plugins/tinymce/themes/inlite/src/test/.eslintrc
Normal file
14
plugins/tinymce/themes/inlite/src/test/.eslintrc
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"env": {
|
||||
"browser": true,
|
||||
"amd": true
|
||||
},
|
||||
|
||||
"globals": {
|
||||
"assert": true,
|
||||
"test": true,
|
||||
"asynctest": true
|
||||
},
|
||||
|
||||
"extends": "../../../../../../.eslintrc"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
test('atomic/alien/ArrTest', [
|
||||
'tinymce/inlite/alien/Arr'
|
||||
], function (Arr) {
|
||||
var testFlatten = function () {
|
||||
assert.eq(Arr.flatten([1, 2, [3, 4, [5, 6]], [7, 8], 9]), [1, 2, 3, 4, 5, 6, 7, 8, 9]);
|
||||
};
|
||||
|
||||
testFlatten();
|
||||
});
|
||||
@@ -0,0 +1,10 @@
|
||||
test('atomic/alien/UuidTest', [
|
||||
'tinymce/inlite/alien/Uuid'
|
||||
], function (Uuid) {
|
||||
var testUuid = function () {
|
||||
assert.eq(Uuid.uuid('mce').indexOf('mce'), 0);
|
||||
assert.eq(Uuid.uuid('mce') !== Uuid.uuid('mce'), true);
|
||||
};
|
||||
|
||||
testUuid();
|
||||
});
|
||||
@@ -0,0 +1,12 @@
|
||||
test('atomic/core/ConvertTest', [
|
||||
'tinymce/inlite/core/Convert'
|
||||
], function (Convert) {
|
||||
var testConvert = function () {
|
||||
assert.eq({x: 1, y: 2, w: 3, h: 4}, Convert.fromClientRect({left: 1, top: 2, width: 3, height: 4}));
|
||||
assert.eq({x: 2, y: 3, w: 4, h: 5}, Convert.fromClientRect({left: 2, top: 3, width: 4, height: 5}));
|
||||
assert.eq({left: 1, top: 2, width: 3, height: 4, bottom: 2 + 4, right: 1 + 3}, Convert.toClientRect({x: 1, y: 2, w: 3, h: 4}));
|
||||
assert.eq({left: 2, top: 3, width: 4, height: 5, bottom: 3 + 5, right: 2 + 4}, Convert.toClientRect({x: 2, y: 3, w: 4, h: 5}));
|
||||
};
|
||||
|
||||
testConvert();
|
||||
});
|
||||
@@ -0,0 +1,51 @@
|
||||
test('browser/atomic/MatcherTest', [
|
||||
'tinymce/inlite/core/Matcher'
|
||||
], function (Matcher) {
|
||||
var testMatch = function (mockEditor, matches, expectedResult) {
|
||||
var result;
|
||||
|
||||
result = Matcher.match(mockEditor, matches);
|
||||
assert.eq(expectedResult, result);
|
||||
};
|
||||
|
||||
var match = function (key) {
|
||||
return function (editor) {
|
||||
return editor[key];
|
||||
};
|
||||
};
|
||||
|
||||
var testMatcher = function () {
|
||||
var mockEditor = {
|
||||
success1: 'success1',
|
||||
success2: 'success2',
|
||||
failure: null
|
||||
};
|
||||
|
||||
testMatch(mockEditor, [
|
||||
match('success1')
|
||||
], 'success1');
|
||||
|
||||
testMatch(mockEditor, [
|
||||
match(null),
|
||||
match('success2')
|
||||
], 'success2');
|
||||
|
||||
testMatch(mockEditor, [
|
||||
match('success1'),
|
||||
match('success2')
|
||||
], 'success1');
|
||||
|
||||
testMatch(mockEditor, [
|
||||
match(null)
|
||||
], null);
|
||||
|
||||
testMatch(mockEditor, [
|
||||
match(null),
|
||||
match(null)
|
||||
], null);
|
||||
|
||||
testMatch(mockEditor, [], null);
|
||||
};
|
||||
|
||||
testMatcher();
|
||||
});
|
||||
@@ -0,0 +1,33 @@
|
||||
test('atomic/core/UrlTypeTest', [
|
||||
'tinymce/inlite/core/UrlType'
|
||||
], function (UrlType) {
|
||||
var testIsDomainLike = function () {
|
||||
var mostUsedTopLevelDomains = [
|
||||
'com', 'org', 'edu', 'gov', 'uk', 'net', 'ca', 'de', 'jp',
|
||||
'fr', 'au', 'us', 'ru', 'ch', 'it', 'nl', 'se', 'no', 'es', 'mil'
|
||||
];
|
||||
|
||||
assert.eq(UrlType.isDomainLike('www.site.com'), true);
|
||||
assert.eq(UrlType.isDomainLike('www.site.xyz'), true);
|
||||
assert.eq(UrlType.isDomainLike(' www.site.xyz'), true);
|
||||
assert.eq(UrlType.isDomainLike('site.xyz'), false);
|
||||
|
||||
mostUsedTopLevelDomains.forEach(function (tld) {
|
||||
assert.eq(UrlType.isDomainLike('site.' + tld), true);
|
||||
assert.eq(UrlType.isDomainLike(' site.' + tld), true);
|
||||
assert.eq(UrlType.isDomainLike('site.' + tld + ' '), true);
|
||||
});
|
||||
|
||||
assert.eq(UrlType.isDomainLike('/a/b'), false);
|
||||
};
|
||||
|
||||
var testIsAbsoluteUrl = function () {
|
||||
assert.eq(UrlType.isAbsolute('http://www.site.com'), true);
|
||||
assert.eq(UrlType.isAbsolute('https://www.site.com'), true);
|
||||
assert.eq(UrlType.isAbsolute('www.site.com'), false);
|
||||
assert.eq(UrlType.isAbsolute('file.gif'), false);
|
||||
};
|
||||
|
||||
testIsDomainLike();
|
||||
testIsAbsoluteUrl();
|
||||
});
|
||||
202
plugins/tinymce/themes/inlite/src/test/js/browser/ThemeTest.js
Normal file
202
plugins/tinymce/themes/inlite/src/test/js/browser/ThemeTest.js
Normal file
@@ -0,0 +1,202 @@
|
||||
asynctest('browser/core/ThemeTest', [
|
||||
'ephox.mcagar.api.TinyLoader',
|
||||
'ephox.mcagar.api.TinyApis',
|
||||
'ephox.mcagar.api.TinyActions',
|
||||
'ephox.mcagar.api.TinyDom',
|
||||
'tinymce/inlite/Theme',
|
||||
'ephox.agar.api.Pipeline',
|
||||
'ephox.agar.api.Chain',
|
||||
'ephox.agar.api.UiFinder',
|
||||
'ephox.agar.api.Mouse',
|
||||
'ephox.agar.api.GeneralSteps',
|
||||
'ephox.agar.api.UiControls',
|
||||
'ephox.agar.api.FocusTools'
|
||||
], function (TinyLoader, TinyApis, TinyActions, TinyDom, Theme, Pipeline, Chain, UiFinder, Mouse, GeneralSteps, UiControls, FocusTools) {
|
||||
var success = arguments[arguments.length - 2];
|
||||
var failure = arguments[arguments.length - 1];
|
||||
var dialogRoot = TinyDom.fromDom(document.body);
|
||||
|
||||
var cWaitForContextToolbar = Chain.fromChainsWith(dialogRoot, [
|
||||
UiFinder.cWaitForState('label', '.mce-tinymce-inline', function (elm) {
|
||||
return elm.dom().style.display === "";
|
||||
})
|
||||
]);
|
||||
|
||||
var cClickToolbarButton = function (ariaLabel) {
|
||||
return Chain.fromChains([
|
||||
UiFinder.cFindIn('div[aria-label="' + ariaLabel + '"]'),
|
||||
Mouse.cTrueClick
|
||||
]);
|
||||
};
|
||||
|
||||
var sClickFocusedButton = Chain.asStep(TinyDom.fromDom(document), [
|
||||
FocusTools.cGetFocused,
|
||||
Mouse.cTrueClick
|
||||
]);
|
||||
|
||||
var sClickContextButton = function (ariaLabel) {
|
||||
return Chain.asStep({}, [
|
||||
cWaitForContextToolbar,
|
||||
cClickToolbarButton(ariaLabel)
|
||||
]);
|
||||
};
|
||||
|
||||
var sWaitForToolbar = function () {
|
||||
return Chain.asStep({}, [
|
||||
cWaitForContextToolbar
|
||||
]);
|
||||
};
|
||||
|
||||
var sBoldTests = function (tinyApis) {
|
||||
return GeneralSteps.sequence([
|
||||
tinyApis.sSetContent('<p>a</p>'),
|
||||
tinyApis.sSetSelection([0, 0], 0, [0, 0], 1),
|
||||
sClickContextButton('Bold'),
|
||||
tinyApis.sAssertContent('<p><strong>a</strong></p>')
|
||||
]);
|
||||
};
|
||||
|
||||
var sH2Tests = function (tinyApis) {
|
||||
return GeneralSteps.sequence([
|
||||
tinyApis.sSetContent('<p>a</p>'),
|
||||
tinyApis.sSetSelection([0, 0], 0, [0, 0], 1),
|
||||
sClickContextButton('Heading 2'),
|
||||
tinyApis.sAssertContent('<h2>a</h2>')
|
||||
]);
|
||||
};
|
||||
|
||||
var sInsertLink = function (url) {
|
||||
return Chain.asStep({}, [
|
||||
cWaitForContextToolbar,
|
||||
cClickToolbarButton('Insert/Edit link'),
|
||||
cWaitForContextToolbar,
|
||||
UiFinder.cFindIn('input'),
|
||||
UiControls.cSetValue(url),
|
||||
cWaitForContextToolbar,
|
||||
cClickToolbarButton('Ok')
|
||||
]);
|
||||
};
|
||||
|
||||
var cWaitForConfirmDialog = Chain.fromChainsWith(dialogRoot, [
|
||||
UiFinder.cWaitForState('window element', '.mce-window', function () {
|
||||
return true;
|
||||
})
|
||||
]);
|
||||
|
||||
var cClickButton = function (btnText) {
|
||||
return Chain.fromChains([
|
||||
UiFinder.cFindIn('button:contains("' + btnText + '")'),
|
||||
Mouse.cTrueClick
|
||||
]);
|
||||
};
|
||||
|
||||
var sClickConfirmButton = function (btnText) {
|
||||
return Chain.asStep({}, [
|
||||
cWaitForConfirmDialog,
|
||||
cClickButton(btnText)
|
||||
]);
|
||||
};
|
||||
|
||||
var sInsertLinkConfirmPrefix = function (url, btnText) {
|
||||
return GeneralSteps.sequence([
|
||||
sInsertLink(url),
|
||||
sClickConfirmButton(btnText)
|
||||
]);
|
||||
};
|
||||
|
||||
var sUnlink = Chain.asStep({}, [
|
||||
cWaitForContextToolbar,
|
||||
cClickToolbarButton('Insert/Edit link'),
|
||||
cWaitForContextToolbar,
|
||||
cClickToolbarButton('Remove link')
|
||||
]);
|
||||
|
||||
var sLinkTests = function (tinyApis) {
|
||||
var sContentActionTest = function (inputHtml, spath, soffset, fpath, foffset, expectedHtml, sAction) {
|
||||
return GeneralSteps.sequence([
|
||||
tinyApis.sSetContent(inputHtml),
|
||||
tinyApis.sSetSelection(spath, soffset, fpath, foffset),
|
||||
sAction,
|
||||
tinyApis.sAssertContent(expectedHtml)
|
||||
]);
|
||||
};
|
||||
|
||||
var sLinkTest = function (inputHtml, spath, soffset, fpath, foffset, url, expectedHtml) {
|
||||
return sContentActionTest(inputHtml, spath, soffset, fpath, foffset, expectedHtml, sInsertLink(url));
|
||||
};
|
||||
|
||||
var sUnlinkTest = function (inputHtml, spath, soffset, fpath, foffset, expectedHtml) {
|
||||
return sContentActionTest(inputHtml, spath, soffset, fpath, foffset, expectedHtml, sUnlink);
|
||||
};
|
||||
|
||||
var sLinkWithConfirmOkTest = function (inputHtml, spath, soffset, fpath, foffset, url, expectedHtml) {
|
||||
return sContentActionTest(inputHtml, spath, soffset, fpath, foffset, expectedHtml, sInsertLinkConfirmPrefix(url, 'Ok'));
|
||||
};
|
||||
|
||||
var sLinkWithConfirmCancelTest = function (inputHtml, spath, soffset, fpath, foffset, url, expectedHtml) {
|
||||
return sContentActionTest(inputHtml, spath, soffset, fpath, foffset, expectedHtml, sInsertLinkConfirmPrefix(url, 'Cancel'));
|
||||
};
|
||||
|
||||
return GeneralSteps.sequence([
|
||||
sLinkWithConfirmOkTest('<p>a</p>', [0, 0], 0, [0, 0], 1, 'www.site.com', '<p><a href="http://www.site.com">a</a></p>'),
|
||||
sLinkWithConfirmCancelTest('<p>a</p>', [0, 0], 0, [0, 0], 1, 'www.site.com', '<p><a href="www.site.com">a</a></p>'),
|
||||
sLinkTest('<p>a</p>', [0, 0], 0, [0, 0], 1, '#1', '<p><a href="#1">a</a></p>'),
|
||||
sLinkTest('<p><a id="x" href="#1">a</a></p>', [0, 0, 0], 0, [0, 0, 0], 1, '#2', '<p><a id="x" href="#2">a</a></p>'),
|
||||
sLinkTest('<p><a href="#3">a</a></p>', [0, 0, 0], 0, [0, 0, 0], 1, '', '<p>a</p>'),
|
||||
sUnlinkTest('<p><a id="x" href="#1">a</a></p>', [0, 0, 0], 0, [0, 0, 0], 1, '<p>a</p>')
|
||||
]);
|
||||
};
|
||||
|
||||
var sInsertTableTests = function (tinyApis) {
|
||||
return GeneralSteps.sequence([
|
||||
tinyApis.sSetContent('<p><br></p><p>b</p>'),
|
||||
tinyApis.sSetCursor([0], 0),
|
||||
sClickContextButton('Insert table'),
|
||||
tinyApis.sAssertContent([
|
||||
'<table style="width: 100%;">',
|
||||
'<tbody>',
|
||||
'<tr>',
|
||||
'<td> </td>',
|
||||
'<td> </td>',
|
||||
'</tr>',
|
||||
'<tr>',
|
||||
'<td> </td>',
|
||||
'<td> </td>',
|
||||
'</tr>',
|
||||
'</tbody>',
|
||||
'</table>',
|
||||
'<p>b</p>'
|
||||
].join('\n')
|
||||
)
|
||||
]);
|
||||
};
|
||||
|
||||
var sAriaTests = function (tinyApis, tinyActions) {
|
||||
return GeneralSteps.sequence([
|
||||
tinyApis.sSetContent('<p>a</p>'),
|
||||
tinyApis.sSetSelection([0, 0], 0, [0, 0], 1),
|
||||
sWaitForToolbar(),
|
||||
tinyActions.sContentKeydown(121, {alt: true}),
|
||||
sClickFocusedButton,
|
||||
tinyApis.sAssertContent('<p><strong>a</strong></p>')
|
||||
]);
|
||||
};
|
||||
|
||||
TinyLoader.setup(function (editor, onSuccess, onFailure) {
|
||||
var tinyApis = TinyApis(editor), tinyActions = TinyActions(editor);
|
||||
|
||||
Pipeline.async({}, [
|
||||
sBoldTests(tinyApis),
|
||||
sH2Tests(tinyApis),
|
||||
sLinkTests(tinyApis),
|
||||
sInsertTableTests(tinyApis),
|
||||
sAriaTests(tinyApis, tinyActions)
|
||||
], onSuccess, onFailure);
|
||||
}, {
|
||||
theme: 'inlite',
|
||||
plugins: 'image table link paste contextmenu textpattern',
|
||||
insert_toolbar: 'quickimage media quicktable',
|
||||
selection_toolbar: 'bold italic | quicklink h1 h2 blockquote',
|
||||
inline: true
|
||||
}, success, failure);
|
||||
});
|
||||
@@ -0,0 +1,65 @@
|
||||
asynctest('browser/alien/BookmarkTest', [
|
||||
'ephox/tinymce',
|
||||
'ephox.agar.api.Pipeline',
|
||||
'ephox.agar.api.Chain',
|
||||
'ephox.agar.api.Cursors',
|
||||
'ephox.agar.api.Assertions',
|
||||
'ephox.mcagar.api.TinyDom',
|
||||
'tinymce/inlite/alien/Bookmark'
|
||||
], function (tinymce, Pipeline, Chain, Cursors, Assertions, TinyDom, Bookmark) {
|
||||
var success = arguments[arguments.length - 2];
|
||||
var failure = arguments[arguments.length - 1];
|
||||
|
||||
var toNativeRange = function (range) {
|
||||
var domRange = document.createRange();
|
||||
domRange.setStart(range.start().dom(), range.soffset());
|
||||
domRange.setEnd(range.finish().dom(), range.foffset());
|
||||
return domRange;
|
||||
};
|
||||
|
||||
var rangeToBookmark = function (dom) {
|
||||
return function (range) {
|
||||
return Bookmark.create(dom, range);
|
||||
};
|
||||
};
|
||||
|
||||
var bookmarkToRange = function (dom) {
|
||||
return function (bookmark) {
|
||||
return Bookmark.resolve(dom, bookmark);
|
||||
};
|
||||
};
|
||||
|
||||
var cAssertRangeEq = function (expected) {
|
||||
return Chain.op(function (actual) {
|
||||
Assertions.assertEq('Not equal startContainer', expected.start().dom(), actual.startContainer);
|
||||
Assertions.assertEq('Not equal startOffset', expected.soffset(), actual.startOffset);
|
||||
Assertions.assertEq('Not equal endContainer', expected.finish().dom(), actual.endContainer);
|
||||
Assertions.assertEq('Not equal endOffset', expected.foffset(), actual.endOffset);
|
||||
});
|
||||
};
|
||||
|
||||
var sTestBookmark = function (html, path) {
|
||||
var dom = tinymce.DOM;
|
||||
var elm = TinyDom.fromDom(dom.create('div', {}, html));
|
||||
|
||||
return Chain.asStep(elm, [
|
||||
Cursors.cFollowPath(Cursors.pathFrom(path)),
|
||||
Chain.mapper(toNativeRange),
|
||||
Chain.mapper(rangeToBookmark(dom)),
|
||||
Chain.mapper(bookmarkToRange(dom)),
|
||||
cAssertRangeEq(Cursors.calculate(elm, Cursors.pathFrom(path)))
|
||||
]);
|
||||
};
|
||||
|
||||
Pipeline.async({}, [
|
||||
sTestBookmark('abc', {element: [0], offset: 0}),
|
||||
sTestBookmark('abc', {element: [0], offset: 1}),
|
||||
sTestBookmark('abc', {start: {element: [0], offset: 0}, finish: {element: [0], offset: 1}}),
|
||||
sTestBookmark('<b>a</b>', {element: [0, 0], offset: 0}),
|
||||
sTestBookmark('<b>a</b>', {element: [0, 0], offset: 0}),
|
||||
sTestBookmark('<b>a</b>', {start: {element: [0, 0], offset: 0}, finish: {element: [0, 0], offset: 1}}),
|
||||
sTestBookmark('<b>a</b><b>b</b>', {start: {element: [0, 0], offset: 0}, finish: {element: [1, 0], offset: 1}})
|
||||
], function () {
|
||||
success();
|
||||
}, failure);
|
||||
});
|
||||
@@ -0,0 +1,38 @@
|
||||
asynctest('browser/alien/UnlinkTest', [
|
||||
'ephox.mcagar.api.TinyLoader',
|
||||
'ephox.mcagar.api.TinyApis',
|
||||
'tinymce/inlite/alien/Unlink',
|
||||
'ephox.agar.api.Pipeline',
|
||||
'ephox.agar.api.Step',
|
||||
'ephox.agar.api.GeneralSteps'
|
||||
], function (TinyLoader, TinyApis, Unlink, Pipeline, Step, GeneralSteps) {
|
||||
var success = arguments[arguments.length - 2];
|
||||
var failure = arguments[arguments.length - 1];
|
||||
|
||||
var sUnlinkSelection = function (editor) {
|
||||
return Step.sync(function () {
|
||||
Unlink.unlinkSelection(editor);
|
||||
});
|
||||
};
|
||||
|
||||
TinyLoader.setup(function (editor, onSuccess, onFailure) {
|
||||
var tinyApis = TinyApis(editor);
|
||||
|
||||
var sAssertUnlink = function (inputHtml, startPath, startOffset, finishPath, finishOffset, expectedHtml) {
|
||||
return GeneralSteps.sequence([
|
||||
tinyApis.sSetContent(inputHtml),
|
||||
tinyApis.sSetSelection(startPath, startOffset, finishPath, finishOffset),
|
||||
sUnlinkSelection(editor),
|
||||
tinyApis.sAssertContent(expectedHtml, 'Should match expected anchor less html')
|
||||
]);
|
||||
};
|
||||
|
||||
Pipeline.async({}, [
|
||||
sAssertUnlink('<p><a href="#">a</a></p>', [0, 0, 0], 0, [0, 0, 0], 1, '<p>a</p>'),
|
||||
sAssertUnlink('<p><a href="#">a</a>b</p>', [0, 0, 0], 0, [0, 1], 1, '<p>ab</p>'),
|
||||
sAssertUnlink('<p><a href="#">a</a><p><a href="#">b</a>', [0, 0, 0], 0, [0, 0, 0], 1, '<p>a</p>\n<p><a href="#">b</a></p>'),
|
||||
sAssertUnlink('<p><a href="#">a</a><p><a href="#">b</a>', [0, 0, 0], 0, [1, 0, 0], 1, '<p>a</p>\n<p>b</p>')
|
||||
], onSuccess, onFailure);
|
||||
}, {
|
||||
}, success, failure);
|
||||
});
|
||||
@@ -0,0 +1,177 @@
|
||||
asynctest('browser/core/ActionsTest', [
|
||||
'ephox.mcagar.api.TinyLoader',
|
||||
'ephox.mcagar.api.TinyApis',
|
||||
'tinymce/inlite/core/Actions',
|
||||
'ephox.agar.api.Pipeline',
|
||||
'ephox.agar.api.Step',
|
||||
'ephox.agar.api.GeneralSteps'
|
||||
], function (TinyLoader, TinyApis, Actions, Pipeline, Step, GeneralSteps) {
|
||||
var success = arguments[arguments.length - 2];
|
||||
var failure = arguments[arguments.length - 1];
|
||||
|
||||
var wrap = function (f, args) {
|
||||
return function () {
|
||||
var currentArgs = Array.prototype.slice.call(arguments);
|
||||
return Step.sync(function () {
|
||||
f.apply(null, [].concat(args).concat(currentArgs));
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
var sInsertTableTests = function (editor, tinyApis) {
|
||||
var sInsertTableTest = function (cols, rows, expectedHtml, message) {
|
||||
var sInsertTable = wrap(Actions.insertTable, editor);
|
||||
|
||||
return GeneralSteps.sequence([
|
||||
tinyApis.sSetContent(''),
|
||||
sInsertTable(cols, rows),
|
||||
tinyApis.sAssertContent(expectedHtml, message)
|
||||
]);
|
||||
};
|
||||
|
||||
return GeneralSteps.sequence([
|
||||
sInsertTableTest(2, 3, [
|
||||
'<table style="width: 100%;">',
|
||||
'<tbody>',
|
||||
'<tr>',
|
||||
'<td> </td>',
|
||||
'<td> </td>',
|
||||
'</tr>',
|
||||
'<tr>',
|
||||
'<td> </td>',
|
||||
'<td> </td>',
|
||||
'</tr>',
|
||||
'<tr>',
|
||||
'<td> </td>',
|
||||
'<td> </td>',
|
||||
'</tr>',
|
||||
'</tbody>',
|
||||
'</table>'
|
||||
].join('\n'),
|
||||
'Should be a 2x3 table'
|
||||
),
|
||||
|
||||
sInsertTableTest(3, 2, [
|
||||
'<table style="width: 100%;">',
|
||||
'<tbody>',
|
||||
'<tr>',
|
||||
'<td> </td>',
|
||||
'<td> </td>',
|
||||
'<td> </td>',
|
||||
'</tr>',
|
||||
'<tr>',
|
||||
'<td> </td>',
|
||||
'<td> </td>',
|
||||
'<td> </td>',
|
||||
'</tr>',
|
||||
'</tbody>',
|
||||
'</table>'
|
||||
].join('\n'),
|
||||
'Should be a 3x2 table'
|
||||
)
|
||||
]);
|
||||
};
|
||||
|
||||
var sFormatBlockTests = function (editor, tinyApis) {
|
||||
var sFormatBlockTest = function (name) {
|
||||
var sFormatBlock = wrap(Actions.formatBlock, editor);
|
||||
|
||||
return GeneralSteps.sequence([
|
||||
tinyApis.sSetContent('<p>a</p>'),
|
||||
tinyApis.sSetCursor([0], 0),
|
||||
sFormatBlock(name),
|
||||
tinyApis.sAssertContent('<' + name + '>a</' + name + '>', 'Should be a ' + name + ' block')
|
||||
]);
|
||||
};
|
||||
|
||||
return GeneralSteps.sequence([
|
||||
sFormatBlockTest('h1'),
|
||||
sFormatBlockTest('h2'),
|
||||
sFormatBlockTest('pre')
|
||||
]);
|
||||
};
|
||||
|
||||
var sCreateLinkTests = function (editor, tinyApis) {
|
||||
var sCreateLinkTest = function (inputHtml, url, sPath, sOffset, fPath, fOffset, expectedHtml) {
|
||||
var sCreateLink = wrap(Actions.createLink, editor);
|
||||
|
||||
return GeneralSteps.sequence([
|
||||
tinyApis.sSetContent(inputHtml),
|
||||
tinyApis.sSetSelection(sPath, sOffset, fPath, fOffset),
|
||||
sCreateLink(url),
|
||||
tinyApis.sAssertContent(expectedHtml, 'Should have a link')
|
||||
]);
|
||||
};
|
||||
|
||||
return GeneralSteps.sequence([
|
||||
sCreateLinkTest('<p>a</p>', '#1', [0, 0], 0, [0, 0], 1, '<p><a href="#1">a</a></p>'),
|
||||
sCreateLinkTest('<p><a href="#1">a</a></p>', '#2', [0, 0], 0, [0, 0], 1, '<p><a href="#2">a</a></p>'),
|
||||
sCreateLinkTest('<p><a href="#1"><em>a</em></a></p>', '#2', [0, 0, 0], 0, [0, 0, 0], 1, '<p><a href="#2"><em>a</em></a></p>')
|
||||
]);
|
||||
};
|
||||
|
||||
var sUnlinkTests = function (editor, tinyApis) {
|
||||
var sUnlinkTest = function (inputHtml, sPath, sOffset, fPath, fOffset, expectedHtml) {
|
||||
var sUnlink = wrap(Actions.unlink, editor);
|
||||
|
||||
return GeneralSteps.sequence([
|
||||
tinyApis.sSetContent(inputHtml),
|
||||
tinyApis.sSetSelection(sPath, sOffset, fPath, fOffset),
|
||||
sUnlink(),
|
||||
tinyApis.sAssertContent(expectedHtml, 'Should not have a link')
|
||||
]);
|
||||
};
|
||||
|
||||
return GeneralSteps.sequence([
|
||||
sUnlinkTest('<p>a</p>', [0, 0], 0, [0, 0], 1, '<p>a</p>'),
|
||||
sUnlinkTest('<p><a href="#">a</a></p>', [0, 0, 0], 0, [0, 0, 0], 1, '<p>a</p>'),
|
||||
sUnlinkTest('<p><a href="#"><em>a</em></a></p>', [0, 0, 0], 0, [0, 0, 0], 1, '<p><em>a</em></p>'),
|
||||
sUnlinkTest('<p><a href="#">a</a>b</p>', [0, 0, 0], 0, [0, 1], 1, '<p>ab</p>')
|
||||
]);
|
||||
};
|
||||
|
||||
var base64ToBlob = function (base64, type) {
|
||||
var buff = atob(base64);
|
||||
var bytes = new Uint8Array(buff.length);
|
||||
|
||||
for (var i = 0; i < bytes.length; i++) {
|
||||
bytes[i] = buff.charCodeAt(i);
|
||||
}
|
||||
|
||||
return new Blob([bytes], {type: type});
|
||||
};
|
||||
|
||||
var sInsertBlobTests = function (editor, tinyApis) {
|
||||
var sInsertBlobTest = function (inputHtml, path, offset, blob, base64, expectedHtml) {
|
||||
var sInsertBlob = wrap(Actions.insertBlob, editor);
|
||||
|
||||
return GeneralSteps.sequence([
|
||||
tinyApis.sSetContent(inputHtml),
|
||||
tinyApis.sSetCursor(path, offset),
|
||||
sInsertBlob(blob, base64),
|
||||
tinyApis.sAssertContent(expectedHtml, 'Should have a image')
|
||||
]);
|
||||
};
|
||||
|
||||
var base64 = 'R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';
|
||||
var blob = base64ToBlob(base64, 'image/gif');
|
||||
|
||||
return GeneralSteps.sequence([
|
||||
sInsertBlobTest('<p>a</p>', [0, 0], 0, base64, blob, '<p><img src="data:image/gif;base64,' + base64 + '" />a</p>')
|
||||
]);
|
||||
};
|
||||
|
||||
TinyLoader.setup(function (editor, onSuccess, onFailure) {
|
||||
var tinyApis = TinyApis(editor);
|
||||
|
||||
Pipeline.async({}, [
|
||||
sInsertTableTests(editor, tinyApis),
|
||||
sFormatBlockTests(editor, tinyApis),
|
||||
sInsertBlobTests(editor, tinyApis),
|
||||
sCreateLinkTests(editor, tinyApis),
|
||||
sUnlinkTests(editor, tinyApis)
|
||||
], onSuccess, onFailure);
|
||||
}, {
|
||||
inline: true
|
||||
}, success, failure);
|
||||
});
|
||||
@@ -0,0 +1,69 @@
|
||||
asynctest('browser/core/ElementMatcherTest', [
|
||||
'ephox.mcagar.api.TinyLoader',
|
||||
'ephox.mcagar.api.TinyApis',
|
||||
'ephox.agar.api.Step',
|
||||
'ephox.agar.api.Assertions',
|
||||
'tinymce/inlite/core/ElementMatcher',
|
||||
'tinymce/inlite/core/PredicateId',
|
||||
'ephox.agar.api.Pipeline'
|
||||
], function (TinyLoader, TinyApis, Step, Assertions, ElementMatcher, PredicateId, Pipeline) {
|
||||
var success = arguments[arguments.length - 2];
|
||||
var failure = arguments[arguments.length - 1];
|
||||
|
||||
var eq = function (target) {
|
||||
return function (elm) {
|
||||
return elm === target;
|
||||
};
|
||||
};
|
||||
|
||||
var constantFalse = function (/*elm*/) {
|
||||
return false;
|
||||
};
|
||||
|
||||
var sElementTest = function (tinyApis, editor, inputHtml, selector) {
|
||||
return Step.sync(function () {
|
||||
var target, result;
|
||||
|
||||
editor.setContent(inputHtml);
|
||||
target = editor.dom.select(selector)[0];
|
||||
|
||||
result = ElementMatcher.element(target, [
|
||||
PredicateId.create('a', constantFalse),
|
||||
PredicateId.create('b', eq(target))
|
||||
])(editor);
|
||||
|
||||
Assertions.assertEq(result.id, 'b', 'Should be matching B');
|
||||
Assertions.assertEq(result.rect.w > 0, true, 'Should be have width');
|
||||
});
|
||||
};
|
||||
|
||||
var sParentTest = function (tinyApis, editor, inputHtml, selector) {
|
||||
return Step.sync(function () {
|
||||
var target, parents, result;
|
||||
|
||||
editor.setContent(inputHtml);
|
||||
target = editor.dom.select(selector)[0];
|
||||
parents = editor.dom.getParents(target);
|
||||
|
||||
result = ElementMatcher.parent(parents, [
|
||||
PredicateId.create('a', constantFalse),
|
||||
PredicateId.create('b', eq(parents[1])),
|
||||
PredicateId.create('c', eq(parents[0]))
|
||||
])(editor);
|
||||
|
||||
Assertions.assertEq(result.id, 'c', 'Should be matching C the closest one');
|
||||
Assertions.assertEq(result.rect.w > 0, true, 'Should be have width');
|
||||
});
|
||||
};
|
||||
|
||||
TinyLoader.setup(function (editor, onSuccess, onFailure) {
|
||||
var tinyApis = TinyApis(editor);
|
||||
|
||||
Pipeline.async({}, [
|
||||
sElementTest(tinyApis, editor, '<p>a</p>', 'p'),
|
||||
sParentTest(tinyApis, editor, '<div><p><em>a</em></p></div>', 'em')
|
||||
], onSuccess, onFailure);
|
||||
}, {
|
||||
inline: true
|
||||
}, success, failure);
|
||||
});
|
||||
@@ -0,0 +1,118 @@
|
||||
test('browser/core/LayoutTest', [
|
||||
'ephox/tinymce',
|
||||
'tinymce/inlite/core/Layout'
|
||||
], function (tinymce, Layout) {
|
||||
// TODO: Move this to atomic test when we can require parts of tinymce core using bolt
|
||||
|
||||
var rect = function (x, y, w, h) {
|
||||
return {x: x, y: y, w: w, h: h};
|
||||
};
|
||||
|
||||
var clientRect = function (x, y, w, h) {
|
||||
return {left: x, top: y, width: w, height: h, bottom: y + h, right: x + w};
|
||||
};
|
||||
|
||||
var assertLayout = function (expected, rects) {
|
||||
var result;
|
||||
|
||||
result = Layout.calc(
|
||||
rects.targetRect,
|
||||
rects.contentAreaRect,
|
||||
rects.panelRect
|
||||
);
|
||||
|
||||
assert.eq(expected, result);
|
||||
};
|
||||
|
||||
var testCalcPanelAtBottomLeft = function () {
|
||||
assertLayout({
|
||||
rect: rect(0, 10, 20, 10),
|
||||
position: 'bl-tl'
|
||||
}, {
|
||||
contentAreaRect: rect(0, 0, 100, 100),
|
||||
targetRect: rect(0, 0, 10, 10),
|
||||
panelRect: rect(0, 0, 20, 10)
|
||||
});
|
||||
};
|
||||
|
||||
var testCalcPanelAtBottomRight = function () {
|
||||
assertLayout({
|
||||
rect: rect(80, 10, 20, 10),
|
||||
position: 'br-tr'
|
||||
}, {
|
||||
contentAreaRect: rect(0, 0, 100, 100),
|
||||
targetRect: rect(90, 0, 10, 10),
|
||||
panelRect: rect(0, 0, 20, 10)
|
||||
});
|
||||
};
|
||||
|
||||
var testCalcPanelAtTopLeft = function () {
|
||||
assertLayout({
|
||||
rect: rect(0, 10, 20, 10),
|
||||
position: 'tl-bl'
|
||||
}, {
|
||||
contentAreaRect: rect(0, 0, 100, 100),
|
||||
targetRect: rect(0, 20, 10, 10),
|
||||
panelRect: rect(0, 0, 20, 10)
|
||||
});
|
||||
};
|
||||
|
||||
var testCalcPanelAtTopRight = function () {
|
||||
assertLayout({
|
||||
rect: rect(80, 10, 20, 10),
|
||||
position: 'tr-br'
|
||||
}, {
|
||||
contentAreaRect: rect(0, 0, 100, 100),
|
||||
targetRect: rect(90, 20, 10, 10),
|
||||
panelRect: rect(0, 0, 20, 10)
|
||||
});
|
||||
};
|
||||
|
||||
var testCalcPanelAtTopCenter = function () {
|
||||
assertLayout({
|
||||
rect: rect(35, 10, 20, 10),
|
||||
position: 'tc-bc'
|
||||
}, {
|
||||
contentAreaRect: rect(0, 0, 100, 100),
|
||||
targetRect: rect(40, 20, 10, 10),
|
||||
panelRect: rect(0, 0, 20, 10)
|
||||
});
|
||||
};
|
||||
|
||||
var testCalcPanelAtBottomCenter = function () {
|
||||
assertLayout({
|
||||
rect: rect(35, 10, 20, 10),
|
||||
position: 'bc-tc'
|
||||
}, {
|
||||
contentAreaRect: rect(0, 0, 100, 100),
|
||||
targetRect: rect(40, 0, 10, 10),
|
||||
panelRect: rect(0, 0, 20, 10)
|
||||
});
|
||||
};
|
||||
|
||||
var testUserConstrain = function () {
|
||||
var targetRect, contentAreaRect, panelRect, userConstrainedPanelRect, handler;
|
||||
|
||||
contentAreaRect = rect(0, 0, 100, 100);
|
||||
targetRect = rect(40, 0, 10, 10);
|
||||
panelRect = rect(0, 0, 20, 10);
|
||||
|
||||
handler = function (rects) {
|
||||
assert.eq(rects.elementRect, clientRect(40, 0, 10, 10));
|
||||
assert.eq(rects.contentAreaRect, clientRect(0, 0, 100, 100));
|
||||
assert.eq(rects.panelRect, clientRect(0, 0, 20, 10));
|
||||
return clientRect(1, 2, 3, 4);
|
||||
};
|
||||
|
||||
userConstrainedPanelRect = Layout.userConstrain(handler, targetRect, contentAreaRect, panelRect);
|
||||
assert.eq(userConstrainedPanelRect, rect(1, 2, 3, 4));
|
||||
};
|
||||
|
||||
testCalcPanelAtBottomLeft();
|
||||
testCalcPanelAtBottomRight();
|
||||
testCalcPanelAtTopLeft();
|
||||
testCalcPanelAtTopRight();
|
||||
testCalcPanelAtTopCenter();
|
||||
testCalcPanelAtBottomCenter();
|
||||
testUserConstrain();
|
||||
});
|
||||
@@ -0,0 +1,62 @@
|
||||
asynctest('browser/core/MeasureTest', [
|
||||
'ephox.mcagar.api.TinyLoader',
|
||||
'tinymce/inlite/core/Measure',
|
||||
'ephox.agar.api.Pipeline',
|
||||
'ephox.mcagar.api.TinyApis',
|
||||
'ephox.agar.api.Step',
|
||||
'ephox.agar.api.Chain',
|
||||
'ephox.agar.api.UiFinder',
|
||||
'ephox.agar.api.Assertions'
|
||||
], function (TinyLoader, Measure, Pipeline, TinyApis, Step, Chain, UiFinder, Assertions) {
|
||||
var success = arguments[arguments.length - 2];
|
||||
var failure = arguments[arguments.length - 1];
|
||||
|
||||
var containsXY = function (r, x, y) {
|
||||
return x >= r.x && x <= r.x + r.w && y >= r.y && y <= r.y + r.h;
|
||||
};
|
||||
|
||||
var contains = function (a, b) {
|
||||
return containsXY(a, b.x, b.y) && containsXY(a, b.x + b.w, b.y + b.h);
|
||||
};
|
||||
|
||||
var sAssertRect = function (editor, measure) {
|
||||
return Step.sync(function () {
|
||||
var elementRect = measure();
|
||||
var pageAreaRect = Measure.getPageAreaRect(editor);
|
||||
var contentAreaRect = Measure.getContentAreaRect(editor);
|
||||
|
||||
Assertions.assertEq('Rect is not in page area rect', contains(pageAreaRect, elementRect), true);
|
||||
Assertions.assertEq('Rect is not in content area rect', contains(contentAreaRect, elementRect), true);
|
||||
Assertions.assertEq('Rect should have width', elementRect.w > 0, true);
|
||||
Assertions.assertEq('Rect should have height', elementRect.h > 0, true);
|
||||
});
|
||||
};
|
||||
|
||||
var getElementRectFromSelector = function (editor, selector) {
|
||||
return function () {
|
||||
var elm = editor.dom.select(selector)[0];
|
||||
var rect = Measure.getElementRect(editor, elm);
|
||||
return rect;
|
||||
};
|
||||
};
|
||||
|
||||
var getSelectionRectFromSelector = function (editor) {
|
||||
return function () {
|
||||
var rect = Measure.getSelectionRect(editor);
|
||||
return rect;
|
||||
};
|
||||
};
|
||||
|
||||
TinyLoader.setup(function (editor, onSuccess, onFailure) {
|
||||
var tinyApis = TinyApis(editor);
|
||||
|
||||
Pipeline.async({}, [
|
||||
tinyApis.sSetContent('<p>a</p><div style="width: 50px; height: 300px">b</div><p>c</p>'),
|
||||
sAssertRect(editor, getElementRectFromSelector(editor, 'p:nth-child(1)')),
|
||||
tinyApis.sSetCursor([0, 0], 0),
|
||||
sAssertRect(editor, getSelectionRectFromSelector(editor))
|
||||
], onSuccess, onFailure);
|
||||
}, {
|
||||
inline: true
|
||||
}, success, failure);
|
||||
});
|
||||
@@ -0,0 +1,26 @@
|
||||
test('browser/core/PredicateIdTest', [
|
||||
'ephox/tinymce',
|
||||
'tinymce/inlite/core/PredicateId'
|
||||
], function (tinymce, PredicateId) {
|
||||
var testFromContextToolbars = function () {
|
||||
var isTrue = function () {
|
||||
return true;
|
||||
};
|
||||
|
||||
var isFalse = function () {
|
||||
return false;
|
||||
};
|
||||
|
||||
var predIds = PredicateId.fromContextToolbars([
|
||||
{toolbar: 'a b c', predicate: isTrue, id: 'a'},
|
||||
{toolbar: 'd e', predicate: isFalse, id: 'b'}
|
||||
]);
|
||||
|
||||
assert.eq([
|
||||
PredicateId.create('a', isTrue),
|
||||
PredicateId.create('b', isFalse)
|
||||
], predIds);
|
||||
};
|
||||
|
||||
testFromContextToolbars();
|
||||
});
|
||||
@@ -0,0 +1,76 @@
|
||||
asynctest('browser/core/SelectionMatcherTest', [
|
||||
'ephox.mcagar.api.TinyLoader',
|
||||
'ephox.mcagar.api.TinyApis',
|
||||
'ephox.agar.api.Step',
|
||||
'ephox.agar.api.Assertions',
|
||||
'tinymce/inlite/core/SelectionMatcher',
|
||||
'tinymce/inlite/core/PredicateId',
|
||||
'ephox.agar.api.GeneralSteps',
|
||||
'ephox.agar.api.Pipeline'
|
||||
], function (TinyLoader, TinyApis, Step, Assertions, SelectionMatcher, PredicateId, GeneralSteps, Pipeline) {
|
||||
var success = arguments[arguments.length - 2];
|
||||
var failure = arguments[arguments.length - 1];
|
||||
|
||||
var assertResult = function (expectedResultState, result) {
|
||||
Assertions.assertEq('Should not be null', result !== null, expectedResultState);
|
||||
|
||||
if (expectedResultState === true) {
|
||||
Assertions.assertEq('Should be matching a', result.id, 'a');
|
||||
Assertions.assertEq('Should be have width', result.rect.w > 0, true);
|
||||
}
|
||||
};
|
||||
|
||||
var sTextSelectionTest = function (tinyApis, editor, inputHtml, spath, soffset, fpath, foffset, expectedResultState) {
|
||||
var sAssertTextSelectionResult = Step.sync(function () {
|
||||
var result = SelectionMatcher.textSelection('a')(editor);
|
||||
assertResult(expectedResultState, result);
|
||||
});
|
||||
|
||||
return GeneralSteps.sequence([
|
||||
tinyApis.sSetContent(inputHtml),
|
||||
tinyApis.sSetSelection(spath, soffset, fpath, foffset),
|
||||
sAssertTextSelectionResult
|
||||
]);
|
||||
};
|
||||
|
||||
var sTextSelectionTests = function (tinyApis, editor) {
|
||||
return GeneralSteps.sequence([
|
||||
sTextSelectionTest(tinyApis, editor, '<p>a</p>', [0], 0, [0], 1, true),
|
||||
sTextSelectionTest(tinyApis, editor, '<p>a</p>', [0], 0, [0], 0, false)
|
||||
]);
|
||||
};
|
||||
|
||||
var sEmptyTextBlockTest = function (tinyApis, editor, inputHtml, spath, soffset, fpath, foffset, expectedResultState) {
|
||||
var sAssertTextSelectionResult = Step.sync(function () {
|
||||
var elements = editor.dom.getParents(editor.selection.getStart());
|
||||
var result = SelectionMatcher.emptyTextBlock(elements, 'a')(editor);
|
||||
assertResult(expectedResultState, result);
|
||||
});
|
||||
|
||||
return GeneralSteps.sequence([
|
||||
tinyApis.sSetContent(inputHtml),
|
||||
tinyApis.sSetSelection(spath, soffset, fpath, foffset),
|
||||
sAssertTextSelectionResult
|
||||
]);
|
||||
};
|
||||
|
||||
var sEmptyTextBlockTests = function (tinyApis, editor) {
|
||||
return GeneralSteps.sequence([
|
||||
sEmptyTextBlockTest(tinyApis, editor, '<p>a</p>', [0], 0, [0], 0, false),
|
||||
sEmptyTextBlockTest(tinyApis, editor, '<p>a</p>', [0], 0, [0], 1, false),
|
||||
sEmptyTextBlockTest(tinyApis, editor, '<p><br></p>', [0], 0, [0], 0, true),
|
||||
sEmptyTextBlockTest(tinyApis, editor, '<p><em><br></em></p>', [0, 0], 0, [0, 0], 0, true)
|
||||
]);
|
||||
};
|
||||
|
||||
TinyLoader.setup(function (editor, onSuccess, onFailure) {
|
||||
var tinyApis = TinyApis(editor);
|
||||
|
||||
Pipeline.async({}, [
|
||||
sTextSelectionTests(tinyApis, editor),
|
||||
sEmptyTextBlockTests(tinyApis, editor)
|
||||
], onSuccess, onFailure);
|
||||
}, {
|
||||
inline: true
|
||||
}, success, failure);
|
||||
});
|
||||
@@ -0,0 +1,41 @@
|
||||
asynctest('atomic/core/ConvertTest', [
|
||||
'ephox/tinymce',
|
||||
'tinymce/inlite/file/Conversions',
|
||||
'ephox.agar.api.Step',
|
||||
'ephox.agar.api.Pipeline',
|
||||
'ephox.agar.api.Assertions'
|
||||
], function (tinymce, Conversions, Step, Pipeline, Assertions) {
|
||||
var success = arguments[arguments.length - 2];
|
||||
var failure = arguments[arguments.length - 1];
|
||||
|
||||
var base64ToBlob = function (base64, type) {
|
||||
var buff = atob(base64);
|
||||
var bytes = new Uint8Array(buff.length);
|
||||
|
||||
for (var i = 0; i < bytes.length; i++) {
|
||||
bytes[i] = buff.charCodeAt(i);
|
||||
}
|
||||
|
||||
return new Blob([bytes], {type: type});
|
||||
};
|
||||
|
||||
var sBlobToBase64 = function () {
|
||||
return Step.async(function (next) {
|
||||
var base64 = 'R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';
|
||||
var blob = base64ToBlob(base64, 'image/gif');
|
||||
|
||||
Conversions.blobToBase64(blob).then(function (convertedBase64) {
|
||||
Assertions.assertEq('Not the correct base64', base64, convertedBase64);
|
||||
next();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
Pipeline.async({}, [
|
||||
sBlobToBase64()
|
||||
], function () {
|
||||
success();
|
||||
}, function () {
|
||||
failure();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* SelectionMatcher.js
|
||||
*
|
||||
* Released under LGPL License.
|
||||
* Copyright (c) 1999-2016 Ephox Corp. All rights reserved
|
||||
*
|
||||
* License: http://www.tinymce.com/license
|
||||
* Contributing: http://www.tinymce.com/contributing
|
||||
*/
|
||||
|
||||
define('tinymce/inlite/core/SelectionMatcher', [
|
||||
'tinymce/inlite/core/Matcher',
|
||||
'tinymce/inlite/core/Measure'
|
||||
], function (Matcher, Measure) {
|
||||
// textSelection :: String -> (Editor -> Matcher.result | Null)
|
||||
var textSelection = function (id) {
|
||||
return function (editor) {
|
||||
if (!editor.selection.isCollapsed()) {
|
||||
return Matcher.result(id, Measure.getSelectionRect(editor));
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
};
|
||||
|
||||
// emptyTextBlock :: [Elements], String -> (Editor -> Matcher.result | Null)
|
||||
var emptyTextBlock = function (elements, id) {
|
||||
return function (editor) {
|
||||
var i, textBlockElementsMap = editor.schema.getTextBlockElements();
|
||||
|
||||
for (i = 0; i < elements.length; i++) {
|
||||
if (elements[i].nodeName === 'TABLE') {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < elements.length; i++) {
|
||||
if (elements[i].nodeName in textBlockElementsMap) {
|
||||
if (editor.dom.isEmpty(elements[i])) {
|
||||
return Matcher.result(id, Measure.getSelectionRect(editor));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
};
|
||||
|
||||
return {
|
||||
textSelection: textSelection,
|
||||
emptyTextBlock: emptyTextBlock
|
||||
};
|
||||
});
|
||||
1
plugins/tinymce/themes/inlite/theme.min.js
vendored
Normal file
1
plugins/tinymce/themes/inlite/theme.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user