init
This commit is contained in:
23
public/tinymce/src/plugins/noneditable/demo/html/demo.html
Normal file
23
public/tinymce/src/plugins/noneditable/demo/html/demo.html
Normal file
@@ -0,0 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Plugin: noneditable Demo Page</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h2>Plugin: noneditable Demo Page</h2>
|
||||
<div id="ephox-ui">
|
||||
<button class="clicky">clicky</button>
|
||||
|
||||
<button class="clicky2">clicky2</button>
|
||||
<button class="boldy">boldy</button>
|
||||
<div style="height: 200px"></div>
|
||||
<div class="tinymce"><div contenteditable="false">
|
||||
CEF DIV
|
||||
</div></div>
|
||||
<textarea class="tinymce"></textarea>
|
||||
</div>
|
||||
<script src="../../../../../js/tinymce/tinymce.js"></script>
|
||||
<script src="../../../../../scratch/demos/plugins/noneditable/demo.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
44
public/tinymce/src/plugins/noneditable/demo/ts/demo/Demo.ts
Normal file
44
public/tinymce/src/plugins/noneditable/demo/ts/demo/Demo.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Demo.js
|
||||
*
|
||||
* Released under LGPL License.
|
||||
* Copyright (c) 1999-2017 Ephox Corp. All rights reserved
|
||||
*
|
||||
* License: http://www.tinymce.com/license
|
||||
* Contributing: http://www.tinymce.com/contributing
|
||||
*/
|
||||
|
||||
import { document } from '@ephox/dom-globals';
|
||||
|
||||
declare let tinymce: any;
|
||||
|
||||
const button = document.querySelector('button.clicky');
|
||||
button.addEventListener('click', function () {
|
||||
tinymce.activeEditor.insertContent(content);
|
||||
});
|
||||
const content = '<span class="mceNonEditable">[NONEDITABLE]</span>';
|
||||
const button2 = document.querySelector('button.boldy');
|
||||
button2.addEventListener('click', function () {
|
||||
tinymce.activeEditor.execCommand('bold');
|
||||
});
|
||||
|
||||
tinymce.init({
|
||||
selector: 'div.tinymce',
|
||||
theme: 'modern',
|
||||
inline: true,
|
||||
skin_url: '../../../../../js/tinymce/skins/lightgray',
|
||||
plugins: 'noneditable code',
|
||||
toolbar: 'code',
|
||||
height: 600
|
||||
});
|
||||
|
||||
tinymce.init({
|
||||
selector: 'textarea.tinymce',
|
||||
theme: 'modern',
|
||||
skin_url: '../../../../../js/tinymce/skins/lightgray',
|
||||
plugins: 'noneditable code',
|
||||
toolbar: 'code',
|
||||
height: 600
|
||||
});
|
||||
|
||||
export {};
|
||||
15
public/tinymce/src/plugins/noneditable/main/ts/Plugin.ts
Normal file
15
public/tinymce/src/plugins/noneditable/main/ts/Plugin.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* 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 PluginManager from 'tinymce/core/api/PluginManager';
|
||||
import FilterContent from './core/FilterContent';
|
||||
|
||||
PluginManager.add('noneditable', function (editor) {
|
||||
FilterContent.setup(editor);
|
||||
});
|
||||
|
||||
export default function () { }
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* 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 getNonEditableClass = function (editor) {
|
||||
return editor.getParam('noneditable_noneditable_class', 'mceNonEditable');
|
||||
};
|
||||
|
||||
const getEditableClass = function (editor) {
|
||||
return editor.getParam('noneditable_editable_class', 'mceEditable');
|
||||
};
|
||||
|
||||
const getNonEditableRegExps = function (editor) {
|
||||
const nonEditableRegExps = editor.getParam('noneditable_regexp', []);
|
||||
|
||||
if (nonEditableRegExps && nonEditableRegExps.constructor === RegExp) {
|
||||
return [nonEditableRegExps];
|
||||
} else {
|
||||
return nonEditableRegExps;
|
||||
}
|
||||
};
|
||||
|
||||
export default {
|
||||
getNonEditableClass,
|
||||
getEditableClass,
|
||||
getNonEditableRegExps
|
||||
};
|
||||
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* 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 Tools from 'tinymce/core/api/util/Tools';
|
||||
import Settings from '../api/Settings';
|
||||
|
||||
const hasClass = function (checkClassName) {
|
||||
return function (node) {
|
||||
return (' ' + node.attr('class') + ' ').indexOf(checkClassName) !== -1;
|
||||
};
|
||||
};
|
||||
|
||||
const replaceMatchWithSpan = function (editor, content, cls) {
|
||||
return function (match) {
|
||||
const args = arguments, index = args[args.length - 2];
|
||||
const prevChar = index > 0 ? content.charAt(index - 1) : '';
|
||||
|
||||
// Is value inside an attribute then don't replace
|
||||
if (prevChar === '"') {
|
||||
return match;
|
||||
}
|
||||
|
||||
// Is value inside a contentEditable='false' tag
|
||||
if (prevChar === '>') {
|
||||
const findStartTagIndex = content.lastIndexOf('<', index);
|
||||
if (findStartTagIndex !== -1) {
|
||||
const tagHtml = content.substring(findStartTagIndex, index);
|
||||
if (tagHtml.indexOf('contenteditable="false"') !== -1) {
|
||||
return match;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
'<span class="' + cls + '" data-mce-content="' + editor.dom.encode(args[0]) + '">' +
|
||||
editor.dom.encode(typeof args[1] === 'string' ? args[1] : args[0]) + '</span>'
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
const convertRegExpsToNonEditable = function (editor, nonEditableRegExps, e) {
|
||||
let i = nonEditableRegExps.length, content = e.content;
|
||||
|
||||
// Don't replace the variables when raw is used for example on undo/redo
|
||||
if (e.format === 'raw') {
|
||||
return;
|
||||
}
|
||||
|
||||
while (i--) {
|
||||
content = content.replace(nonEditableRegExps[i], replaceMatchWithSpan(editor, content, Settings.getNonEditableClass(editor)));
|
||||
}
|
||||
|
||||
e.content = content;
|
||||
};
|
||||
|
||||
const setup = function (editor) {
|
||||
let editClass, nonEditClass;
|
||||
const contentEditableAttrName = 'contenteditable';
|
||||
|
||||
editClass = ' ' + Tools.trim(Settings.getEditableClass(editor)) + ' ';
|
||||
nonEditClass = ' ' + Tools.trim(Settings.getNonEditableClass(editor)) + ' ';
|
||||
|
||||
const hasEditClass = hasClass(editClass);
|
||||
const hasNonEditClass = hasClass(nonEditClass);
|
||||
const nonEditableRegExps = Settings.getNonEditableRegExps(editor);
|
||||
|
||||
editor.on('PreInit', function () {
|
||||
if (nonEditableRegExps.length > 0) {
|
||||
editor.on('BeforeSetContent', function (e) {
|
||||
convertRegExpsToNonEditable(editor, nonEditableRegExps, e);
|
||||
});
|
||||
}
|
||||
|
||||
editor.parser.addAttributeFilter('class', function (nodes) {
|
||||
let i = nodes.length, node;
|
||||
|
||||
while (i--) {
|
||||
node = nodes[i];
|
||||
|
||||
if (hasEditClass(node)) {
|
||||
node.attr(contentEditableAttrName, 'true');
|
||||
} else if (hasNonEditClass(node)) {
|
||||
node.attr(contentEditableAttrName, 'false');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
editor.serializer.addAttributeFilter(contentEditableAttrName, function (nodes) {
|
||||
let i = nodes.length, node;
|
||||
|
||||
while (i--) {
|
||||
node = nodes[i];
|
||||
if (!hasEditClass(node) && !hasNonEditClass(node)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nonEditableRegExps.length > 0 && node.attr('data-mce-content')) {
|
||||
node.name = '#text';
|
||||
node.type = 3;
|
||||
node.raw = true;
|
||||
node.value = node.attr('data-mce-content');
|
||||
} else {
|
||||
node.attr(contentEditableAttrName, null);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export default {
|
||||
setup
|
||||
};
|
||||
@@ -0,0 +1,50 @@
|
||||
import { Pipeline } from '@ephox/agar';
|
||||
import { UnitTest } from '@ephox/bedrock';
|
||||
import { LegacyUnit, TinyLoader } from '@ephox/mcagar';
|
||||
|
||||
import Plugin from 'tinymce/plugins/noneditable/Plugin';
|
||||
import Theme from 'tinymce/themes/modern/Theme';
|
||||
|
||||
UnitTest.asynctest('browser.tinymce.plugins.noneditable.NonEditablePluginTest', function () {
|
||||
const success = arguments[arguments.length - 2];
|
||||
const failure = arguments[arguments.length - 1];
|
||||
const suite = LegacyUnit.createSuite();
|
||||
|
||||
Plugin();
|
||||
Theme();
|
||||
|
||||
suite.test('noneditable class', function (editor) {
|
||||
editor.setContent('<p><span class="mceNonEditable">abc</span></p>');
|
||||
LegacyUnit.equal(editor.dom.select('span')[0].contentEditable, 'false');
|
||||
});
|
||||
|
||||
suite.test('editable class', function (editor) {
|
||||
editor.setContent('<p><span class="mceEditable">abc</span></p>');
|
||||
LegacyUnit.equal(editor.dom.select('span')[0].contentEditable, 'true');
|
||||
});
|
||||
|
||||
suite.test('noneditable regexp', function (editor) {
|
||||
editor.setContent('<p>{test1}{test2}</p>');
|
||||
|
||||
LegacyUnit.equal(editor.dom.select('span').length, 2);
|
||||
LegacyUnit.equal(editor.dom.select('span')[0].contentEditable, 'false');
|
||||
LegacyUnit.equal(editor.dom.select('span')[1].contentEditable, 'false');
|
||||
LegacyUnit.equal(editor.getContent(), '<p>{test1}{test2}</p>');
|
||||
});
|
||||
|
||||
suite.test('noneditable regexp inside cE=false', function (editor) {
|
||||
editor.setContent('<span contenteditable="false">{test1}</span>');
|
||||
LegacyUnit.equal(editor.dom.select('span').length, 1);
|
||||
});
|
||||
|
||||
TinyLoader.setup(function (editor, onSuccess, onFailure) {
|
||||
Pipeline.async({}, suite.toSteps(editor), onSuccess, onFailure);
|
||||
}, {
|
||||
add_unload_trigger: false,
|
||||
indent: false,
|
||||
noneditable_regexp: [/\{[^\}]+\}/g],
|
||||
plugins: 'noneditable',
|
||||
entities: 'raw',
|
||||
skin_url: '/project/js/tinymce/skins/lightgray'
|
||||
}, success, failure);
|
||||
});
|
||||
Reference in New Issue
Block a user