Code Monkey home page Code Monkey logo

medium-draft's Introduction

Latest development is going on in this branch.

medium-draft - demo

npm version Build Status

A medium like rich text editor built upon draft-js with an emphasis on eliminating mouse usage by adding relevant keyboard shortcuts.

Documentation in progress.

Install the beta version using

npm install medium-draft@beta

Features

  • Focus on keyboard shortcuts and auto transform of text blocks.
  • Image addition with support for rich text captioning.
  • Minimize mouse usage.
  • Autolists.
  • Proper handling of RETURN presses.
  • It also has implementations of some custom blocks like:
    • caption - Can be used as a caption for media blocks like image or video instead of nested draft-js instances for simplicity.
    • block-quote-caption - Caption for blockquotes.
    • todo - Todo text with a checkbox.
  • Easily customizable toolbar via toolbarConfig for the following block and inline styles. Defaults to all. Case sensitive.
    • block: ['ordered-list-item', 'unordered-list-item', 'blockquote', 'header-three', 'todo']
    • inline: ['BOLD', 'ITALIC', 'UNDERLINE', 'hyperlink', 'HIGHLIGHT']
Following are the keyboard shortcuts to toggle block types (Alt and CTRL for Windows/Linux and Option and Command for OSX)
  • Alt/Option +

    • 1 - Toggle Ordered list item
    • * - Toggle Unordered list item
    • # - Toggle Header-three.
    • < - Toggle Caption block.
    • > - Toggle unstyled or paragraph block.
    • H - Highlight selection.
Other Shortcuts
  • CMD/CTRL + K -> Add Link
  • CMD/CTRL + SHIFT + K -> Remove link if cursor is inside a word with link.
Editor level commands

These commands are not a part of the core editor but have been implemented in the example code that uses the medium-draft editor.

  • Command/CTRL + S - Save current data to localstorage.
  • Alt + Shift + L - Load previously saved data from localstorage.
Special characters while typing: While typing in an empty block, if the content matches one of the following, that particular block's type and look will be changed to the corresponding block specified below
  • -- - If current block is blockquote, it will be changed to block-quote-caption, else caption.
  • *. (An asterisk and a period) - unordered-list-item.
  • *<SPACE> (An asterisk and a space) - unordered-list-item.
  • -<SPACE> (A hyphen and a space) - unordered-list-item.
  • 1. (The number 1 and a period) - unordered-list-item.
  • ## - header-two.
  • [] - todo.
  • == - unstyled.

Installation

  • npm.
    • npm install medium-draft.
    • import Editor from 'medium-draft'
  • Browser
    • Include <link rel="stylesheet" type="text/css" href="https://unpkg.com/medium-draft/dist/medium-draft.css"> in <head>
    • Include <script src="https://unpkg.com/medium-draft/dist/medium-draft.js"></script>. medium-draft is available in the global object as MediumDraft.

Usage

medium-draft sits on top of draft-js with some built in functionalities and blocks. Its API is almost the same as that of draft-js. You can take a look at the demo editor's code to see the implementation.

CSS

Include the css that comes with the library in your HTML -

<link rel="stylesheet" type="text/css" href="https://unpkg.com/medium-draft/dist/medium-draft.css">

If you are using webpack for bundling, you can import the CSS like this in your JS code

import 'medium-draft/lib/index.css';

If you are using sideButtons, you will also need to include the css for font-awesome -

<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.6.1/css/font-awesome.min.css">

or something equivalent.

JS (ES6)

At the minimum, you need to provide editorState and onChange props, the same as draft-js.

import React from 'react';
import ReactDOM from 'react-dom';

// if using webpack
// import 'medium-draft/lib/index.css';

import {
  Editor,
  createEditorState,
} from 'medium-draft';

