init
This commit is contained in:
15
public/tinymce/src/plugins/visualchars/demo/html/demo.html
Normal file
15
public/tinymce/src/plugins/visualchars/demo/html/demo.html
Normal file
@@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>visualchars Plugin Demo Page</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h2>Plugin: visualchars Demo Page</h2>
|
||||
<div id="ephox-ui">
|
||||
<textarea name="" id="" cols="30" rows="10" class="tinymce"></textarea>
|
||||
</div>
|
||||
<script src="../../../../../js/tinymce/tinymce.js"></script>
|
||||
<script src="../../../../../scratch/demos/plugins/visualchars/demo.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
22
public/tinymce/src/plugins/visualchars/demo/ts/demo/Demo.ts
Normal file
22
public/tinymce/src/plugins/visualchars/demo/ts/demo/Demo.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
declare let tinymce: any;
|
||||
|
||||
tinymce.init({
|
||||
selector: 'textarea.tinymce',
|
||||
plugins: 'visualchars code',
|
||||
toolbar: 'visualchars code',
|
||||
visualchars_default_state: true,
|
||||
skin_url: '../../../../../js/tinymce/skins/lightgray',
|
||||
height: 600
|
||||
});
|
||||
|
||||
export {};
|
||||
27
public/tinymce/src/plugins/visualchars/main/ts/Plugin.ts
Normal file
27
public/tinymce/src/plugins/visualchars/main/ts/Plugin.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
|
||||
import { Cell } from '@ephox/katamari';
|
||||
import PluginManager from 'tinymce/core/api/PluginManager';
|
||||
import Api from './api/Api';
|
||||
import Commands from './api/Commands';
|
||||
import Keyboard from './core/Keyboard';
|
||||
import Bindings from './core/Bindings';
|
||||
import * as Buttons from './ui/Buttons';
|
||||
|
||||
PluginManager.add('visualchars', function (editor) {
|
||||
const toggleState = Cell(false);
|
||||
|
||||
Commands.register(editor, toggleState);
|
||||
Buttons.register(editor);
|
||||
Keyboard.setup(editor, toggleState);
|
||||
Bindings.setup(editor, toggleState);
|
||||
|
||||
return Api.get(toggleState);
|
||||
});
|
||||
|
||||
export default function () {}
|
||||
20
public/tinymce/src/plugins/visualchars/main/ts/api/Api.ts
Normal file
20
public/tinymce/src/plugins/visualchars/main/ts/api/Api.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
|
||||
const get = function (toggleState) {
|
||||
const isEnabled = function () {
|
||||
return toggleState.get();
|
||||
};
|
||||
|
||||
return {
|
||||
isEnabled
|
||||
};
|
||||
};
|
||||
|
||||
export default {
|
||||
get
|
||||
};
|
||||
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
|
||||
import Actions from '../core/Actions';
|
||||
|
||||
const register = function (editor, toggleState) {
|
||||
editor.addCommand('mceVisualChars', function () {
|
||||
Actions.toggleVisualChars(editor, toggleState);
|
||||
});
|
||||
};
|
||||
|
||||
export default {
|
||||
register
|
||||
};
|
||||
14
public/tinymce/src/plugins/visualchars/main/ts/api/Events.ts
Normal file
14
public/tinymce/src/plugins/visualchars/main/ts/api/Events.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
|
||||
const fireVisualChars = function (editor, state) {
|
||||
return editor.fire('VisualChars', { state });
|
||||
};
|
||||
|
||||
export default {
|
||||
fireVisualChars
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
|
||||
import { Editor } from 'tinymce/core/api/Editor';
|
||||
|
||||
const isEnabledByDefault = (editor: Editor) => {
|
||||
return editor.getParam('visualchars_default_state', false);
|
||||
};
|
||||
|
||||
export default {
|
||||
isEnabledByDefault
|
||||
};
|
||||
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
|
||||
import Events from '../api/Events';
|
||||
import VisualChars from './VisualChars';
|
||||
|
||||
const toggleVisualChars = function (editor, toggleState) {
|
||||
const body = editor.getBody();
|
||||
const selection = editor.selection;
|
||||
let bookmark;
|
||||
|
||||
toggleState.set(!toggleState.get());
|
||||
Events.fireVisualChars(editor, toggleState.get());
|
||||
|
||||
bookmark = selection.getBookmark();
|
||||
|
||||
if (toggleState.get() === true) {
|
||||
VisualChars.show(editor, body);
|
||||
} else {
|
||||
VisualChars.hide(editor, body);
|
||||
}
|
||||
|
||||
selection.moveToBookmark(bookmark);
|
||||
};
|
||||
|
||||
export default {
|
||||
toggleVisualChars
|
||||
};
|
||||
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
|
||||
import { Editor } from 'tinymce/core/api/Editor';
|
||||
import Settings from '../api/Settings';
|
||||
import Actions from './Actions';
|
||||
|
||||
const setup = (editor: Editor, toggleState) => {
|
||||
editor.on('init', () => {
|
||||
// should be false when enabled, so toggling will change it to true
|
||||
const valueForToggling = !Settings.isEnabledByDefault(editor);
|
||||
toggleState.set(valueForToggling);
|
||||
Actions.toggleVisualChars(editor, toggleState);
|
||||
});
|
||||
};
|
||||
|
||||
export default {
|
||||
setup
|
||||
};
|
||||
43
public/tinymce/src/plugins/visualchars/main/ts/core/Data.ts
Normal file
43
public/tinymce/src/plugins/visualchars/main/ts/core/Data.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
|
||||
const charMap = {
|
||||
'\u00a0': 'nbsp',
|
||||
'\u00ad': 'shy'
|
||||
};
|
||||
|
||||
const charMapToRegExp = function (charMap, global?) {
|
||||
let key, regExp = '';
|
||||
|
||||
for (key in charMap) {
|
||||
regExp += key;
|
||||
}
|
||||
|
||||
return new RegExp('[' + regExp + ']', global ? 'g' : '');
|
||||
};
|
||||
|
||||
const charMapToSelector = function (charMap) {
|
||||
let key, selector = '';
|
||||
|
||||
for (key in charMap) {
|
||||
if (selector) {
|
||||
selector += ',';
|
||||
}
|
||||
selector += 'span.mce-' + charMap[key];
|
||||
}
|
||||
|
||||
return selector;
|
||||
};
|
||||
|
||||
export default {
|
||||
charMap,
|
||||
regExp: charMapToRegExp(charMap),
|
||||
regExpGlobal: charMapToRegExp(charMap, true),
|
||||
selector: charMapToSelector(charMap),
|
||||
charMapToRegExp,
|
||||
charMapToSelector
|
||||
};
|
||||
16
public/tinymce/src/plugins/visualchars/main/ts/core/Html.ts
Normal file
16
public/tinymce/src/plugins/visualchars/main/ts/core/Html.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
|
||||
import Data from './Data';
|
||||
|
||||
const wrapCharWithSpan = function (value) {
|
||||
return '<span data-mce-bogus="1" class="mce-' + Data.charMap[value] + '">' + value + '</span>';
|
||||
};
|
||||
|
||||
export default {
|
||||
wrapCharWithSpan
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
|
||||
import Delay from 'tinymce/core/api/util/Delay';
|
||||
import VisualChars from './VisualChars';
|
||||
|
||||
const setup = function (editor, toggleState) {
|
||||
const debouncedToggle = Delay.debounce(function () {
|
||||
VisualChars.toggle(editor);
|
||||
}, 300);
|
||||
|
||||
if (editor.settings.forced_root_block !== false) {
|
||||
editor.on('keydown', function (e) {
|
||||
if (toggleState.get() === true) {
|
||||
e.keyCode === 13 ? VisualChars.toggle(editor) : debouncedToggle();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export default {
|
||||
setup
|
||||
};
|
||||
52
public/tinymce/src/plugins/visualchars/main/ts/core/Nodes.ts
Normal file
52
public/tinymce/src/plugins/visualchars/main/ts/core/Nodes.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
|
||||
import { Arr } from '@ephox/katamari';
|
||||
import { Element, Node } from '@ephox/sugar';
|
||||
import Data from './Data';
|
||||
import Html from './Html';
|
||||
|
||||
const isMatch = function (n) {
|
||||
return Node.isText(n) &&
|
||||
Node.value(n) !== undefined &&
|
||||
Data.regExp.test(Node.value(n));
|
||||
};
|
||||
|
||||
// inlined sugars PredicateFilter.descendants for file size
|
||||
const filterDescendants = function (scope, predicate) {
|
||||
let result = [];
|
||||
const dom = scope.dom();
|
||||
const children = Arr.map(dom.childNodes, Element.fromDom);
|
||||
|
||||
Arr.each(children, function (x) {
|
||||
if (predicate(x)) {
|
||||
result = result.concat([ x ]);
|
||||
}
|
||||
result = result.concat(filterDescendants(x, predicate));
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
const findParentElm = function (elm, rootElm) {
|
||||
while (elm.parentNode) {
|
||||
if (elm.parentNode === rootElm) {
|
||||
return elm;
|
||||
}
|
||||
elm = elm.parentNode;
|
||||
}
|
||||
};
|
||||
|
||||
const replaceWithSpans = function (html) {
|
||||
return html.replace(Data.regExpGlobal, Html.wrapCharWithSpan);
|
||||
};
|
||||
|
||||
export default {
|
||||
isMatch,
|
||||
filterDescendants,
|
||||
findParentElm,
|
||||
replaceWithSpans
|
||||
};
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
|
||||
import Data from './Data';
|
||||
import Nodes from './Nodes';
|
||||
import { Arr } from '@ephox/katamari';
|
||||
import { Element, Node } from '@ephox/sugar';
|
||||
|
||||
const show = function (editor, rootElm) {
|
||||
let node, div;
|
||||
const nodeList = Nodes.filterDescendants(Element.fromDom(rootElm), Nodes.isMatch);
|
||||
|
||||
Arr.each(nodeList, function (n) {
|
||||
const withSpans = Nodes.replaceWithSpans(Node.value(n));
|
||||
|
||||
div = editor.dom.create('div', null, withSpans);
|
||||
while ((node = div.lastChild)) {
|
||||
editor.dom.insertAfter(node, n.dom());
|
||||
}
|
||||
|
||||
editor.dom.remove(n.dom());
|
||||
});
|
||||
};
|
||||
|
||||
const hide = function (editor, body) {
|
||||
const nodeList = editor.dom.select(Data.selector, body);
|
||||
|
||||
Arr.each(nodeList, function (node) {
|
||||
editor.dom.remove(node, 1);
|
||||
});
|
||||
};
|
||||
|
||||
const toggle = function (editor) {
|
||||
const body = editor.getBody();
|
||||
const bookmark = editor.selection.getBookmark();
|
||||
let parentNode = Nodes.findParentElm(editor.selection.getNode(), body);
|
||||
|
||||
// if user does select all the parentNode will be undefined
|
||||
parentNode = parentNode !== undefined ? parentNode : body;
|
||||
|
||||
hide(editor, parentNode);
|
||||
show(editor, parentNode);
|
||||
|
||||
editor.selection.moveToBookmark(bookmark);
|
||||
};
|
||||
|
||||
export default {
|
||||
show,
|
||||
hide,
|
||||
toggle
|
||||
};
|
||||
38
public/tinymce/src/plugins/visualchars/main/ts/ui/Buttons.ts
Normal file
38
public/tinymce/src/plugins/visualchars/main/ts/ui/Buttons.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
|
||||
* Licensed under the LGPL or a commercial license.
|
||||
* For LGPL see License.txt in the project root for license information.
|
||||
* For commercial licenses see https://www.tiny.cloud/
|
||||
*/
|
||||
|
||||
const toggleActiveState = function (editor) {
|
||||
return function (e) {
|
||||
const ctrl = e.control;
|
||||
|
||||
editor.on('VisualChars', function (e) {
|
||||
ctrl.active(e.state);
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
const register = function (editor) {
|
||||
editor.addButton('visualchars', {
|
||||
active: false,
|
||||
title: 'Show invisible characters',
|
||||
cmd: 'mceVisualChars',
|
||||
onPostRender: toggleActiveState(editor)
|
||||
});
|
||||
|
||||
editor.addMenuItem('visualchars', {
|
||||
text: 'Show invisible characters',
|
||||
cmd: 'mceVisualChars',
|
||||
onPostRender: toggleActiveState(editor),
|
||||
selectable: true,
|
||||
context: 'view',
|
||||
prependToContext: true
|
||||
});
|
||||
};
|
||||
|
||||
export {
|
||||
register
|
||||
};
|
||||
@@ -0,0 +1,23 @@
|
||||
import { RawAssertions } from '@ephox/agar';
|
||||
import Data from 'tinymce/plugins/visualchars/core/Data';
|
||||
import { UnitTest } from '@ephox/bedrock';
|
||||
|
||||
UnitTest.test('atomic.tinymce.plugins.visualchars.DataTest', function () {
|
||||
RawAssertions.assertEq(
|
||||
'should return correct selector',
|
||||
'span.mce-a,span.mce-b',
|
||||
Data.charMapToSelector({ a: 'a', b: 'b' })
|
||||
);
|
||||
|
||||
RawAssertions.assertEq(
|
||||
'should return correct regexp',
|
||||
'/[ab]/',
|
||||
Data.charMapToRegExp({ a: 'a', b: 'b' }).toString()
|
||||
);
|
||||
|
||||
RawAssertions.assertEq(
|
||||
'should return correct global regexp',
|
||||
'/[ab]/g',
|
||||
Data.charMapToRegExp({ a: 'a', b: 'b' }, true).toString()
|
||||
);
|
||||
});
|
||||
@@ -0,0 +1,20 @@
|
||||
import { RawAssertions } from '@ephox/agar';
|
||||
import Html from 'tinymce/plugins/visualchars/core/Html';
|
||||
import { UnitTest } from '@ephox/bedrock';
|
||||
|
||||
UnitTest.test('atomic.tinymce.plugins.visualchars.HtmlTest', function () {
|
||||
const nbsp = '\u00a0';
|
||||
const shy = '\u00AD';
|
||||
|
||||
RawAssertions.assertEq(
|
||||
'should return correct span',
|
||||
'<span data-mce-bogus="1" class="mce-nbsp">' + nbsp + '</span>',
|
||||
Html.wrapCharWithSpan(nbsp)
|
||||
);
|
||||
|
||||
RawAssertions.assertEq(
|
||||
'should return correct span',
|
||||
'<span data-mce-bogus="1" class="mce-shy">' + shy + '</span>',
|
||||
Html.wrapCharWithSpan(shy)
|
||||
);
|
||||
});
|
||||
@@ -0,0 +1,50 @@
|
||||
import { Assertions } from '@ephox/agar';
|
||||
import { Element } from '@ephox/sugar';
|
||||
import Nodes from 'tinymce/plugins/visualchars/core/Nodes';
|
||||
import { UnitTest } from '@ephox/bedrock';
|
||||
import { document } from '@ephox/dom-globals';
|
||||
|
||||
UnitTest.test('atomic.tinymce.plugins.visualchars.NodesTest', function () {
|
||||
const nbsp = '\u00a0';
|
||||
const shy = '\u00AD';
|
||||
|
||||
const testReplaceWithSpans = function () {
|
||||
Assertions.assertHtml(
|
||||
'should return span around shy and nbsp',
|
||||
'a<span data-mce-bogus="1" class="mce-nbsp">\u00a0</span>b<span data-mce-bogus="1" class="mce-shy">\u00AD</span>',
|
||||
Nodes.replaceWithSpans('a' + nbsp + 'b' + shy)
|
||||
);
|
||||
};
|
||||
|
||||
const testFilterDescendants = function () {
|
||||
const div = document.createElement('div');
|
||||
div.innerHTML = '<p>a</p>' +
|
||||
'<p>b' + nbsp + '</p>' +
|
||||
'<p>c</p>' +
|
||||
'<p>d' + shy + '</p>';
|
||||
|
||||
Assertions.assertEq(
|
||||
'should return list with nodes with shy or nbsp in it',
|
||||
2,
|
||||
Nodes.filterDescendants(Element.fromDom(div), Nodes.isMatch).length
|
||||
);
|
||||
};
|
||||
|
||||
const testFilterDescendants2 = function () {
|
||||
const div = document.createElement('div');
|
||||
div.innerHTML = '<p>a' + nbsp + '</p>' +
|
||||
'<p>b' + nbsp + '</p>' +
|
||||
'<p>c' + nbsp + '</p>' +
|
||||
'<p>d' + shy + '</p>';
|
||||
|
||||
Assertions.assertEq(
|
||||
'should return list with nodes with shy or nbsp in it',
|
||||
4,
|
||||
Nodes.filterDescendants(Element.fromDom(div), Nodes.isMatch).length
|
||||
);
|
||||
};
|
||||
|
||||
testReplaceWithSpans();
|
||||
testFilterDescendants();
|
||||
testFilterDescendants2();
|
||||
});
|
||||
@@ -0,0 +1,35 @@
|
||||
import { Keyboard, Keys, Pipeline, Waiter } from '@ephox/agar';
|
||||
import { UnitTest } from '@ephox/bedrock';
|
||||
import { TinyApis, TinyLoader, TinyUi } from '@ephox/mcagar';
|
||||
import { Element } from '@ephox/sugar';
|
||||
|
||||
import Plugin from 'tinymce/plugins/visualchars/Plugin';
|
||||
import Theme from 'tinymce/themes/modern/Theme';
|
||||
|
||||
import { sAssertNbspStruct, sAssertSpanStruct } from '../module/test/Utils';
|
||||
|
||||
UnitTest.asynctest('browser.tinymce.plugins.visualchars.DefaultStateTest', (success, failure) => {
|
||||
Plugin();
|
||||
Theme();
|
||||
|
||||
TinyLoader.setup(function (editor, onSuccess, onFailure) {
|
||||
const tinyUi = TinyUi(editor);
|
||||
const tinyApis = TinyApis(editor);
|
||||
|
||||
Pipeline.async({}, [
|
||||
tinyApis.sSetContent('<p>a b</p>'),
|
||||
// Need to trigger a keydown event to get the visual chars to show after calling set content
|
||||
Keyboard.sKeydown(Element.fromDom(editor.getDoc()), Keys.space(), { }),
|
||||
Waiter.sTryUntil('Wait for visual chars to show', tinyApis.sAssertContentStructure(sAssertSpanStruct), 50, 1000),
|
||||
tinyUi.sClickOnToolbar('click on visualchars button', 'div[aria-label="Show invisible characters"] > button'),
|
||||
tinyApis.sAssertContentStructure(sAssertNbspStruct),
|
||||
tinyUi.sClickOnToolbar('click on visualchars button', 'div[aria-label="Show invisible characters"] > button'),
|
||||
tinyApis.sAssertContentStructure(sAssertSpanStruct)
|
||||
], onSuccess, onFailure);
|
||||
}, {
|
||||
plugins: 'visualchars',
|
||||
toolbar: 'visualchars',
|
||||
skin_url: '/project/js/tinymce/skins/lightgray',
|
||||
visualchars_default_state: true
|
||||
}, success, failure);
|
||||
});
|
||||
@@ -0,0 +1,35 @@
|
||||
import { Assertions, Pipeline } from '@ephox/agar';
|
||||
import { UnitTest } from '@ephox/bedrock';
|
||||
import { TinyApis, TinyLoader, TinyUi } from '@ephox/mcagar';
|
||||
|
||||
import Plugin from 'tinymce/plugins/visualchars/Plugin';
|
||||
import Theme from 'tinymce/themes/modern/Theme';
|
||||
|
||||
import { sAssertNbspStruct, sAssertSpanStruct } from '../module/test/Utils';
|
||||
|
||||
UnitTest.asynctest('browser.tinymce.plugins.visualchars.PluginTest', (success, failure) => {
|
||||
Plugin();
|
||||
Theme();
|
||||
|
||||
TinyLoader.setup(function (editor, onSuccess, onFailure) {
|
||||
const tinyUi = TinyUi(editor);
|
||||
const tinyApis = TinyApis(editor);
|
||||
|
||||
Pipeline.async({}, [
|
||||
tinyApis.sSetContent('<p>a b</p>'),
|
||||
Assertions.sAssertEq('assert equal', 0, editor.dom.select('span').length),
|
||||
tinyUi.sClickOnToolbar('click on visualchars button', 'div[aria-label="Show invisible characters"] > button'),
|
||||
tinyApis.sAssertContentStructure(sAssertSpanStruct),
|
||||
tinyUi.sClickOnToolbar('click on visualchars button', 'div[aria-label="Show invisible characters"] > button'),
|
||||
tinyApis.sAssertContentStructure(sAssertNbspStruct),
|
||||
tinyUi.sClickOnToolbar('click on visualchars button', 'div[aria-label="Show invisible characters"] > button'),
|
||||
tinyApis.sAssertContentStructure(sAssertSpanStruct),
|
||||
tinyUi.sClickOnToolbar('click on visualchars button', 'div[aria-label="Show invisible characters"] > button'),
|
||||
tinyApis.sAssertContentStructure(sAssertNbspStruct)
|
||||
], onSuccess, onFailure);
|
||||
}, {
|
||||
plugins: 'visualchars',
|
||||
toolbar: 'visualchars',
|
||||
skin_url: '/project/js/tinymce/skins/lightgray'
|
||||
}, success, failure);
|
||||
});
|
||||
@@ -0,0 +1,36 @@
|
||||
import { ApproxStructure } from '@ephox/agar';
|
||||
|
||||
const sAssertSpanStruct = ApproxStructure.build(function (s, str) {
|
||||
return s.element('body', {
|
||||
children: [
|
||||
s.element('p', {
|
||||
children: [
|
||||
s.text(str.is('a')),
|
||||
s.element('span', {}),
|
||||
s.element('span', {}),
|
||||
s.text(str.is('b'))
|
||||
]
|
||||
})
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
const sAssertNbspStruct = ApproxStructure.build(function (s, str) {
|
||||
return s.element('body', {
|
||||
children: [
|
||||
s.element('p', {
|
||||
children: [
|
||||
s.text(str.is('a')),
|
||||
s.text(str.is('\u00a0')),
|
||||
s.text(str.is('\u00a0')),
|
||||
s.text(str.is('b'))
|
||||
]
|
||||
})
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
export {
|
||||
sAssertNbspStruct,
|
||||
sAssertSpanStruct
|
||||
};
|
||||
Reference in New Issue
Block a user