diff --git a/README.md b/README.md
index 6be2309..1e89cec 100644
--- a/README.md
+++ b/README.md
@@ -11,7 +11,7 @@
[![NPM](https://nodei.co/npm/@insidersbyte/react-markdown-editor.png?downloads=true&downloadRank=true)](https://nodei.co/npm/@insidersbyte/react-markdown-editor/)
-[React](http://facebook.github.io/react) Markdown editor with preview and drag and drop image support (at the moment it always adds the image to the end, regardless of where you drop it), built with [react-markdown-renderer](https://github.com/insidersbyte/react-markdown-renderer).
+[React](http://facebook.github.io/react) Markdown editor with preview, built with [react-markdown-renderer](https://github.com/insidersbyte/react-markdown-renderer).
## Demo
http://insidersbyte.github.io/react-markdown-editor
@@ -41,20 +41,6 @@ class App extends React.Component {
this.updateMarkdown = this.updateMarkdown.bind(this);
}
- onImageDrop(file) {
- // This is where you would upload your files to whatever storage you are using
- // You just need to return a promise with the original filename and the url of the uploaded file
-
- return new Promise((resolve) => {
- setTimeout(() => {
- resolve({
- filename: file.name,
- url: 'http://images.freeimages.com/images/previews/b56/hands-2-ok-hand-1241594.jpg',
- });
- }, 3000);
- });
- }
-
updateMarkdown(event) {
this.setState({ markdown: event.target.value });
}
@@ -64,7 +50,6 @@ class App extends React.Component {
);
}
@@ -77,7 +62,6 @@ ReactDOM.render(, document.getElementById('app'));
* value (*string*) - the raw markdown that will be converted to html (**required**)
* onChange (*function*) - called when a change is made (**required**)
-* onImageDrop (*function*) - called per image dropped on the textarea
* options (*object*) - the options for remarkable (see [here](https://github.com/jonschlinkert/remarkable#options)) (default: { })
## Styles
diff --git a/__tests__/src/index-test.js b/__tests__/src/index-test.js
index cc7d289..0bde2c6 100644
--- a/__tests__/src/index-test.js
+++ b/__tests__/src/index-test.js
@@ -10,159 +10,23 @@ import MarkdownEditor from '../../src';
let markdownEditor;
const value = '';
-const validFile = [{ type: 'image/jpeg', name: 'image' }];
-const invalidFile = [{ type: 'text/markdown', name: 'markdown' }];
-const uploadedImage = { url: 'url', filename: 'image' };
const onChangeMock = jest.genMockFunction();
-const onImageDropMock = jest.genMockFunction();
-function generateMarkdownEditor(includeOnDropImage = false) {
- const markup = includeOnDropImage ?
- :
- ;
-
- return TestUtils.renderIntoDocument(markup);
-}
-
-function simulateDrop(files, useDataTransfer = true) {
- TestUtils.Simulate.drop(
- TestUtils.findRenderedDOMComponentWithTag(markdownEditor, 'TextArea'),
- { [useDataTransfer ? 'dataTransfer' : 'target']: { files } }
- );
+function generateMarkdownEditor() {
+ return TestUtils.renderIntoDocument();
}
describe('MarkdownEditor', () => {
beforeEach(() => {
markdownEditor = generateMarkdownEditor();
onChangeMock.mockClear();
- onImageDropMock.mockClear();
});
- it('renders', () => {
+ it('renders correctly', () => {
const markdownEditorNode = ReactDOM.findDOMNode(markdownEditor);
expect(markdownEditorNode).toBeDefined();
expect(markdownEditorNode).not.toBe(null);
-
- expect(markdownEditor.state.draggingOver).toBe(false);
- });
-
- describe('onDragEnter', () => {
- it('sets draggingOver to true', () => {
- expect(markdownEditor.state.draggingOver).toBe(false);
-
- TestUtils.Simulate.dragEnter(TestUtils.findRenderedDOMComponentWithTag(markdownEditor, 'TextArea'));
-
- expect(markdownEditor.state.draggingOver).toBe(true);
- });
- });
-
- describe('onDragLeave', () => {
- it('sets draggingOver to false', () => {
- markdownEditor.setState({ draggingOver: true });
-
- TestUtils.Simulate.dragLeave(TestUtils.findRenderedDOMComponentWithTag(markdownEditor, 'TextArea'));
-
- expect(markdownEditor.state.draggingOver).toBe(false);
- });
- });
-
- describe('onDrop', () => {
- it('sets draggingOver to false', () => {
- markdownEditor.setState({ draggingOver: true });
-
- simulateDrop(validFile);
-
- expect(markdownEditor.state.draggingOver).toBe(false);
- });
-
- describe('valid images, but no onImageDrop prop passed', () => {
- it('does not call onChange', () => {
- expect(onChangeMock).not.toBeCalled();
-
- simulateDrop(validFile);
-
- expect(onChangeMock).not.toBeCalled();
- });
- });
-
- describe('onImageDrop prop passed', () => {
- beforeEach(() => {
- markdownEditor = generateMarkdownEditor(true);
-
- expect(onChangeMock).not.toBeCalled();
- expect(onImageDropMock).not.toBeCalled();
- });
-
- describe('invalid files', () => {
- afterEach(() => {
- expect(onChangeMock).not.toBeCalled();
- expect(onImageDropMock).not.toBeCalled();
- });
-
- describe('no files passed', () => {
- it('does not call onChange or onImageDrop', () => {
- simulateDrop([]);
- });
- });
-
- describe('no images passed', () => {
- it('does not call onChange or onImageDrop', () => {
- simulateDrop(invalidFile);
- });
- });
- });
-
- describe('invalid response from onImageDrop', () => {
- afterEach(() => {
- simulateDrop(validFile);
-
- expect(onChangeMock.mock.calls.length).toBe(1);
- expect(onChangeMock).toBeCalledWith({ target: { value: '\n![uploading image...]()' } });
-
- expect(onImageDropMock.mock.calls.length).toBe(1);
- expect(onImageDropMock).toBeCalledWith(validFile[0]);
- });
-
- describe('no filename', () => {
- it('does not call onChange twice', () => {
- onImageDropMock.mockReturnValueOnce({ url: 'url' });
- });
- });
-
- describe('no url', () => {
- it('does not call onChange twice', () => {
- onImageDropMock.mockReturnValueOnce({ filename: 'filename' });
- });
- });
- });
-
- describe('one image passed', () => {
- beforeEach(() => {
- onImageDropMock.mockReturnValueOnce(uploadedImage);
- });
-
- afterEach(() => {
- // TODO: This should be two calls but having an issue with promises
- expect(onChangeMock.mock.calls.length).toBe(1);
- expect(onChangeMock).toBeCalledWith({ target: { value: '\n![uploading image...]()' } });
- // expect(onChangeMock).toBeCalledWith({ target: { value: '\n![image](url)' } });
-
- expect(onImageDropMock.mock.calls.length).toBe(1);
- expect(onImageDropMock).toBeCalledWith(validFile[0]);
- });
-
- it('calls onChange and onImageDrop', () => {
- simulateDrop(validFile);
- });
-
- describe('one image passed with event.target.files', () => {
- it('calls onChange and onImageDrop', () => {
- simulateDrop(validFile, false);
- });
- });
- });
- });
});
});
diff --git a/src/index.js b/src/index.js
index 8dbbe91..ada23fe 100644
--- a/src/index.js
+++ b/src/index.js
@@ -2,15 +2,10 @@ import React from 'react';
import MarkdownRenderer from 'react-markdown-renderer';
import TextArea from 'react-textarea-autosize';
-const imageType = /^image\//;
-const placeholderTemplate = (filename) => `![uploading ${filename}...]()`;
-const uploadedTemplate = ({ filename, url }) => `![${filename}](${url})`;
-
export default class MarkdownEditor extends React.Component {
static propTypes = {
value: React.PropTypes.string.isRequired,
onChange: React.PropTypes.func.isRequired,
- onImageDrop: React.PropTypes.func,
options: React.PropTypes.object,
};
@@ -18,79 +13,14 @@ export default class MarkdownEditor extends React.Component {
options: {},
};
- state = {
- draggingOver: false,
- };
-
- onDragEnter = () => {
- this.setState({ draggingOver: true });
- };
-
- onDragLeave = () => {
- this.setState({ draggingOver: false });
- };
-
- onImageDrop = (event) => {
- event.preventDefault();
-
- this.setState({ draggingOver: false });
-
- if (!this.props.onImageDrop) {
- return;
- }
-
- const files = event.dataTransfer ? event.dataTransfer.files : event.target.files;
- const filesArray = [...files];
- const images = filesArray.filter(o => imageType.test(o.type));
-
- if (images.length === 0) {
- return;
- }
-
- const imageFileNames = images.map(o => placeholderTemplate(o.name));
- const imagePlaceholders = imageFileNames.join('\n');
-
- this.props.onChange({
- target: {
- value: `${this.props.value}\n${imagePlaceholders}`,
- },
- });
-
- for (const image of images) {
- Promise
- .resolve(this.props.onImageDrop(image))
- .then(({ filename, url }) => {
- if (!filename || !url) {
- return;
- }
-
- const templateString = placeholderTemplate(filename);
- const uploadedString = uploadedTemplate({ filename, url });
- const value = this.props.value.replace(templateString, uploadedString);
-
- this.props.onChange({
- target: {
- value,
- },
- });
- });
- }
- };
-
render() {
- let textAreaClassName = 'markdown-editor__textarea';
-
- if (this.state.draggingOver) {
- textAreaClassName += ' markdown-editor__textarea--dragover';
- }
-
return (