class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      editorState: createEditorState(), // for empty content
    };

    /*
    this.state = {
      editorState: createEditorState(data), // with content
    };
    */

    this.onChange = (editorState) => {
      this.setState({ editorState });
    };

    this.refsEditor = React.createRef();

  }

  componentDidMount() {
    this.refsEditor.current.focus();
  }

  render() {
    const { editorState } = this.state;
    return (
      <Editor
        ref={this.refsEditor}
        editorState={editorState}
        onChange={this.onChange} />
    );
  }
};

ReactDOM.render(
  <App />,
  document.getElementById('app')
);

Customizing side buttons

medium-draft's Editor accepts a prop called sideButtons. By default, there is only one (image) button, but you can add more. The sideButtons prop must be an array of objects with each object having the following signature:

{
  "title": "unique-button-name",
  "component": ButtonComponent
}

For ex:

{
  "title": "Image",
  "component": ImageSideButton
}

Example code:

Right now, the image button simply adds an image inside the editor using URL.createObjectURL. But if you would like to first upload the image to your server and then add that image to the editor, you can follow one of the 2 methods:

  1. Either extend the default ImageSideButton component that comes with medium-draft.

  2. Or create your own component with the complete functionality yourself.

For simplicity, we will follow the first method. If you study the implementation of ImageSideButton, you will see an onChange method that receives the file chooser event where the seleced files are available as event.target.files. We will simply override this method as we don't want to customize anything else. Also note that each side button component receives getEditorState function (returns the draft editorState), setEditorState(newEditorState) function (sets the new editorState) and close function which you need to call manually to close the side buttons list:

import React from 'react';
import {
  ImageSideButton,
  Block,
  addNewBlock,
  createEditorState,
  Editor,
} from 'medium-draft';
import 'isomorphic-fetch';

class CustomImageSideButton extends ImageSideButton {

  /*
  We will only check for first file and also whether
  it is an image or not.
  */
  onChange(e) {
    const file = e.target.files[0];
    if (file.type.indexOf('image/') === 0) {
      // This is a post request to server endpoint with image as `image`
      const formData = new FormData();
      formData.append('image', file);
      fetch('/your-server-endpoint', {
        method: 'POST',
        body: formData,
      }).then((response) => {
        if (response.status === 200) {
          // Assuming server responds with
          // `{ "url": "http://example-cdn.com/image.jpg"}`
          return response.json().then(data => {
            if (data.url) {
              this.props.setEditorState(addNewBlock(
                this.props.getEditorState(),
                Block.IMAGE, {
                  src: data.url,
                }
              ));
            }
          });
        }
      });
    }
    this.props.close();
  }

}

// Now pass this component instead of default prop to Editor example above.
class App extends React.Component {
  constructor(props) {
    super(props);

    this.sideButtons = [{
      title: 'Image',
      component: CustomImageSideButton,
    }];

    this.state = {
      editorState: createEditorState(), // for empty content
    };

    /*
    this.state = {
      editorState: createEditorState(data), // with content
    };
    */

    this.onChange = (editorState) => {
      this.setState({ editorState });
    };

    this.refsEditor = React.createRef()

  }

  componentDidMount() {
    this.refsEditor.current.focus();
  }

  render() {
    const { editorState } = this.state;
    return (
      <Editor
        ref={this.refsEditor}
        editorState={editorState}
        onChange={this.onChange}
        sideButtons={this.sideButtons}
      />
    );
  }
};

Removing side buttons

To remove the side buttons entirely, so that the circular add button never appears, just pass an empty array:

sideButtons={[]}

Customizing toolbar

There are three props you can use to customize the buttons in the toolbar that appears whenever you select text within the editor:

  • blockButtons
  • inlineButtons
  • toolbarConfig

The default block-level editor buttons are ['header-three', 'unordered-list-item', 'ordered-list-item', 'blockquote', 'todo'], and the default inline editor buttons ['BOLD', 'ITALIC', 'UNDERLINE', 'HIGHLIGHT', 'hyperlink'].

