Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@tinymce/tinymce-react

Package Overview
Dependencies
Maintainers
1
Versions
365
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@tinymce/tinymce-react - npm Package Compare versions

Comparing version 3.2.0 to 3.3.0

4

CHANGELOG.md

@@ -0,1 +1,5 @@

## 3.3.0 (2019-07-29)
* Fixed an issue that made the editor ignore new event handlers provided through props
* Removed use of deprecated lifecycle hooks `componentWillMount` and `componentWillReceiveProps`
## 3.2.0 (2019-06-04)

@@ -2,0 +6,0 @@ * Changed the CDN URL to use `cdn.tiny.cloud`

16

lib/cjs/main/ts/components/Editor.d.ts

@@ -31,12 +31,16 @@ /**

static defaultProps: Partial<IAllProps>;
private element;
private id?;
private id;
private elementRef;
private editor?;
private inline?;
private inline;
private currentContent?;
componentWillMount(): void;
private boundHandlers;
constructor(props: Partial<IAllProps>);
componentDidUpdate(prevProps: Partial<IAllProps>): void;
componentDidMount(): void;
componentWillUnmount(): void;
componentWillReceiveProps(nextProps: Partial<IProps>): void;
render(): JSX.Element;
render(): React.ReactElement<{
ref: React.RefObject<Element>;
id: string;
}, string | ((props: any) => React.ReactElement<any, string | any | (new (props: any) => React.Component<any, any, any>)> | null) | (new (props: any) => React.Component<any, any, any>)>;
private initialise;

@@ -43,0 +47,0 @@ private initEditor;

@@ -42,7 +42,6 @@ "use strict";

__extends(Editor, _super);
function Editor() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.element = null;
function Editor(props) {
var _this = _super.call(this, props) || this;
_this.initialise = function () {
var finalInit = __assign({}, _this.props.init, { target: _this.element, readonly: _this.props.disabled, inline: _this.inline, plugins: Utils_1.mergePlugins(_this.props.init && _this.props.init.plugins, _this.props.plugins), toolbar: _this.props.toolbar || (_this.props.init && _this.props.init.toolbar), setup: function (editor) {
var finalInit = __assign({}, _this.props.init, { target: _this.elementRef.current, readonly: _this.props.disabled, inline: _this.inline, plugins: Utils_1.mergePlugins(_this.props.init && _this.props.init.plugins, _this.props.plugins), toolbar: _this.props.toolbar || (_this.props.init && _this.props.init.toolbar), setup: function (editor) {
_this.editor = editor;

@@ -56,12 +55,24 @@ editor.on('init', function (e) {

} });
if (Utils_1.isTextarea(_this.element)) {
_this.element.style.visibility = '';
if (Utils_1.isTextarea(_this.elementRef.current)) {
_this.elementRef.current.style.visibility = '';
}
TinyMCE_1.getTinymce().init(finalInit);
};
_this.id = _this.props.id || Utils_1.uuid('tiny-react');
_this.elementRef = React.createRef();
_this.inline = _this.props.inline ? _this.props.inline : _this.props.init && _this.props.init.inline;
_this.boundHandlers = {};
return _this;
}
Editor.prototype.componentWillMount = function () {
this.id = this.id || this.props.id || Utils_1.uuid('tiny-react');
this.inline = this.props.inline ? this.props.inline : this.props.init && this.props.init.inline;
Editor.prototype.componentDidUpdate = function (prevProps) {
if (this.editor && this.editor.initialized) {
Utils_1.bindHandlers(this.editor, this.props, this.boundHandlers);
this.currentContent = this.currentContent || this.editor.getContent();
if (typeof this.props.value === 'string' && this.props.value !== prevProps.value && this.props.value !== this.currentContent) {
this.editor.setContent(this.props.value);
}
if (typeof this.props.disabled === 'boolean' && this.props.disabled !== prevProps.disabled) {
this.editor.setMode(this.props.disabled ? 'readonly' : 'design');
}
}
};

@@ -72,4 +83,4 @@ Editor.prototype.componentDidMount = function () {

}
else if (this.element && this.element.ownerDocument) {
var doc = this.element.ownerDocument;
else if (this.elementRef.current && this.elementRef.current.ownerDocument) {
var doc = this.elementRef.current.ownerDocument;
var channel = this.props.cloudChannel;

@@ -85,13 +96,2 @@ var apiKey = this.props.apiKey ? this.props.apiKey : 'no-api-key';

};
Editor.prototype.componentWillReceiveProps = function (nextProps) {
if (this.editor && this.editor.initialized) {
this.currentContent = this.currentContent || this.editor.getContent();
if (typeof nextProps.value === 'string' && nextProps.value !== this.props.value && nextProps.value !== this.currentContent) {
this.editor.setContent(nextProps.value);
}
if (typeof nextProps.disabled === 'boolean' && nextProps.disabled !== this.props.disabled) {
this.editor.setMode(nextProps.disabled ? 'readonly' : 'design');
}
}
};
Editor.prototype.render = function () {

@@ -112,9 +112,11 @@ return this.inline ? this.renderInline() : this.renderIframe();

}
Utils_1.bindHandlers(this.props, editor, initEvent);
if (Utils_1.isFunction(this.props.onInit)) {
this.props.onInit(initEvent, editor);
}
Utils_1.bindHandlers(editor, this.props, this.boundHandlers);
};
Editor.prototype.renderInline = function () {
var _this = this;
var _a = this.props.tagName, tagName = _a === void 0 ? 'div' : _a;
return React.createElement(tagName, {
ref: function (elm) { return (_this.element = elm); },
ref: this.elementRef,
id: this.id

@@ -124,4 +126,8 @@ });

Editor.prototype.renderIframe = function () {
var _this = this;
return React.createElement("textarea", { ref: function (elm) { return (_this.element = elm); }, style: { visibility: 'hidden' }, id: this.id, name: this.props.textareaName });
return React.createElement('textarea', {
ref: this.elementRef,
style: { visibility: 'hidden' },
name: this.props.textareaName,
id: this.id
});
};

@@ -128,0 +134,0 @@ Editor.propTypes = EditorPropTypes_1.EditorPropTypes;

@@ -14,68 +14,6 @@ /**

};
export interface IEditorPropTypes extends CopyProps<IEvents>, CopyProps<IProps> {
export declare type IEventPropTypes = CopyProps<IEvents>;
export interface IEditorPropTypes extends IEventPropTypes, CopyProps<IProps> {
}
export declare const eventPropTypes: {
onActivate: PropTypes.Requireable<(...args: any[]) => any>;
onAddUndo: PropTypes.Requireable<(...args: any[]) => any>;
onBeforeAddUndo: PropTypes.Requireable<(...args: any[]) => any>;
onBeforeExecCommand: PropTypes.Requireable<(...args: any[]) => any>;
onBeforeGetContent: PropTypes.Requireable<(...args: any[]) => any>;
onBeforeRenderUI: PropTypes.Requireable<(...args: any[]) => any>;
onBeforeSetContent: PropTypes.Requireable<(...args: any[]) => any>;
onBeforePaste: PropTypes.Requireable<(...args: any[]) => any>;
onBlur: PropTypes.Requireable<(...args: any[]) => any>;
onChange: PropTypes.Requireable<(...args: any[]) => any>;
onClearUndos: PropTypes.Requireable<(...args: any[]) => any>;
onClick: PropTypes.Requireable<(...args: any[]) => any>;
onContextMenu: PropTypes.Requireable<(...args: any[]) => any>;
onCopy: PropTypes.Requireable<(...args: any[]) => any>;
onCut: PropTypes.Requireable<(...args: any[]) => any>;
onDblclick: PropTypes.Requireable<(...args: any[]) => any>;
onDeactivate: PropTypes.Requireable<(...args: any[]) => any>;
onDirty: PropTypes.Requireable<(...args: any[]) => any>;
onDrag: PropTypes.Requireable<(...args: any[]) => any>;
onDragDrop: PropTypes.Requireable<(...args: any[]) => any>;
onDragEnd: PropTypes.Requireable<(...args: any[]) => any>;
onDragGesture: PropTypes.Requireable<(...args: any[]) => any>;
onDragOver: PropTypes.Requireable<(...args: any[]) => any>;
onDrop: PropTypes.Requireable<(...args: any[]) => any>;
onExecCommand: PropTypes.Requireable<(...args: any[]) => any>;
onFocus: PropTypes.Requireable<(...args: any[]) => any>;
onFocusIn: PropTypes.Requireable<(...args: any[]) => any>;
onFocusOut: PropTypes.Requireable<(...args: any[]) => any>;
onGetContent: PropTypes.Requireable<(...args: any[]) => any>;
onHide: PropTypes.Requireable<(...args: any[]) => any>;
onInit: PropTypes.Requireable<(...args: any[]) => any>;
onKeyDown: PropTypes.Requireable<(...args: any[]) => any>;
onKeyPress: PropTypes.Requireable<(...args: any[]) => any>;
onKeyUp: PropTypes.Requireable<(...args: any[]) => any>;
onLoadContent: PropTypes.Requireable<(...args: any[]) => any>;
onMouseDown: PropTypes.Requireable<(...args: any[]) => any>;
onMouseEnter: PropTypes.Requireable<(...args: any[]) => any>;
onMouseLeave: PropTypes.Requireable<(...args: any[]) => any>;
onMouseMove: PropTypes.Requireable<(...args: any[]) => any>;
onMouseOut: PropTypes.Requireable<(...args: any[]) => any>;
onMouseOver: PropTypes.Requireable<(...args: any[]) => any>;
onMouseUp: PropTypes.Requireable<(...args: any[]) => any>;
onNodeChange: PropTypes.Requireable<(...args: any[]) => any>;
onObjectResizeStart: PropTypes.Requireable<(...args: any[]) => any>;
onObjectResized: PropTypes.Requireable<(...args: any[]) => any>;
onObjectSelected: PropTypes.Requireable<(...args: any[]) => any>;
onPaste: PropTypes.Requireable<(...args: any[]) => any>;
onPostProcess: PropTypes.Requireable<(...args: any[]) => any>;
onPostRender: PropTypes.Requireable<(...args: any[]) => any>;
onPreProcess: PropTypes.Requireable<(...args: any[]) => any>;
onProgressState: PropTypes.Requireable<(...args: any[]) => any>;
onRedo: PropTypes.Requireable<(...args: any[]) => any>;
onRemove: PropTypes.Requireable<(...args: any[]) => any>;
onReset: PropTypes.Requireable<(...args: any[]) => any>;
onSaveContent: PropTypes.Requireable<(...args: any[]) => any>;
onSelectionChange: PropTypes.Requireable<(...args: any[]) => any>;
onSetAttrib: PropTypes.Requireable<(...args: any[]) => any>;
onSetContent: PropTypes.Requireable<(...args: any[]) => any>;
onShow: PropTypes.Requireable<(...args: any[]) => any>;
onSubmit: PropTypes.Requireable<(...args: any[]) => any>;
onUndo: PropTypes.Requireable<(...args: any[]) => any>;
onVisualAid: PropTypes.Requireable<(...args: any[]) => any>;
};
export declare const eventPropTypes: IEventPropTypes;
export declare const EditorPropTypes: IEditorPropTypes;

@@ -8,6 +8,7 @@ /**

*/
import { IAllProps } from './components/Editor';
export declare const isFunction: (x: any) => x is Function;
export declare const bindHandlers: (props: any, editor: any, initEvent: Event) => void;
export declare const bindHandlers: (editor: any, props: Partial<IAllProps>, boundHandlers: Record<string, Function>) => void;
export declare const uuid: (prefix: string) => string;
export declare const isTextarea: (element: Element | null) => element is HTMLTextAreaElement;
export declare const mergePlugins: (initPlugins: string | string[], inputPlugins?: string | string[] | undefined) => string[];

