kadikraman / draftjs-md-converter

Converts content from Draft.js blocks to Markdown and vice versa.
https://kadikraman.github.io/draftjs-md-converter/
MIT License
145 stars 37 forks source link

Images ![undefined](undefined) #17

Closed El-Gregory closed 7 years ago

El-Gregory commented 7 years ago

Hi @kadikraman, so far draftjs-md-converter has been a real life saver but I'm having trouble having it convert images properly. When I look at the draft entities they are correct and displaying in draft correctly but are output as undefined when I convert to markdown. Have you seen this before?

Thanks in advance

kadikraman commented 7 years ago

Hi @El-Gregory ! Thanks, I'm glad it's been useful.

Would you be able to provide an example of the draft.js blocks that are being passed in? As in, an example of the argument you're giving to the draftjsToMd function that's outputting as ![undefined](undefined)?

El-Gregory commented 7 years ago

Thanks for the quick response @kadikraman . Here are the json stringified blocks and entities for a single image. I think the non atomic blocks are whitespace.

{"entityMap":{"0":{"type":"IMAGE","mutability":"MUTABLE","data":{"src":"http://invilla.services/wp-content/uploads/2014/01/7UP-330ml-CAN.jpg","height":"auto","width":"auto"}}},"blocks":[{"key":"fm1b8","text":"","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}},{"key":"ep7hi","text":" ","type":"atomic","depth":0,"inlineStyleRanges":[],"entityRanges":[{"offset":0,"length":1,"key":0}],"data":{}},{"key":"o4ap","text":"","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[],"data":{}}]}

Here is how I'm calling it.

const myMdDict = {
  BOLD: '**',
  STRIKETHROUGH: '~~',
  UNDERLINE: '__',
  CODE: '```'
};
const newMarkdown = draftjsToMd(editorState, myMdDict);

And this is what comes out.


![undefined](undefined)
kadikraman commented 7 years ago

@El-Gregory I've been able to replicate your issue. So the problem is that the data format for an image assumed by this library is:

{
  type: 'IMAGE',
  mutability: 'MUTABLE',
  data: {
    fileName: 'someName',
    url: 'http://invilla.services/wp-content/uploads/2014/01/7UP-330ml-CAN.jpg'
  }
}

which would produce ![someName](http://invilla.services/wp-content/uploads/2014/01/7UP-330ml-CAN.jpg)

whereas yours is:

{
  type: 'IMAGE',
  mutability: 'MUTABLE',
  data: {
    src: 'http://invilla.services/wp-content/uploads/2014/01/7UP-330ml-CAN.jpg'
  }
}

which produces ![undefined](undefined)

because fileName and url are not defined within the data object

How are you adding images? Is it an existing plugin or have you written your own?

El-Gregory commented 7 years ago

That helps enormously! I'm using react-draft-wysiwyg and it's photo plugin but thanks to your tip I found the offending code.

  addImage: Function = (src: string, height: string, width: string): void => {
    const { editorState, onChange } = this.props;
    const entityKey = editorState
      .getCurrentContent()
      .createEntity('IMAGE', 'MUTABLE', { src, height, width })
      .getLastCreatedEntityKey();
    const newEditorState = AtomicBlockUtils.insertAtomicBlock(
      editorState,
      entityKey,
      ' '
    );
    onChange(newEditorState);
    this.doCollapse();
  };

It sounds like I'll just need to add fileName and url. I need to tweak it to work with our uploader anyway so tweaking this should be no problem. I'll let the author know of the bug too.

Thanks so much!

kadikraman commented 7 years ago

@El-Gregory I think my library might be in the wrong here as I wrote my own image plugin. Looks like the draft-js-plugins version of a photo plugin also uses src. I think it should be possible for mine to support both is that helps?

Something like this:

Existing draftjs -> md

  data: {
    fileName: 'someName',
    url: 'http://invilla.services/wp-content/uploads/2014/01/7UP-330ml-CAN.jpg'
  }

returns ![someName](http://invilla.services/wp-content/uploads/2014/01/7UP-330ml-CAN.jpg)

Existing md -> draftjs

![someName](http://invilla.services/wp-content/uploads/2014/01/7UP-330ml-CAN.jpg) returns

  data: {
    fileName: 'someName',
    url: 'http://invilla.services/wp-content/uploads/2014/01/7UP-330ml-CAN.jpg',
    src: 'http://invilla.services/wp-content/uploads/2014/01/7UP-330ml-CAN.jpg'
  }

Yours draftjs -> md

  data: {
    src: 'http://invilla.services/wp-content/uploads/2014/01/7UP-330ml-CAN.jpg'
  }

returns ![](http://invilla.services/wp-content/uploads/2014/01/7UP-330ml-CAN.jpg)

Yours md -> draftjs

![](http://invilla.services/wp-content/uploads/2014/01/7UP-330ml-CAN.jpg) returns

  data: {
    fileName: '',
    url: 'http://invilla.services/wp-content/uploads/2014/01/7UP-330ml-CAN.jpg',
    src: 'http://invilla.services/wp-content/uploads/2014/01/7UP-330ml-CAN.jpg'
  }

So you'd have both src and url attributes and so any existing implementations would still work as well (yay for backwards compatibility).

El-Gregory commented 7 years ago

I love it!

On Apr 25, 2017 9:03 AM, "Kadi Kraman" notifications@github.com wrote:

@El-Gregory https://github.com/El-Gregory I think my library might be in the wrong here as I wrote my own image plugin. Looks like the draft-js-plugins version https://github.com/draft-js-plugins/draft-js-plugins/blob/master/draft-js-image-plugin/src/modifiers/addImage.js of a photo plugin also uses src. I think it should be possible for mine to support both is that helps?

Something like this: Existing draftjs -> md

data: { fileName: 'someName', url: 'http://invilla.services/wp-content/uploads/2014/01/7UP-330ml-CAN.jpg' }

returns someName Existing md -> draftjs

someName returns

data: { fileName: 'someName', url: 'http://invilla.services/wp-content/uploads/2014/01/7UP-330ml-CAN.jpg', src: 'http://invilla.services/wp-content/uploads/2014/01/7UP-330ml-CAN.jpg' }

Yours draftjs -> md

data: { src: 'http://invilla.services/wp-content/uploads/2014/01/7UP-330ml-CAN.jpg' }

returns Yours md -> draftjs

returns

data: { fileName: '', url: 'http://invilla.services/wp-content/uploads/2014/01/7UP-330ml-CAN.jpg', src: 'http://invilla.services/wp-content/uploads/2014/01/7UP-330ml-CAN.jpg' }

So you'd have both src and url attributes and so any existing implementations would still work as well (yay for backwards compatibility).

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/kadikraman/draftjs-md-converter/issues/17#issuecomment-297079092, or mute the thread https://github.com/notifications/unsubscribe-auth/AWDra4Qvf3KOJ-N-OvvLhiSgctgqh2usks5rzhkngaJpZM4NGmiB .

El-Gregory commented 7 years ago

It looks like there's an additional problem with the md -> draft code.

entityMap[entityKey] = {
      type: 'image',
      mutability: 'IMMUTABLE',
      data: {
        url: child.url,
        fileName: child.alt
      }
    };

Needed to be

entityMap[entityKey] = {
      type: 'IMAGE',
      mutability: 'MUTABLE',
      data: {
        url: child.url,
        fileName: child.alt,
        src: child.url
      }
    };

In order to display the image correctly in draft. The entity was there it just showed as a blank line.

I hope that helps.

kadikraman commented 7 years ago

@El-Gregory Could you try v0.1.2? Hopefully should be fixed there.

El-Gregory commented 7 years ago

Works great @kadikraman !!! Thanks soooooo much!