For example, if you want to keep the default block buttons and add a few more, you can do something like the following:

import { BLOCK_BUTTONS } from 'medium-draft';

const blockButtons = [{
    label: 'H1',
    style: 'header-one',
    icon: 'header',
    description: 'Heading 1',
  },
  {
    label: 'H2',
    style: 'header-two',
    icon: 'header',
    description: 'Heading 2',
}].concat(BLOCK_BUTTONS);

// in your component
<Editor blockButtons={blockButtons} ... />

If you want to remove some buttons or reorder them, you could use functions like array.slice on the default BLOCK_BUTTONS and INLINE_BUTTONS, but this is probably more trouble than it's worth.

For this purpose it's better to use the toolbarConfig prop:

// custom ordering for block and inline buttons, and removes some buttons
const toolbarConfig = {
  block: ['unordered-list-item', 'header-one', 'header-three'],
  inline: ['BOLD', 'UNDERLINE', 'hyperlink'],
}

<Editor toolbarConfig={toolbarConfig} ... />

The strings inside the block and inline arrays must match the style attribute inside blockButtons and inlineButtons arrays.

To summarize: if you need add, remove, and reorder buttons, it's probably easiest to use blockButtons, inlineButtons, and toolbarConfig together.

Supply Your Own Toolbar

If the toolbar customization props aren't sufficient to get the behavior you want, you can inject your own toolbar with the ToolbarComponent prop.

This pattern is called component injection. Your ToolbarComponent receives the same props as the default toolbar.

If you want to write your own toolbar component, a good place to start is with the default component.

Render data to HTML

The feature to export HTML is available from version 0.4.1 onwards.

medium-draft uses draft-convert (which in turn uses react-dom-server) to render draft-js's editorState to HTML.

The exporter is not a part of the core library. If you want to use medium-draft-exporter, follow these steps -

Browserify/webpack

  • npm install draft-convert.

draft-convert is part of peerDependencies of medium-draft.

Code
  import mediumDraftExporter from 'medium-draft/lib/exporter';
  const editorState = /* your draft editorState */;
  const renderedHTML = mediumDraftExporter(editorState.getCurrentContent());
  /* Use renderedHTML */

Browser

  • Add the following scripts before your js code.
<script src="https://unpkg.com/[email protected]/dist/react-dom-server.min.js"></script>
<script src="https://unpkg.com/[email protected]/dist/draft-convert.min.js"></script>
<script src="https://unpkg.com/medium-draft/dist/medium-draft-exporter.js"></script>

The exporter is available as MediumDraftExporter global;

  • JS
var mediumDraftExporter = MediumDraftExporter.default;
const editorState = /* your draft editorState */;
const renderedHTML = mediumDraftExporter(editorState.getCurrentContent());
/* Use renderedHTML */

The medium-draft-exporter also comes with a preset CSS if you want to apply some basic styles to the rendered HTML.

  • In webpack, as part of your rendered HTML's page, use this-

    import 'medium-draft/lib/basic.css'
  • In browser, in your rendered html's page, you can include this stylesheet link

    <link rel="stylesheet" type="text/css" href="https://unpkg.com/medium-draft/dist/basic.css">

Load HTML exported using medium-draft-exporter to editorState

The feature to export HTML is available from version 0.5.3 onwards.

medium-draft uses draft-convert (which in turn uses react-dom-server) to render draft-js's editorState to HTML.

The importer is not a part of the core library. If you want to use medium-draft-importer, follow these steps -

Browserify/webpack

  • npm install draft-convert.

draft-convert is part of peerDependencies of medium-draft.

Code
  import { convertToRaw } from 'draft-js';
  import { createEditorState } from 'medium-draft';
  import mediumDraftImporter from 'medium-draft/lib/importer';

  const html = /* your previously exported html */;
  const editorState = createEditorState(convertToRaw(mediumDraftImporter(html)));
  // Use this editorState

Browser

  • Add the following scripts before your js code.