@@ -11,18 +11,26 @@ "use strict";

var EditorPropTypes_1 = require("./components/EditorPropTypes");
var isValidKey = function (keys) { return function (key) { return keys.indexOf(key) !== -1; }; };
// tslint:disable-next-line:ban-types
exports.isFunction = function (x) { return typeof x === 'function'; };
exports.bindHandlers = function (props, editor, initEvent) {
Object.keys(props)
.filter(isValidKey(Object.keys(EditorPropTypes_1.eventPropTypes)))
.forEach(function (key) {
var handler = props[key];
if (exports.isFunction(handler)) {
if (key === 'onInit') {
handler(initEvent, editor);
}
else {
editor.on(key.substring(2), function (e) { return handler(e, editor); });
}
var isEventProp = function (name) {
return name in EditorPropTypes_1.eventPropTypes;
};
var findEventHandlers = function (props) {
return Object.keys(props)
.filter(isEventProp)
.filter(function (name) { return exports.isFunction(props[name]); })
.map(function (name) { return ({
handler: props[name],
eventName: name.substring(2)
}); });
};
exports.bindHandlers = function (editor, props, boundHandlers) {
findEventHandlers(props).forEach(function (found) {
// Unbind old handler
var oldHandler = boundHandlers[found.eventName];
if (exports.isFunction(oldHandler)) {
editor.off(found.eventName, oldHandler);
}
// Bind new handler
var newHandler = function (e) { return found.handler(e, editor); };
boundHandlers[found.eventName] = newHandler;
editor.on(found.eventName, newHandler);
});

@@ -29,0 +37,0 @@ };

@@ -9,10 +9,9 @@ import { Chain } from '@ephox/agar';

ref: React.RefObject<Editor>;
root: HTMLElement;
}
declare type TestEditor = (props: IAllProps) => JSX.Element;
declare const cSetup: (createElement: (Ed: TestEditor) => JSX.Element) => Chain<Payload, Payload>;
declare const cRemove: Chain<Payload, Payload>;
declare const cNamedChainDirect: (name: "ref" | "DOMNode" | "editor" | "root") => Chain<Record<string, any>, Record<string, any>>;
declare const cRender: (props: IAllProps) => Chain<Payload, Payload>;
declare const cReRender: (props: IAllProps) => Chain<Payload, Payload>;
declare const cRemove: Chain<{}, {}>;
declare const cNamedChainDirect: (name: "ref" | "DOMNode" | "editor") => Chain<Record<string, any>, Record<string, any>>;
declare const cDOMNode: (chain: Chain<any, any>) => Chain<{}, any>;
declare const cEditor: (chain: Chain<any, any>) => Chain<{}, any>;
export { cSetup, cRemove, cNamedChainDirect, cDOMNode, cEditor };
export { cRender, cReRender, cRemove, cNamedChainDirect, cDOMNode, cEditor };

@@ -18,53 +18,47 @@ "use strict";

var ReactDOM = require("react-dom");
var TinyMCE_1 = require("src/main/ts/TinyMCE");
var Editor_1 = require("../../../main/ts/components/Editor");
require("tinymce/tinymce");
var setTinymceBaseUrl = function (baseUrl) {
var tinymce = TinyMCE_1.getTinymce();
var prefix = document.location.protocol + '//' + document.location.host;
tinymce.baseURL = baseUrl.indexOf('://') === -1 ? prefix + baseUrl : baseUrl;
tinymce.baseURI = new tinymce.util.URI(tinymce.baseURL);
var getRoot = function () {
return katamari_1.Option.from(document.getElementById('root')).getOrThunk(function () {
var root = document.createElement('div');
root.id = 'root';
document.body.appendChild(root);
return root;
});
};
var getTestEditor = function (onLoaded) {
return function (props) {
var cRender = function (props) {
return agar_1.Chain.async(function (_, next, die) {
var originalInit = props.init || {};
var originalSetup = originalInit.setup || katamari_1.Fun.noop;
var ref = React.createRef();
var init = __assign({}, originalInit, { setup: function (editor) {
var init = __assign({}, originalInit, { base_url: "/project/node_modules/tinymce", setup: function (editor) {
originalSetup(editor);
editor.on('SkinLoaded', function () {
setTimeout(function () {
onLoaded(editor, ref);
katamari_1.Option.from(ref.current)
.map(ReactDOM.findDOMNode)
.filter(function (val) { return val instanceof Element; })
.fold(function () { return die('Could not find DOMNode'); }, function (DOMNode) {
next({
ref: ref,
editor: editor,
DOMNode: DOMNode
});
});
}, 0);
});
} });
setTinymceBaseUrl(init.base_url || "/project/node_modules/tinymce");
return React.createElement(Editor_1.Editor, __assign({ ref: ref }, props, { init: init }));
};
ReactDOM.render(React.createElement(Editor_1.Editor, __assign({ ref: ref }, props, { init: init })), getRoot());
});
};
var cSetup = function (createElement) {
return agar_1.Chain.async(function (_, next, die) {
var root = document.createElement('div');
document.body.appendChild(root);
var onEditorLoaded = function (editor, ref) {
katamari_1.Option.from(ref.current)
.map(ReactDOM.findDOMNode)
.filter(function (val) { return val instanceof Element; })
.fold(function () { return die('Could not find DOMNode'); }, function (DOMNode) {
next({
ref: ref,
root: root,
editor: editor,
DOMNode: DOMNode
});
});
};
var testEditor = getTestEditor(onEditorLoaded);
var editorElement = createElement(testEditor);
ReactDOM.render(editorElement, root);
exports.cRender = cRender;
// By rendering the Editor into the same root, React will perform a diff and update.
var cReRender = function (props) {
return agar_1.Chain.op(function (payload) {
ReactDOM.render(React.createElement(Editor_1.Editor, __assign({ ref: payload.ref }, props)), getRoot());
});
};
exports.cSetup = cSetup;
var cRemove = agar_1.Chain.op(function (res) {
ReactDOM.unmountComponentAtNode(res.root);
exports.cReRender = cReRender;
var cRemove = agar_1.Chain.op(function (_) {
ReactDOM.unmountComponentAtNode(getRoot());
});

@@ -71,0 +65,0 @@ exports.cRemove = cRemove;

import { Chain } from '@ephox/agar';
declare const EventState: () => {
cEach: (name: string, doAssert: (args: any[]) => void) => Chain<any, any>;
handler: (name: string) => (...args: any[]) => void;
cEach: (name: string, assertState: (args: any[]) => void) => Chain<any, any>;
createHandler: (name: string) => (...args: any[]) => void;
get: (name: string) => any;
cClearState: Chain<{}, {}>;
};
export { EventState };
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
Object.defineProperty(exports, "__esModule", { value: true });
var agar_1 = require("@ephox/agar");
var katamari_1 = require("@ephox/katamari");
var EventState = function () {
var state = {};
var handler = function (name) {
var state = katamari_1.Cell({});
var createHandler = function (name) {
return function () {

@@ -12,22 +24,27 @@ var args = [];

}
state[name] = args;
var _a;
state.set(__assign({}, state.get(), (_a = {}, _a[name] = args, _a)));
};
};
var get = function (name) {
return state[name];
return state.get()[name];
};
var cEach = function (name, doAssert) {
var cEach = function (name, assertState) {
return agar_1.Chain.fromChains([
agar_1.Chain.op(function () { return agar_1.Assertions.assertEq(name + ' should exist', true, !!state[name]); }),
agar_1.Chain.op(function () {
doAssert(state[name]);
agar_1.Assertions.assertEq('State from "' + name + '" handler should exist', true, name in state.get());
assertState(state.get()[name]);
})
]);
};
var cClearState = agar_1.Chain.op(function () {
state.set({});
});
return {
cEach: cEach,
handler: handler,
get: get
createHandler: createHandler,
get: get,
cClearState: cClearState
};
};
exports.EventState = EventState;

@@ -5,3 +5,2 @@ "use strict";

var bedrock_1 = require("@ephox/bedrock");
var React = require("react");
var Loader_1 = require("../alien/Loader");

@@ -15,14 +14,61 @@ var mcagar_1 = require("@ephox/mcagar");

};
var state = TestHelpers_1.EventState();
var eventState = TestHelpers_1.EventState();
agar_1.Pipeline.async({}, [
agar_1.Logger.t('Assert structure of editor and react wrapper events', agar_1.Chain.asStep({}, [
Loader_1.cSetup(function (Editor) { return (React.createElement(Editor, { onEditorChange: state.handler('onEditorChange'), onSetContent: state.handler('onSetContent') })); }),
agar_1.Logger.t('Assert structure of tinymce and tinymce-react events', agar_1.Chain.asStep({}, [
Loader_1.cRender({
onEditorChange: eventState.createHandler('onEditorChange'),
onSetContent: eventState.createHandler('onSetContent')
}),
Loader_1.cEditor(mcagar_1.ApiChains.cSetContent('<p>Initial Content</p>')),
// tinymce native event
eventState.cEach('onSetContent', function (args) { return agar_1.Assertions.assertEq('First arg should be event from Tiny', '<p>Initial Content</p>', args[0].content); }),
eventState.cEach('onSetContent', function (args) { return agar_1.Assertions.assertEq('Second arg should be editor', true, isEditor(args[1])); }),
// tinymce-react unique event
eventState.cEach('onEditorChange', function (args) { return agar_1.Assertions.assertEq('First arg should be new content', '<p>Initial Content</p>', args[0]); }),
eventState.cEach('onEditorChange', function (args) { return agar_1.Assertions.assertEq('Second arg should be editor', true, isEditor(args[1])); }),
eventState.cClearState,
Loader_1.cRemove
])),
agar_1.Logger.t('Should be able to register an event handler after initial render', agar_1.Chain.asStep({}, [
Loader_1.cRender({ initialValue: '<p>Initial Content</p>' }),
Loader_1.cReRender({ onSetContent: eventState.createHandler('onSetContent') }),
Loader_1.cEditor(mcagar_1.ApiChains.cAssertContent('<p>Initial Content</p>')),
Loader_1.cEditor(mcagar_1.ApiChains.cSetContent('<p>New Content</p>')),
state.cEach('onEditorChange', function (args) { return agar_1.Assertions.assertEq('First arg should be new content', '<p>New Content</p>', args[0]); }),
state.cEach('onEditorChange', function (args) { return agar_1.Assertions.assertEq('Second arg should be editor', true, isEditor(args[1])); }),
state.cEach('onSetContent', function (args) { return agar_1.Assertions.assertEq('First arg should be something', true, !!args[0]); }),
state.cEach('onSetContent', function (args) { return agar_1.Assertions.assertEq('Second arg should be editor', true, isEditor(args[1])); }),
eventState.cEach('onSetContent', function (args) { return agar_1.Assertions.assertEq('Should have bound handler, hence new content', '<p>New Content</p>', args[0].content); }),
eventState.cClearState,
Loader_1.cRemove
])),
agar_1.Logger.t('Providing a new event handler and re-rendering should unbind old handler and bind new handler', agar_1.Chain.asStep({}, [
Loader_1.cRender({ onSetContent: eventState.createHandler('InitialHandler') }),
Loader_1.cEditor(mcagar_1.ApiChains.cSetContent('<p>Initial Content</p>')),
Loader_1.cReRender({ onSetContent: eventState.createHandler('NewHandler') }),
Loader_1.cEditor(mcagar_1.ApiChains.cSetContent('<p>New Content</p>')),
eventState.cEach('InitialHandler', function (args) {
return agar_1.Assertions.assertEq('Initial handler should have been unbound, hence initial content', '<p>Initial Content</p>', args[0].content);
}),
eventState.cEach('NewHandler', function (args) {
return agar_1.Assertions.assertEq('New handler should have been bound, hence new content', '<p>New Content</p>', args[0].content);
}),
eventState.cClearState,
Loader_1.cRemove
])),
agar_1.Logger.t('Test value prop', agar_1.Chain.asStep({}, [
Loader_1.cRender({ value: '<p>Initial Value</p>' }),
Loader_1.cEditor(mcagar_1.ApiChains.cAssertContent('<p>Initial Value</p>')),
Loader_1.cReRender({ value: '<p>New Value</p>' }),
Loader_1.cEditor(mcagar_1.ApiChains.cAssertContent('<p>New Value</p>')),
Loader_1.cRemove
])),
agar_1.Logger.t('Test disabled prop', agar_1.Chain.asStep({}, [
Loader_1.cRender({}),
Loader_1.cEditor(agar_1.Chain.op(function (editor) {
agar_1.Assertions.assertEq('Should be design mode', 'design', editor.mode.get());
})),
Loader_1.cReRender({ disabled: true }),
Loader_1.cEditor(agar_1.Chain.op(function (editor) {
agar_1.Assertions.assertEq('Should be readonly mode', 'readonly', editor.mode.get());
})),
Loader_1.cRemove
]))
], success, failure);
});

@@ -5,3 +5,2 @@ "use strict";

var bedrock_1 = require("@ephox/bedrock");
var React = require("react");
var Loader_1 = require("../alien/Loader");

@@ -17,3 +16,3 @@ bedrock_1.UnitTest.asynctest('Editor.test', function (success, failure) {

agar_1.Logger.t('it is div by default for inline', agar_1.Chain.asStep({}, [
Loader_1.cSetup(function (Editor) { return React.createElement(Editor, { inline: true }); }),
Loader_1.cRender({ inline: true }),
Loader_1.cDOMNode(cAssertProperty('tagName', 'DIV')),

@@ -23,3 +22,7 @@ Loader_1.cRemove

agar_1.Logger.t('can be set to inline in init', agar_1.Chain.asStep({}, [
Loader_1.cSetup(function (Editor) { return React.createElement(Editor, { init: { inline: true } }); }),
Loader_1.cRender({
init: {
inline: true
}
}),
Loader_1.cDOMNode(cAssertProperty('tagName', 'DIV')),

@@ -29,3 +32,6 @@ Loader_1.cRemove

agar_1.Logger.t('it can be changed to p', agar_1.Chain.asStep({}, [
Loader_1.cSetup(function (Editor) { return React.createElement(Editor, { inline: true, tagName: 'p' }); }),
Loader_1.cRender({
inline: true,
tagName: 'p'
}),
Loader_1.cDOMNode(cAssertProperty('tagName', 'P')),

@@ -35,3 +41,3 @@ Loader_1.cRemove

agar_1.Logger.t('iframe editor does not change element', agar_1.Chain.asStep({}, [
Loader_1.cSetup(function (Editor) { return React.createElement(Editor, { tagName: 'p' }); }),
Loader_1.cRender({ tagName: 'p' }),
Loader_1.cDOMNode(cAssertProperty('tagName', 'TEXTAREA')),

@@ -43,3 +49,3 @@ Loader_1.cRemove

agar_1.Logger.t('is set normally if prop is provided', agar_1.Chain.asStep({}, [
Loader_1.cSetup(function (Editor) { return React.createElement(Editor, { id: 'test' }); }),
Loader_1.cRender({ id: 'test' }),
Loader_1.cDOMNode(cAssertProperty('id', 'test')),

@@ -49,3 +55,3 @@ Loader_1.cRemove

agar_1.Logger.t('gets set automatically to uuid if not set', agar_1.Chain.asStep({}, [
Loader_1.cSetup(function (Editor) { return React.createElement(Editor, null); }),
Loader_1.cRender({}),
Loader_1.cDOMNode(agar_1.Chain.op(function (node) {

@@ -59,3 +65,3 @@ agar_1.Assertions.assertEq('Should not be uuid', typeof node.id === 'string' && node.id.indexOf('tiny-react') !== -1, true);

agar_1.Logger.t('is not set when prop is not provided', agar_1.Chain.asStep({}, [
Loader_1.cSetup(function (Editor) { return React.createElement(Editor, null); }),
Loader_1.cRender({}),
Loader_1.cDOMNode(cAssertProperty('name', '')),

@@ -65,3 +71,3 @@ Loader_1.cRemove

agar_1.Logger.t('is set when prop is provided', agar_1.Chain.asStep({}, [
Loader_1.cSetup(function (Editor) { return React.createElement(Editor, { textareaName: 'test' }); }),
Loader_1.cRender({ textareaName: 'test' }),
Loader_1.cDOMNode(cAssertProperty('name', 'test')),

@@ -68,0 +74,0 @@ Loader_1.cRemove

@@ -31,12 +31,16 @@ /**

static defaultProps: Partial<IAllProps>;
private element;
private id?;
private id;
private elementRef;
private editor?;
private inline?;
private inline;
private currentContent?;
componentWillMount(): void;
private boundHandlers;
constructor(props: Partial<IAllProps>);
componentDidUpdate(prevProps: Partial<IAllProps>): void;
componentDidMount(): void;
componentWillUnmount(): void;
componentWillReceiveProps(nextProps: Partial<IProps>): void;
render(): JSX.Element;
render(): React.ReactElement<{
ref: React.RefObject<Element>;
id: string;
}, string | ((props: any) => React.ReactElement<any, string | any | (new (props: any) => React.Component<any, any, any>)> | null) | (new (props: any) => React.Component<any, any, any>)>;
private initialise;

@@ -43,0 +47,0 @@ private initEditor;

@@ -40,7 +40,6 @@ /**

__extends(Editor, _super);
function Editor() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.element = null;
function Editor(props) {
var _this = _super.call(this, props) || this;
_this.initialise = function () {
var finalInit = __assign({}, _this.props.init, { target: _this.element, readonly: _this.props.disabled, inline: _this.inline, plugins: mergePlugins(_this.props.init && _this.props.init.plugins, _this.props.plugins), toolbar: _this.props.toolbar || (_this.props.init && _this.props.init.toolbar), setup: function (editor) {
var finalInit = __assign({}, _this.props.init, { target: _this.elementRef.current, readonly: _this.props.disabled, inline: _this.inline, plugins: mergePlugins(_this.props.init && _this.props.init.plugins, _this.props.plugins), toolbar: _this.props.toolbar || (_this.props.init && _this.props.init.toolbar), setup: function (editor) {
_this.editor = editor;

@@ -54,12 +53,24 @@ editor.on('init', function (e) {

} });
if (isTextarea(_this.element)) {
_this.element.style.visibility = '';
if (isTextarea(_this.elementRef.current)) {
_this.elementRef.current.style.visibility = '';
}
getTinymce().init(finalInit);
};
_this.id = _this.props.id || uuid('tiny-react');
_this.elementRef = React.createRef();
_this.inline = _this.props.inline ? _this.props.inline : _this.props.init && _this.props.init.inline;
_this.boundHandlers = {};
return _this;
}
Editor.prototype.componentWillMount = function () {
this.id = this.id || this.props.id || uuid('tiny-react');
this.inline = this.props.inline ? this.props.inline : this.props.init && this.props.init.inline;
Editor.prototype.componentDidUpdate = function (prevProps) {
if (this.editor && this.editor.initialized) {
bindHandlers(this.editor, this.props, this.boundHandlers);
this.currentContent = this.currentContent || this.editor.getContent();
if (typeof this.props.value === 'string' && this.props.value !== prevProps.value && this.props.value !== this.currentContent) {
this.editor.setContent(this.props.value);
}
if (typeof this.props.disabled === 'boolean' && this.props.disabled !== prevProps.disabled) {
this.editor.setMode(this.props.disabled ? 'readonly' : 'design');
}
}
};

@@ -70,4 +81,4 @@ Editor.prototype.componentDidMount = function () {

}
else if (this.element && this.element.ownerDocument) {
var doc = this.element.ownerDocument;
else if (this.elementRef.current && this.elementRef.current.ownerDocument) {
var doc = this.elementRef.current.ownerDocument;
var channel = this.props.cloudChannel;

@@ -83,13 +94,2 @@ var apiKey = this.props.apiKey ? this.props.apiKey : 'no-api-key';

};
Editor.prototype.componentWillReceiveProps = function (nextProps) {
if (this.editor && this.editor.initialized) {
this.currentContent = this.currentContent || this.editor.getContent();
if (typeof nextProps.value === 'string' && nextProps.value !== this.props.value && nextProps.value !== this.currentContent) {
this.editor.setContent(nextProps.value);
}
if (typeof nextProps.disabled === 'boolean' && nextProps.disabled !== this.props.disabled) {
this.editor.setMode(nextProps.disabled ? 'readonly' : 'design');
}
}
};
Editor.prototype.render = function () {

@@ -110,9 +110,11 @@ return this.inline ? this.renderInline() : this.renderIframe();

}
bindHandlers(this.props, editor, initEvent);
if (isFunction(this.props.onInit)) {
this.props.onInit(initEvent, editor);
}
bindHandlers(editor, this.props, this.boundHandlers);
};
Editor.prototype.renderInline = function () {
var _this = this;
var _a = this.props.tagName, tagName = _a === void 0 ? 'div' : _a;
return React.createElement(tagName, {
ref: function (elm) { return (_this.element = elm); },
ref: this.elementRef,
id: this.id

@@ -122,4 +124,8 @@ });

Editor.prototype.renderIframe = function () {
var _this = this;
return React.createElement("textarea", { ref: function (elm) { return (_this.element = elm); }, style: { visibility: 'hidden' }, id: this.id, name: this.props.textareaName });
return React.createElement('textarea', {
ref: this.elementRef,
style: { visibility: 'hidden' },
name: this.props.textareaName,
id: this.id
});
};

@@ -126,0 +132,0 @@ Editor.propTypes = EditorPropTypes;

@@ -14,68 +14,6 @@ /**

};
export interface IEditorPropTypes extends CopyProps<IEvents>, CopyProps<IProps> {
export declare type IEventPropTypes = CopyProps<IEvents>;
export interface IEditorPropTypes extends IEventPropTypes, CopyProps<IProps> {
}
export declare const eventPropTypes: {
onActivate: PropTypes.Requireable<(...args: any[]) => any>;
onAddUndo: PropTypes.Requireable<(...args: any[]) => any>;
onBeforeAddUndo: PropTypes.Requireable<(...args: any[]) => any>;
onBeforeExecCommand: PropTypes.Requireable<(...args: any[]) => any>;
onBeforeGetContent: PropTypes.Requireable<(...args: any[]) => any>;
onBeforeRenderUI: PropTypes.Requireable<(...args: any[]) => any>;
onBeforeSetContent: PropTypes.Requireable<(...args: any[]) => any>;
onBeforePaste: PropTypes.Requireable<(...args: any[]) => any>;
onBlur: PropTypes.Requireable<(...args: any[]) => any>;
onChange: PropTypes.Requireable<(...args: any[]) => any>;
onClearUndos: PropTypes.Requireable<(...args: any[]) => any>;
onClick: PropTypes.Requireable<(...args: any[]) => any>;
onContextMenu: PropTypes.Requireable<(...args: any[]) => any>;
onCopy: PropTypes.Requireable<(...args: any[]) => any>;
onCut: PropTypes.Requireable<(...args: any[]) => any>;
onDblclick: PropTypes.Requireable<(...args: any[]) => any>;
onDeactivate: PropTypes.Requireable<(...args: any[]) => any>;
onDirty: PropTypes.Requireable<(...args: any[]) => any>;
onDrag: PropTypes.Requireable<(...args: any[]) => any>;
onDragDrop: PropTypes.Requireable<(...args: any[]) => any>;
onDragEnd: PropTypes.Requireable<(...args: any[]) => any>;
onDragGesture: PropTypes.Requireable<(...args: any[]) => any>;
onDragOver: PropTypes.Requireable<(...args: any[]) => any>;
onDrop: PropTypes.Requireable<(...args: any[]) => any>;
onExecCommand: PropTypes.Requireable<(...args: any[]) => any>;
onFocus: PropTypes.Requireable<(...args: any[]) => any>;
onFocusIn: PropTypes.Requireable<(...args: any[]) => any>;
onFocusOut: PropTypes.Requireable<(...args: any[]) => any>;
onGetContent: PropTypes.Requireable<(...args: any[]) => any>;
onHide: PropTypes.Requireable<(...args: any[]) => any>;
onInit: PropTypes.Requireable<(...args: any[]) => any>;
onKeyDown: PropTypes.Requireable<(...args: any[]) => any>;
onKeyPress: PropTypes.Requireable<(...args: any[]) => any>;
onKeyUp: PropTypes.Requireable<(...args: any[]) => any>;
onLoadContent: PropTypes.Requireable<(...args: any[]) => any>;
onMouseDown: PropTypes.Requireable<(...args: any[]) => any>;
onMouseEnter: PropTypes.Requireable<(...args: any[]) => any>;
onMouseLeave: PropTypes.Requireable<(...args: any[]) => any>;
onMouseMove: PropTypes.Requireable<(...args: any[]) => any>;
onMouseOut: PropTypes.Requireable<(...args: any[]) => any>;
onMouseOver: PropTypes.Requireable<(...args: any[]) => any>;
onMouseUp: PropTypes.Requireable<(...args: any[]) => any>;
onNodeChange: PropTypes.Requireable<(...args: any[]) => any>;
onObjectResizeStart: PropTypes.Requireable<(...args: any[]) => any>;
onObjectResized: PropTypes.Requireable<(...args: any[]) => any>;
onObjectSelected: PropTypes.Requireable<(...args: any[]) => any>;
onPaste: PropTypes.Requireable<(...args: any[]) => any>;
onPostProcess: PropTypes.Requireable<(...args: any[]) => any>;
onPostRender: PropTypes.Requireable<(...args: any[]) => any>;
onPreProcess: PropTypes.Requireable<(...args: any[]) => any>;
onProgressState: PropTypes.Requireable<(...args: any[]) => any>;
onRedo: PropTypes.Requireable<(...args: any[]) => any>;
onRemove: PropTypes.Requireable<(...args: any[]) => any>;
onReset: PropTypes.Requireable<(...args: any[]) => any>;
onSaveContent: PropTypes.Requireable<(...args: any[]) => any>;
onSelectionChange: PropTypes.Requireable<(...args: any[]) => any>;
onSetAttrib: PropTypes.Requireable<(...args: any[]) => any>;
onSetContent: PropTypes.Requireable<(...args: any[]) => any>;
onShow: PropTypes.Requireable<(...args: any[]) => any>;
onSubmit: PropTypes.Requireable<(...args: any[]) => any>;
onUndo: PropTypes.Requireable<(...args: any[]) => any>;
onVisualAid: PropTypes.Requireable<(...args: any[]) => any>;
};
export declare const eventPropTypes: IEventPropTypes;
export declare const EditorPropTypes: IEditorPropTypes;

@@ -8,6 +8,7 @@ /**

*/
import { IAllProps } from './components/Editor';
export declare const isFunction: (x: any) => x is Function;
export declare const bindHandlers: (props: any, editor: any, initEvent: Event) => void;
export declare const bindHandlers: (editor: any, props: Partial<IAllProps>, boundHandlers: Record<string, Function>) => void;
export declare const uuid: (prefix: string) => string;
export declare const isTextarea: (element: Element | null) => element is HTMLTextAreaElement;
export declare const mergePlugins: (initPlugins: string | string[], inputPlugins?: string | string[] | undefined) => string[];

@@ -9,18 +9,26 @@ /**

import { eventPropTypes } from './components/EditorPropTypes';
var isValidKey = function (keys) { return function (key) { return keys.indexOf(key) !== -1; }; };
// tslint:disable-next-line:ban-types
export var isFunction = function (x) { return typeof x === 'function'; };
export var bindHandlers = function (props, editor, initEvent) {
Object.keys(props)
.filter(isValidKey(Object.keys(eventPropTypes)))
.forEach(function (key) {
var handler = props[key];
if (isFunction(handler)) {
if (key === 'onInit') {
handler(initEvent, editor);
}
else {
editor.on(key.substring(2), function (e) { return handler(e, editor); });
}
var isEventProp = function (name) {
return name in eventPropTypes;
};
var findEventHandlers = function (props) {
return Object.keys(props)
.filter(isEventProp)
.filter(function (name) { return isFunction(props[name]); })
.map(function (name) { return ({
handler: props[name],
eventName: name.substring(2)
}); });
};
export var bindHandlers = function (editor, props, boundHandlers) {
findEventHandlers(props).forEach(function (found) {
// Unbind old handler
var oldHandler = boundHandlers[found.eventName];
if (isFunction(oldHandler)) {
editor.off(found.eventName, oldHandler);
}
// Bind new handler
var newHandler = function (e) { return found.handler(e, editor); };
boundHandlers[found.eventName] = newHandler;
editor.on(found.eventName, newHandler);
});

@@ -27,0 +35,0 @@ };

@@ -9,10 +9,9 @@ import { Chain } from '@ephox/agar';

ref: React.RefObject<Editor>;
root: HTMLElement;
}
declare type TestEditor = (props: IAllProps) => JSX.Element;
declare const cSetup: (createElement: (Ed: TestEditor) => JSX.Element) => Chain<Payload, Payload>;
declare const cRemove: Chain<Payload, Payload>;
declare const cNamedChainDirect: (name: "ref" | "DOMNode" | "editor" | "root") => Chain<Record<string, any>, Record<string, any>>;
declare const cRender: (props: IAllProps) => Chain<Payload, Payload>;
declare const cReRender: (props: IAllProps) => Chain<Payload, Payload>;
declare const cRemove: Chain<{}, {}>;
declare const cNamedChainDirect: (name: "ref" | "DOMNode" | "editor") => Chain<Record<string, any>, Record<string, any>>;
declare const cDOMNode: (chain: Chain<any, any>) => Chain<{}, any>;
declare const cEditor: (chain: Chain<any, any>) => Chain<{}, any>;
export { cSetup, cRemove, cNamedChainDirect, cDOMNode, cEditor };
export { cRender, cReRender, cRemove, cNamedChainDirect, cDOMNode, cEditor };

@@ -16,52 +16,45 @@ var __assign = (this && this.__assign) || function () {

import * as ReactDOM from 'react-dom';
import { getTinymce } from 'src/main/ts/TinyMCE';
import { Editor } from '../../../main/ts/components/Editor';
import 'tinymce/tinymce';
var setTinymceBaseUrl = function (baseUrl) {
var tinymce = getTinymce();
var prefix = document.location.protocol + '//' + document.location.host;
tinymce.baseURL = baseUrl.indexOf('://') === -1 ? prefix + baseUrl : baseUrl;
tinymce.baseURI = new tinymce.util.URI(tinymce.baseURL);
var getRoot = function () {
return Option.from(document.getElementById('root')).getOrThunk(function () {
var root = document.createElement('div');
root.id = 'root';
document.body.appendChild(root);
return root;
});
};
var getTestEditor = function (onLoaded) {
return function (props) {
var cRender = function (props) {
return Chain.async(function (_, next, die) {
var originalInit = props.init || {};
var originalSetup = originalInit.setup || Fun.noop;
var ref = React.createRef();
var init = __assign({}, originalInit, { setup: function (editor) {
var init = __assign({}, originalInit, { base_url: "/project/node_modules/tinymce", setup: function (editor) {
originalSetup(editor);
editor.on('SkinLoaded', function () {
setTimeout(function () {
onLoaded(editor, ref);
Option.from(ref.current)
.map(ReactDOM.findDOMNode)
.filter(function (val) { return val instanceof Element; })
.fold(function () { return die('Could not find DOMNode'); }, function (DOMNode) {
next({
ref: ref,
editor: editor,
DOMNode: DOMNode
});
});
}, 0);
});
} });
setTinymceBaseUrl(init.base_url || "/project/node_modules/tinymce");
return React.createElement(Editor, __assign({ ref: ref }, props, { init: init }));
};
ReactDOM.render(React.createElement(Editor, __assign({ ref: ref }, props, { init: init })), getRoot());
});
};
var cSetup = function (createElement) {
return Chain.async(function (_, next, die) {
var root = document.createElement('div');
document.body.appendChild(root);
var onEditorLoaded = function (editor, ref) {
Option.from(ref.current)
.map(ReactDOM.findDOMNode)
.filter(function (val) { return val instanceof Element; })
.fold(function () { return die('Could not find DOMNode'); }, function (DOMNode) {
next({
ref: ref,
root: root,
editor: editor,
DOMNode: DOMNode
});
});
};
var testEditor = getTestEditor(onEditorLoaded);
var editorElement = createElement(testEditor);
ReactDOM.render(editorElement, root);
// By rendering the Editor into the same root, React will perform a diff and update.
var cReRender = function (props) {
return Chain.op(function (payload) {
ReactDOM.render(React.createElement(Editor, __assign({ ref: payload.ref }, props)), getRoot());
});
};
var cRemove = Chain.op(function (res) {
ReactDOM.unmountComponentAtNode(res.root);
var cRemove = Chain.op(function (_) {
ReactDOM.unmountComponentAtNode(getRoot());
});

@@ -83,2 +76,2 @@ var cNamedChainDirect = function (name) { return NamedChain.direct(NamedChain.inputName(), Chain.mapper(function (res) { return res[name]; }), name); };

};
export { cSetup, cRemove, cNamedChainDirect, cDOMNode, cEditor };
export { cRender, cReRender, cRemove, cNamedChainDirect, cDOMNode, cEditor };
import { Chain } from '@ephox/agar';
declare const EventState: () => {
cEach: (name: string, doAssert: (args: any[]) => void) => Chain<any, any>;
handler: (name: string) => (...args: any[]) => void;
cEach: (name: string, assertState: (args: any[]) => void) => Chain<any, any>;
createHandler: (name: string) => (...args: any[]) => void;
get: (name: string) => any;
cClearState: Chain<{}, {}>;
};
export { EventState };

@@ -0,5 +1,17 @@

var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
import { Chain, Assertions } from '@ephox/agar';
import { Cell } from '@ephox/katamari';
var EventState = function () {
var state = {};
var handler = function (name) {
var state = Cell({});
var createHandler = function (name) {
return function () {

@@ -10,22 +22,27 @@ var args = [];

}
state[name] = args;
var _a;
state.set(__assign({}, state.get(), (_a = {}, _a[name] = args, _a)));
};
};
var get = function (name) {
return state[name];
return state.get()[name];
};
var cEach = function (name, doAssert) {
var cEach = function (name, assertState) {
return Chain.fromChains([
Chain.op(function () { return Assertions.assertEq(name + ' should exist', true, !!state[name]); }),
Chain.op(function () {
doAssert(state[name]);
Assertions.assertEq('State from "' + name + '" handler should exist', true, name in state.get());
assertState(state.get()[name]);
})
]);
};
var cClearState = Chain.op(function () {
state.set({});
});
return {
cEach: cEach,
handler: handler,
get: get
createHandler: createHandler,
get: get,
cClearState: cClearState
};
};
export { EventState };
import { Assertions, Chain, Logger, Pipeline } from '@ephox/agar';
import { UnitTest } from '@ephox/bedrock';
import * as React from 'react';
import { cRemove, cSetup, cEditor } from '../alien/Loader';
import { cRemove, cRender, cEditor, cReRender } from '../alien/Loader';
import { ApiChains } from '@ephox/mcagar';

@@ -12,14 +11,61 @@ import { getTinymce } from '../../../main/ts/TinyMCE';

};
var state = EventState();
var eventState = EventState();
Pipeline.async({}, [
Logger.t('Assert structure of editor and react wrapper events', Chain.asStep({}, [
cSetup(function (Editor) { return (React.createElement(Editor, { onEditorChange: state.handler('onEditorChange'), onSetContent: state.handler('onSetContent') })); }),
Logger.t('Assert structure of tinymce and tinymce-react events', Chain.asStep({}, [
cRender({
onEditorChange: eventState.createHandler('onEditorChange'),
onSetContent: eventState.createHandler('onSetContent')
}),
cEditor(ApiChains.cSetContent('<p>Initial Content</p>')),
// tinymce native event
eventState.cEach('onSetContent', function (args) { return Assertions.assertEq('First arg should be event from Tiny', '<p>Initial Content</p>', args[0].content); }),
eventState.cEach('onSetContent', function (args) { return Assertions.assertEq('Second arg should be editor', true, isEditor(args[1])); }),
// tinymce-react unique event
eventState.cEach('onEditorChange', function (args) { return Assertions.assertEq('First arg should be new content', '<p>Initial Content</p>', args[0]); }),
eventState.cEach('onEditorChange', function (args) { return Assertions.assertEq('Second arg should be editor', true, isEditor(args[1])); }),
eventState.cClearState,
cRemove
])),
Logger.t('Should be able to register an event handler after initial render', Chain.asStep({}, [
cRender({ initialValue: '<p>Initial Content</p>' }),
cReRender({ onSetContent: eventState.createHandler('onSetContent') }),
cEditor(ApiChains.cAssertContent('<p>Initial Content</p>')),
cEditor(ApiChains.cSetContent('<p>New Content</p>')),
state.cEach('onEditorChange', function (args) { return Assertions.assertEq('First arg should be new content', '<p>New Content</p>', args[0]); }),
state.cEach('onEditorChange', function (args) { return Assertions.assertEq('Second arg should be editor', true, isEditor(args[1])); }),
state.cEach('onSetContent', function (args) { return Assertions.assertEq('First arg should be something', true, !!args[0]); }),
state.cEach('onSetContent', function (args) { return Assertions.assertEq('Second arg should be editor', true, isEditor(args[1])); }),
eventState.cEach('onSetContent', function (args) { return Assertions.assertEq('Should have bound handler, hence new content', '<p>New Content</p>', args[0].content); }),
eventState.cClearState,
cRemove
])),
Logger.t('Providing a new event handler and re-rendering should unbind old handler and bind new handler', Chain.asStep({}, [
cRender({ onSetContent: eventState.createHandler('InitialHandler') }),
cEditor(ApiChains.cSetContent('<p>Initial Content</p>')),
cReRender({ onSetContent: eventState.createHandler('NewHandler') }),
cEditor(ApiChains.cSetContent('<p>New Content</p>')),
eventState.cEach('InitialHandler', function (args) {
return Assertions.assertEq('Initial handler should have been unbound, hence initial content', '<p>Initial Content</p>', args[0].content);
}),
eventState.cEach('NewHandler', function (args) {
return Assertions.assertEq('New handler should have been bound, hence new content', '<p>New Content</p>', args[0].content);
}),
eventState.cClearState,
cRemove
])),
Logger.t('Test value prop', Chain.asStep({}, [
cRender({ value: '<p>Initial Value</p>' }),
cEditor(ApiChains.cAssertContent('<p>Initial Value</p>')),
cReRender({ value: '<p>New Value</p>' }),
cEditor(ApiChains.cAssertContent('<p>New Value</p>')),
cRemove
])),
Logger.t('Test disabled prop', Chain.asStep({}, [
cRender({}),
cEditor(Chain.op(function (editor) {
Assertions.assertEq('Should be design mode', 'design', editor.mode.get());
})),
cReRender({ disabled: true }),
cEditor(Chain.op(function (editor) {
Assertions.assertEq('Should be readonly mode', 'readonly', editor.mode.get());
})),
cRemove
]))
], success, failure);
});
import { Assertions, Chain, GeneralSteps, Logger, Pipeline } from '@ephox/agar';
import { UnitTest } from '@ephox/bedrock';
import * as React from 'react';
import { cRemove, cSetup, cDOMNode } from '../alien/Loader';
import { cRemove, cRender, cDOMNode } from '../alien/Loader';
UnitTest.asynctest('Editor.test', function (success, failure) {

@@ -14,3 +13,3 @@ var cAssertProperty = function (propName, expected) {

Logger.t('it is div by default for inline', Chain.asStep({}, [
cSetup(function (Editor) { return React.createElement(Editor, { inline: true }); }),
cRender({ inline: true }),
cDOMNode(cAssertProperty('tagName', 'DIV')),

@@ -20,3 +19,7 @@ cRemove

Logger.t('can be set to inline in init', Chain.asStep({}, [
cSetup(function (Editor) { return React.createElement(Editor, { init: { inline: true } }); }),
cRender({
init: {
inline: true
}
}),
cDOMNode(cAssertProperty('tagName', 'DIV')),

@@ -26,3 +29,6 @@ cRemove

Logger.t('it can be changed to p', Chain.asStep({}, [
cSetup(function (Editor) { return React.createElement(Editor, { inline: true, tagName: 'p' }); }),
cRender({
inline: true,
tagName: 'p'
}),
cDOMNode(cAssertProperty('tagName', 'P')),

@@ -32,3 +38,3 @@ cRemove

Logger.t('iframe editor does not change element', Chain.asStep({}, [
cSetup(function (Editor) { return React.createElement(Editor, { tagName: 'p' }); }),
cRender({ tagName: 'p' }),
cDOMNode(cAssertProperty('tagName', 'TEXTAREA')),

@@ -40,3 +46,3 @@ cRemove

Logger.t('is set normally if prop is provided', Chain.asStep({}, [
cSetup(function (Editor) { return React.createElement(Editor, { id: 'test' }); }),
cRender({ id: 'test' }),
cDOMNode(cAssertProperty('id', 'test')),

@@ -46,3 +52,3 @@ cRemove

Logger.t('gets set automatically to uuid if not set', Chain.asStep({}, [
cSetup(function (Editor) { return React.createElement(Editor, null); }),
cRender({}),
cDOMNode(Chain.op(function (node) {

@@ -56,3 +62,3 @@ Assertions.assertEq('Should not be uuid', typeof node.id === 'string' && node.id.indexOf('tiny-react') !== -1, true);

Logger.t('is not set when prop is not provided', Chain.asStep({}, [
cSetup(function (Editor) { return React.createElement(Editor, null); }),
cRender({}),
cDOMNode(cAssertProperty('name', '')),

@@ -62,3 +68,3 @@ cRemove

Logger.t('is set when prop is provided', Chain.asStep({}, [
cSetup(function (Editor) { return React.createElement(Editor, { textareaName: 'test' }); }),
cRender({ textareaName: 'test' }),
cDOMNode(cAssertProperty('name', 'test')),

@@ -65,0 +71,0 @@ cRemove

{
"name": "@tinymce/tinymce-react",
"version": "3.2.0",
"version": "3.3.0",
"description": "Official TinyMCE React Component",

@@ -38,2 +38,3 @@ "repository": {

"devDependencies": {
"@babel/core": "^7.0.0-0",
"@ephox/agar": "^4.12",

@@ -43,7 +44,7 @@ "@ephox/bedrock": "^4.2.8",

"@ephox/tslint-rules": "^1.0.7",
"@storybook/addon-actions": "^4.1.11",
"@storybook/addon-console": "^1.1.0",
"@storybook/addon-info": "^4.1.11",
"@storybook/addon-notes": "^4.1.11",
"@storybook/react": "^4.1.11",
"@storybook/addon-actions": "^5.1.9",
"@storybook/addon-console": "^1.1.1",
"@storybook/addon-info": "^5.2.0-alpha.30",
"@storybook/addon-notes": "^5.1.9",
"@storybook/react": "^5.1.9",
"@storybook/storybook-deployer": "^2.8.1",

@@ -57,2 +58,3 @@ "@types/node": "^10.12.19",

"awesome-typescript-loader": "^5.2.1",
"babel-loader": "^8.0.0",
"core-js": "^2.6.3",

@@ -59,0 +61,0 @@ "raf": "^3.4.1",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc