npm package: @haakonmb/markdown-draft-js
Description: Convert draftjs blocks to markdown using the marked library, and vice versa.
Author: Rose Robertson
Latest version: 3.1.0

**NOTICE** :
This is a fork of https://github.com/Rosey/markdown-draft-js to solve a time-sensitive issue. You will probably want to use the version created by Rosey rather than this one, since this package solves a very specific issue for me and probably wont see further independent development.

# Markdown draft js

A tool for converting [Draft.js](https://draftjs.org) [raw object](https://draftjs.org/docs/api-reference-data-conversion) to [markdown](https://daringfireball.net/projects/markdown/), and vice-versa.

**Looking for an example?** [There is a running example here](https://rosey.github.io/markdown-draft-js/)

### Markdown draft js vs other similar projects - what’s the story?

I started this project in 2016 because I was in need of a draft/markdown conversion tool that could handle custom entities, such as mentions, and the existing conversion tools out there didn’t support these slightly complex needs. I was also finding various bugs with the existing conversion tools and none of them seemed to be maintained, so I decided to write my own.

It’s now 2019 and the landscape has potentially changed! I don’t spend a ton of time keeping tabs on other draftjs markdown conversion tools out there, but I believe there are a few that are actively maintained and significantly more popular than this one, such as [draft-js-export-markdown](https://github.com/sstur/draft-js-utils/tree/master/packages/draft-js-export-markdown). Before choosing this project, I encourage you to do your research! This may still be the best tool for what you need, but it’s always worth being critical and looking at all your options 😃 Stability wise, I use markdown-draft-js in a production environment with over 10k monthly active users and it has served very well so far.

## Basic Usage

Please note: We recommend using a polyfill (like babel-polyfill) since we're using a bunch of modern array methods.

`draftToMarkdown` expects a [RAW Draft.js JS object](https://draftjs.org/docs/api-reference-data-conversion).

It returns a string of markdown.

```javascript
// First, import `draftToMarkdown`
import { draftToMarkdown } from 'markdown-draft-js';

var markdownString = draftToMarkdown(rawObject);
```

`markdownToDraft` expects a string containing markdown.

It returns a [RAW Draft.js JS object](https://draftjs.org/docs/api-reference-data-conversion).

```javascript
// First, import `draftToMarkdown`
import { markdownToDraft } from 'markdown-draft-js';

var rawObject = markdownToDraft(markdownString);
```

## Example

```javascript
[---]

import { draftToMarkdown, markdownToDraft } from 'markdown-draft-js';
import { EditorState, convertToRaw, convertFromRaw } from 'draft-js';

[---]

constructor(props) {
  super(props);

  // Convert input from markdown to draftjs state
  const markdownString = this.props.markdownString;
  const rawData = markdownToDraft(markdownString);
  const contentState = convertFromRaw(rawData);
  const newEditorState = EditorState.createWithContent(contentState);
  this.state = {
    editorState: newEditorState,
  };

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

    // Convert draftjs state to markdown
    const content = editorState.getCurrentContent();
    const rawObject = convertToRaw(content);
    const markdownString = draftToMarkdown(rawObject);

    // Do something with the markdown
  };
}

[---]
```

## Custom Values

In case you want to extend markdown’s functionality, you can. `draftToMarkdown` accepts an (optional) second `options` argument.

It takes two values: `styleItems` and `entityItems`. This is because of a distinction in draftjs between styles and entities. You can read more about them on [Draft’s documentation](https://draftjs.org/docs/api-reference-character-metadata).

Say I wanted to convert <span style="color: red">**red text**</span> from my Draft.js editor to a span with a red colour style. Unless I write a custom method for it, the markdown parser will ignore this special style, since it’s not a normal, pre-defined style. (An example of this style item is defined in one of the Draft.js [custom colours](https://github.com/facebook/draft-js/tree/master/examples/color) examples.)

However, I can pass in a custom renderer for the `red` style type, and then decide how I want it to be depicted in markdown. Since markdown parsers usually also accept HTML, in this example I’ll just have my custom renderer do a `span` with a red style. Here it is:

```javascript
var markdownString = draftToMarkdown(rawObject, {
  styleItems: {
    red: {
      open: function () {
        return '<span style="color: red">';
      },

      close: function () {
        return '</span>';
      }
    }
  }
});
```

`red` is the value of the `style` key in the raw object. The `open` method is what precedes the actual text, and `close` is what succeeds it.

Here’s another example, with a mention entity type -


```javascript
var markdownString = draftToMarkdown(rawObject, {
  entityItems: {
    mention: {
      open: function (entity) {
        return '<span class="mention-item" data-user-id="' + entity.data.id + '">';
      },

      close: function (entity) {
        return '</span>';
      }
    }
  }
});
```

Since entities can also contain additional custom information - in this case, the user’s id, an `entity` object is passed to the open and close methods so that you can use that information in your open/close text if you need to.

What if you wanted to go the opposite direction? markdownToDraft uses [Remarkable](https://github.com/jonschlinkert/remarkable) for defining custom markdown types.

In this case, you need to write a [remarkable plugin](https://github.com/jonschlinkert/remarkable/blob/master/docs/plugins.md) first and pass it in to `markdownToDraft` -

```javascript
var rawDraftJSObject = markdownToDraft(markdownString, {
  remarkablePlugins: [remarkableMentionPlugin],
  blockEntities: {
    mention_open: function (item) {
      return {
        type: "mention",
        mutability: "IMMUTABLE",
        data: {
          mention: {
            id: item.id,
            name: item.name
          }
        }
      };
    }
  }
});
```


## Additional options

### Remarkable options

Since this module uses Remarkable under the hood, you can also pass down preset and options for the Remarkable parser. Simply add the `remarkablePreset` or `remarkableOptions` property (or both of them) to your options object. For example, let's say you wanted to use the `commonmark` preset and parse html as well:

```javascript
var rawDraftJSObject = markdownToDraft(markdownString, {
  remarkablePreset: 'commonmark',
  remarkableOptions: {
    html: true
  }
});
```

#### Enabling / Disabling rules

It's possible to enable or disable specific rules. Remarkable categorizes them into three groups, every file represents a possible rule:

- [Inline](https://github.com/jonschlinkert/remarkable/tree/master/lib/rules_inline) (e.g. links, bold, italic)
- [Block](https://github.com/jonschlinkert/remarkable/tree/master/lib/rules_block) (e.g. tables, headings)
- [Core](https://github.com/jonschlinkert/remarkable/tree/master/lib/rules_core) (e.g. automatic link conversion or abbreviations)

```javascript
var rawDraftJSObject = markdownToDraft(markdownString, {
  remarkablePreset: 'commonmark',
  remarkableOptions: {
    disable: {
      inline: ['links', 'emphasis'],
      block: ['heading']
    },
    enable: {
      block: 'table',
      core: ['abbr']
    }
  }
});
```

The `table` rule is disabled by default but could be enabled like in the example above.

### More options

`preserveNewlines` can be passed in to preserve empty whitespace newlines. By default, markdown rules specify that blank whitespace is collapsed, but in the interest in maintaining 1:1 parity with draft appearance-wise, this option can be turned on if you like :)

NOTE: If you plan on passing the markdown to a 3rd party markdown parser, markdown default behaviour IS to strip additional newlines, so the HTML it generates will likely strip those newlines at that point.... Which is why this is an option disabled by default.

`escapeMarkdownCharacters` – by default this value is **true** and markdown characters (e.g. *~_`) typed directly into the editor by a user are escaped when converting from draft to markdown.

Setting this option to **false** will prevent those special characters from being escaped, so the markdown string it generates will remain in its “raw” form. What this means is that when the markdown is later converted back to draftjs or parsed by a different markdown tool, any user-entered markdown will be rendered AS markdown, and will not "match" what the user initially entered. (So if the user explicitly typed in `**hello**`, converting to markdown and back to draft it will be restored as **hello** instead of the original `**hello**`)

### FAQ

#### How do I get images to work?

For now, check out [this pull request](https://github.com/Rosey/markdown-draft-js/pull/49) and the discussion below. [this comment](https://github.com/Rosey/markdown-draft-js/pull/49#issuecomment-369682808) outlines how to get images working by writing a basic plugin for markdown-draft-js. The reason it’s not built into the library itself is because draftjs doesn’t support images out of the box, so there’s no standardized way of supporting them in the library that will work for everyone. In the future I hope to publish a plugin for people to quickly add image support if they need to, but I haven’t quite gotten there yet 🙂