<script src="https://unpkg.com/[email protected]/dist/react-dom-server.min.js"></script>
<script src="https://unpkg.com/[email protected]/dist/draft-convert.min.js"></script>
<script src="https://unpkg.com/medium-draft/dist/medium-draft-importer.js"></script>

The importer is available as MediumDraftImporter global;

  • JS
  const { convertToRaw } = Draft;
  const { createEditorState } = MediumDraft;
  const mediumDraftImporter = MediumDraftImporter.default;
  const html = /* your previously exported html */;
  const editorState = createEditorState(convertToRaw(mediumDraftImporter(html)));
  // Use this editorState

Issues

  • Write an exporter to export draft data to HTML specifically for medium-draft.
  • Figure out a way to show placeholder text for empty image captions.
  • Currently, the toolbar that appears when text is selected needs to be fixed regarding its position in the viewport.

Developer

  • Clone this repo git clone https://github.com/brijeshb42/medium-draft.git.
  • Install node packages npm install react react-dom draft-convert && npm install.
  • Start local demo npm run dev. This will start a local server on port 8080.
  • Build using npm run build.

LICENSE

MIT

medium-draft's People

Contributors

anthonyjgrove avatar brijeshb42 avatar brycedorn avatar dependabot[bot] avatar flurryrush avatar hsource avatar j00nz avatar janaka120 avatar jaspersorrio avatar krstffr avatar kylebebak avatar marcelometal avatar marshevskyy avatar mckelvey avatar migeelesparty avatar odinuge avatar r17x avatar valthon avatar yukaii avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

medium-draft's Issues

how do I follow a link?

When I hover over a link, it shows the url for it in the pop-up. How do I open the link in a new browser tab?

Do I have to toggle the edit state to off? How do I do that? Sorry, I'm new to Draft-js

package.json missing react module

Hey there! I cloned the git repository but failed to build because react is not included in the package dependencies. I think its best to not have the react module installed globally

Cheers!

Export to markdown

This could be outputted to markdown using html2markdown libraries. Some content may may need to be output as pure html.

custom styles for the toolbar

We're wanting to add colour inline styles to the toolbar.

I've been reading the docs and going through the code, but I'm not completely clear how to create a custom style.. with I assume customStyleMap.

Ideally it would be great to add something like react-color.

Do we use customrenderer somehow?

Appreciate your guidance.

Component's children should not be mutated

Everytime I choose a type of list (UL or OL) from the tooltip options, I get

warning.js:36 Warning: Component's children should not be mutated.
in ol
in div (created by DraftEditorContents)
in DraftEditorContents (created by DraftEditor)
in div (created by DraftEditor)
in div (created by DraftEditor)
in div (created by DraftEditor)
in DraftEditor (created by MediumDraftEditor)
in div (created by MediumDraftEditor)
in div (created by MediumDraftEditor)
in MediumDraftEditor (created by CreateRecall)
in div (created by CreateRecall)
in CreateRecall (created by Playground)
in div (created by Playground)
in Playground (created by Relay(Playground))
in Relay(Playground) (created by RouterContext)
in StaticContainer (created by RouteContainer)
in RouteContainer (created by RouterContext)
in RouterContext (created by Router)
in StaticContainer (created by RelayReadyStateRenderer)
in RelayReadyStateRenderer (created by IsomorphicRenderer)
in IsomorphicRenderer (created by IsomorphicRelayRouterContext)
in IsomorphicRelayRouterContext (created by Router)
in ScrollBehaviorContext (created by Router)
in Router
in Provider
in AppContainer

Missing data node, in blocks object

I'm storing the content of the editor into my database as a JSON object, and I saw it had a missing blog data node.

Inspecting the demo app I saw the blocks object, has a node data, and it contains the src attribute with the URL to know what image will render at this point right?
screen shot 2016-12-03 at 11 21 59 pm

