From ad4c25122e871b1e4c97ce68fa5615288a5e9802 Mon Sep 17 00:00:00 2001 From: Jonathon Kelly Date: Sat, 28 Oct 2017 12:54:09 +0100 Subject: [PATCH] remove on drop image --- README.md | 18 +- __tests__/src/index-test.js | 142 +- src/index.js | 72 +- yarn.lock | 5470 +++++++++++++++++++++++++++++++++++ 4 files changed, 5475 insertions(+), 227 deletions(-) create mode 100644 yarn.lock 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 (

Markdown