And using the example from the README, (I only upload the image first #40) I don't get the data node.

My editor state converted to raw looks like
screen shot 2016-12-03 at 11 26 17 pm

My doubt is, How can get the data node?, The issue is without this node when I restore my editor it doesn't know what image needs to be render.

How to get text from editorState?

I started using React about a week ago and am still adjusting to common patterns and conventions. You'll have to excuse me if this is completely obvious but editorState doesn't return any text content so far as I can tell...

Supplying custom stylemaps

Hi

I'd like to supply my own stylemap to the editor like so

import { Block, Inline } from '../constants';

const emailStyleMap = {
  [Block.H1]: {
    fontWeight: 300,
    ...  
  },
};

I pass this as a prop on the editor, but it does not get applied.

Any ideas?

Links not showing

When i add a link to any piece of text i don't see any style effects applied on that text. The link is saved correctly btw.

And more, is it possible to set the target attribute of the link?

Can't add ref to medium-draft

Why are you using strings as your ref for medium-draft in your example?

Isn't that legacy? Anyway, it doesn't work and this.refs is just an empty object.

How do I get this to work with the modern ref={(c) => this._input = c}

Server-side React render was discarded

Hey!
Thanks for this library first of all!

Seems it generates random ids for some elements and therefore discards server-side rendered code:

warning.js?85a7:36 Warning: React attempted to reuse markup in a container but the checksum was invalid. This generally means that you are using server rendering and the markup generated on the server was not what the client was expecting. React injected new markup to compensate which works but you have lost many of the benefits of server rendering. Instead, figure out why the markup being generated is different on the client or server:
 (client) er" id="placeholder-5s0dv" data-reactid=
 (server) er" id="placeholder-evdvv" data-reactid=

This is the place react complaining about in client side html:

<div class="DraftEditor-root" data-reactid="148">
    <div class="public-DraftEditorPlaceholder-root" data-reactid="149">
        <div class="public-DraftEditorPlaceholder-inner" id="placeholder-5s0dv" data-reactid="150">Write your story...</div>
    </div>
    <div class="DraftEditor-editorContainer" data-reactid="151">
        <div aria-describedby="placeholder-5s0dv" class="public-DraftEditor-content" contenteditable="true" role="textbox" spellcheck="true" style="outline:none;white-space:pre-wrap;word-wrap:break-word;" data-reactid="152">
            <div data-contents="true" data-reactid="153">
                <div class="md-block md-block-paragraph" data-block="true" data-editor="5s0dv" data-offset-key="f9aiq-0-0" data-reactid="154">
                    <div data-offset-key="f9aiq-0-0" class="public-DraftStyleDefault-block public-DraftStyleDefault-ltr" data-reactid="155"><span data-offset-key="f9aiq-0-0" data-reactid="156"><br data-text="true" data-reactid="157"></span></div>
                </div>
            </div>
        </div>
    </div>

I can dig into it some more to find exact place where this is happening, but i think it will be way easier for someone who knows this code. Please, let me know what do you, guys, think about this

Upload images to s3, and update the editor state.

Hi, I'm working with medium-draft, I'm using axios, and js aws sdk to upload files to s3

My first step is to get a signed URL and put my object file, at this point, all works well.

My challenge at this times is put the returned URL to my editor state, I tried differents ways to add it, and I can't figure why it's not working.

I read the medium-draft app, and the example app also and I only found one way to set the state, but it depends on a data context which involves the URL and SRC as attributes of data, That's right? image.js

So I created an anonymous function to get the context of this and data object at the same level, and I didn't get errors, the problem is I can't display the image over the editor.

The onChange functions looks like

onChange(e) {

    const file = e.target.files[0];

    if (file.type.indexOf('image/') === 0) {
      api 
      .get(`/getSignedUrl?folder=news&filename=${file.name}&filetype=${file.type}`)
      .then(response => {
        const signedUrl = response.data.url
        const options = {
          headers: {
            'Content-Type': file.type
          }
        }
        // put file to aws
        return axios.put(signedUrl, file, options)

      })
      .then(response => {
        // second step render the s3 url into the editor
        if (response.status === 200) {

           response.data = {
             url: response.request.responseURL.split("?")[0],
             src: response.request.responseURL.split("?")[0]
           }
           // anonymous function to get the data context, otherwise it fails with the error
           // ReferenceError: data is not defined
           const withData = data => {
             if (data.url) {
               const src = response.request.responseURL.split("?")[0]
               this.props.setEditorState(addNewBlock(
                 this.props.getEditorState(),
                 Block.IMAGE, {
                   src,
                 }
               ));
             }
           }
          console.log('data', response.data) 
         // Object {url: "https://s3.amazonaws.com/xideral.co/news/xideral.png", src: "https://s3.amazonaws.com/xideral.co/news/xideral.png"}
          return withData(response) 
        }

      })
      .catch(e => console.log('Error Uploading in blog', e))
    }
    this.props.close();
  }

What must have src, when you don't generate it as a blob file? like const src = URL.createObjectURL(file);? what kind of object is expecting Block.Image instead of src blob.

Using this component on mobile devices

There are a few issues we've come across when trying to use this component on mobile devices.

  1. the native toolbar (copy, paste) sits on top of this component's rich text editor tooltip

bs_realios_mobile_iphone 6s plus-9 0

  1. The tooltip is often partly off the screen

screen shot 2016-10-27 at 6 54 30 am

So we're thinking of disabling it outright for mobile devices. Is there a prop or something similar we can do to disable the tooltip?

Any other thoughts or suggestions? It looks like medium.com for instance doesn't allow rich text editing on mobile devices. You need to use the desktop or download their native app (which extends the native toolbar and keyboard).

Update to React 15.5

Apparently the component is not updated to the latest version of React.
Specifically in the new version React.PropTypes has been moved to its own package.
This triggers the following exception:
Accessing PropTypes via the main React package is deprecated. Use the prop-types package from npm instead

Can't save output to firebase

The issue here is that 'undefined' is not a type in JSON, and it's not something that Firebase can store.

When I try and save Editor state to firebase I get the following error message

Uncaught Error: Firebase.push failed: first argument contains undefined in property 'somePath.articles.editorState._immutable._map._root.entries.0.1._map._root.entries.0.1._map.__ownerID'

Strikethrough command

In the demo i see that the Link command(with the symbol #) has a tooltip mentioning 'strikethrough', which is clearly not true.

Anyway i really need the link and the strikethrough commands, any idea on how to get the latter?

Opposite of mediumDraftExporter (convertFromHTML)?

It seems that this library has provided an export function, but not an import function. draft-convert supports both. I'm attempting to implement the reverse (import), but I'm new to this library and draft-convert, so it's somewhat challenging. Do you have any plans to implement convertFromHTML?

how to add color-picker?

Hi, i want to add a clolor-picker component to toolbar, but I don't know how to add, can you give a suggest?

I have saw the drafts's example, that must set customStyleMap, but I have many many colors ,so I don't know how to add color-picker function.

thanks.

include preprocessed CSS file to change font-family?

Hi! I love your work and I am using it in my project. One problem though, the font-family is set and hardcoded in the index.css file. Meaning I have to go through the file and change every font-family statement. Is there anyway we can include the SASS or LESS file so we can add some variables for the font?

Like:

$font-sans-serif: Helvetica, sans-serif;
$font-serif: Georgia, serif;

Thank you!

Todo check boxes do not work on Firefox

This might be a bit trivial, but I noticed in the demo that the checkboxes weren't working on Firefox when I was testing it. I really like Medium-Draft and I was thinking of having my team integrate it into our platform, so I wanted to give you guys a heads up.

Thanks.

Is version 0.3.13 stable?

Hi

for some reason i had to reinstall all the node modules i'm using, to do that i use npm.
The version installed for medium-draft was 0.3.13 and apparently it did not work(seemed like the onChange event never fires).

After some investigation i went back to the version 0.3.12 and everything started working again.

What i wonder is how stable is that version, i don't even seem that tag on the releases.

Empty Block appears when dragging image or using EmbedSideButton

I have manipulated your examples code as little as possible but for these two cases, when drag and dropping an image and when embedding a video from the sidebuttons, and empty block is created by default before the img block. I can't delete it from the editor without deleting the image/video.

My handleDropped code looks like:

handleDroppedFiles(selection, files) {
    const file = files[0];
    if (file.type.indexOf('image/') === 0) {
      // const src = URL.createObjectURL(file);

      const formData = new FormData();
      formData.append('image', file, file.name);

      imageUpload(formData).then(path => {
        const src = path.path;

        this.onChange(addNewBlockAt(
          this.state.editorState,
          selection.getAnchorKey(),
          Block.IMAGE, {
            src,
          }
        ));
        return HANDLED;
      });
    }
    return NOT_HANDLED;
  }

This is how it looks now, I just create a formData to be able to add it to the body when making a POST request (imageUpload is basically the request) and then I get the path where the file is stored and putting in the Block.IMAGE, as it was before
I don't add any blocks or anything, I drag the image into the empty editor and this is the resulting dom:

<div class="md-block md-block-paragraph" data-block="true" data-editor="34ndg" data-offset-key="cct11-0-0">...</div>
<figure class="md-block md-block-image" data-block="true" data-editor="34ndg" data-offset-key="1j3bh-0-0">...</figure>

For the video embed I literally copy your examples EmbedSideButton.jsx and AtomicEmbedComponent.jsx.

Adding an image from the SideButton doesn't have this issue.

Any ideas? How could I debug this? Let me know if you need more code samples!
Thanks!

JSON.parse(mySavedEditorData) results in an error

I'm trying to load the editor with previously saved data (convertToRaw) but am getting the following error: VM123741:1 Uncaught SyntaxError: Unexpected token u in JSON at position 0

Note that I used the following to save to mongodb: convertToRaw(this.state.instructions.getCurrentContent())

Great job !

I integrated medium-draft in my Meteor project and I really love it, thanks (yes I know, it's not really an issue... ;) ).

Empty spaces above and below images

Is there a solution for getting rid of the the empty paragraph blocks above and below an image in the editor? What's the best way to deal with them?

<div class="md-block md-block-paragraph" data-block="true" data-editor="66e9a" data-offset-key="2vr7c-0-0"><div data-offset-key="2vr7c-0-0" class="public-DraftStyleDefault-block public-DraftStyleDefault-ltr"><span data-offset-key="2vr7c-0-0"><br data-text="true"></span></div></div>

OnChange event is called when the editor data is populated

I use a Ajax call to get the last data from the back end, the data flows to the component correctly.

What i also see is that the onChange event is called multiple times as the component data is populated.

I wonder if this is the expecting behavior, because with all the other components i use the onChange method is not triggered unless the user attempts to modify the component's value.

Uncaught TypeError: Cannot read property 'preventDefault' of undefined

Hi,

I am getting an error when I am trying to add picture:
addbutton.js:146 Uncaught TypeError: Cannot read property 'preventDefault' of undefined

I think when checking for prevent default, it would be nice to check for event itself too.

Also do you have any call to print it out as a html content for saving in db?

Placeholder

hi,

I'm trying to get a placeholder on my Editor with no success, what i did coming, from the draft js docs, is adding a placeholder property to the Editor component, unfortunately it doesn't work.

AddButton submits form

Hi,
If you use editor inside a form, the AddButton on the bottom for adding images behaves as submit button. Which means when I want to add image it submits the whole form. So it's my polite request, if possible, to change button in AddButton to type="button" so the button doesn't behave as a submit button.

convertFromRaw infinite loop when content has anchor tags

Hi

First off, awesome library - saves A TON of work.

However I've run into a problem. I persisting data to my DB as described in the wiki using

convertToRaw(this.state.editorState.getCurrentContent());

and then initializing it using

createEditorState(rawContent)

This works fine, unless there is any anchor tags in the content, in which case createEditorState's convertFromRaw enters an infinite loop

UPDATE:

Probably catching the error yields:

Unknown DraftEntity key.
    at invariant (eval at <anonymous> (http://localhost:3000/site.js:596:2), <anonymous>:38:15)
    at Object.get (eval at <anonymous> (http://localhost:3000/site.js:11838:2), <anonymous>:71:27)
    at eval (eval at <anonymous> (http://localhost:3000/site.js:12474:2), <anonymous>:53:30)
    at Array.forEach (native)
    at convertFromDraftStateToRaw (eval at <anonymous> (http://localhost:3000/site.js:12474:2), <anonymous>:52:14)
    at Composer.handleChange (eval at 2247 (http://localhost:3000/1.bf94ea2aa48f3cb3c814.hot-update.js:6:2), <anonymous>:224:42)
    at Composer.proxiedMethod (eval at <anonymous> (http://localhost:3000/site.js:2241:2), <anonymous>:44:30)
    at MediumDraftEditor._this.onChange (eval at <anonymous> (http://localhost:3000/site.js:14256:2), <anonymous>:86:19)
    at MediumDraftEditor.setLink (eval at <anonymous> (http://localhost:3000/site.js:14256:2), <anonymous>:146:12)
    at Toolbar.onKeyDown (eval at <anonymous> (http://localhost:3000/site.js:13608:2), <anonymous>:136:20)

Any ideas?

Toolbars not styled

Hey there!

I just found the project, and the demo is awesome. Really. Congrats! (:

I've almost successfully implemented it, but the editor and side toolbar renders like this:

style-mia

It applies the inline style and blocks if I press the buttons, but shouldn't it just show up when text selecting?

I've tried looking for a style that might be breaking it, but couldn't find anything.

Any clues what might be happening here?

Thanks!

Support Latex

First thing Awesome stuff.

Would be nice if that can support Latex.

Initialize editor with data

Hello,

The readme suggests passing data into the editor to initialize it:

 /*
    this.state = {
      editorState: createEditorState(data), // with content
    };
    */

How should we convert html into that data ?

Since you say you use draft-convert for export I figure that should work for import.

draft-convert docs:

let html = "<p class="md-block-unstyled">something something</p>";
// this gives a ContentState
const rawState = convertFromHTML(html);

// nope
createEditorState(rawState);

This is obviously not the type of object you are looking for. (Errors below)

I have also tried passing that ContentState directly to medium-draft <Editor editorState={rawState} />

errors:

QueryManager.js:227 Error in observer.next 
TypeError: Cannot read property 'map' of undefined
    at convertFromRawToDraftState (convertFromRawToDraftState.js:48)
    at createEditorState (content.js:27)
    at new TextEditor (TextEditor.js:99)
    at eval (createClassProxy.js:98)
    at instantiate (createClassProxy.js:106)
    at new TextEditor (eval at proxyClass (createClassProxy.js:NaN), <anonymous>:4:17)
    at eval (ReactCompositeComponent.js:295)
    at measureLifeCyclePerf (ReactCompositeComponent.js:75)
    at ReactCompositeComponentWrapper._constructComponentWithoutOwner (ReactCompositeComponent.js:294)
    at ReactCompositeComponentWrapper._constructComponent (ReactCompositeComponent.js:280)

function convertFromRawToDraftState(rawState) {
  var blocks = rawState.blocks;


rawState has ._map but no .blocks

ContentState
_map: Map
blockMap: (...)
length: (...)
selectionAfter: (...)
selectionBefore: (...)
__proto__: Record

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.