lokiuz/redraft

Add support for draft-js-plugins

mxstbr opened this issue · 7 comments

It'd be super rad if I could do

const renderer = {
  plugins: [mentionsPlugin]
}

or something to that effect. That way I basically wouldn't have to change anything about my setup between rendering a DraftJS plugins editor and redraft!

/cc @juliankrispel @nikgraf

Not so sure it should be part of redraft or maybe just a component with redraft as a dependency. It would accept plugins and other settings as props and would call redraft. Bit like this: https://github.com/draft-js-plugins/draft-js-plugins/blob/master/draft-js-plugins-editor/src/Editor/index.js

Still redraft would need to handle all those options ie the case from #33

I think redraft could actually handle these fairly well in core, because most of the plugins functionalities are really irrelevant for rendering. (they're only used for editing experience changes)

The only thing redraft would need to handle is nested definitions of five methods:

  1. decorators
  2. customStyleMap
  3. blockRendererMap
  4. blockStyleFn
  5. blockRendererFn

decorators

These are already handled fairly well, it would just need to be extended to handle an array of a mixture of normal and complex decorators. See #33.

customStyleMap

This is almost the same thing as redrafts inline option, that should just also support style objects: (maybe it already does?)

const renderer = {
  inline: {
    'BOLD': {
      fontWeight: 400,
    }
  }
}

blockRendererMap

This is almost the same thing as redrafts blocks option, that should just also support the blockRendererMap notation:

const renderer = {
  blocks: {
    'unstyled': {
        element: 'div',
        aliasedElements: ['p'],
        wrapper: <ul />
    }
  }
}

blockRendererFn and blockStyleFn are the only two I'm not sure how to handle since the provided methods might use the Immutable API under the hood, which redraft doesn't ship. Any ideas for those?

Exports for plugins would be super nice. I was thinking either to champion/recommend one of the exporters or build our own. I would like to avoid building our own :)

The problem is supporting same api that draft-js does, possibly while not adding it as a dependency.

The blockRendererFn and blockStyleFn both accept ContentBlock as an argument. While redraft already includes some basic stub for ContentBlock it would probably have to suport all of its methods to handle any plugin.

This is probably what would need to be ported from draft:
https://github.com/facebook/draft-js/blob/master/src/model/immutable/ContentBlock.js
https://github.com/facebook/draft-js/blob/master/src/model/immutable/findRangesImmutable.js
https://github.com/facebook/draft-js/blob/master/src/model/immutable/CharacterMetadata.js

My ideas so far:

  1. A wrapper around redraft not to bloat its current api and size (though some changes might still be required).
  2. Add Immutable.js, port whole ContentBlock and it's dependencies from draft-js
  3. Add some better error handling for missing methods in the ContentBlock stub and require users to pass a createContentBlock to redraft if any of the plugins require those methods.

Any other ideas?

I'd hate anything that requires Immutable by default, to be completely honest, but I definitely see the value in letting users choose to do so if they don't mind it.

What about having two different "modes" with two different sets of tradeoffs? Something like this:

  1. Slim/default mode: No createContentBlock method is provided, so the blockRenderFn and blockStyleFn of all plugins are ignored. Downside is that users might have to reimplement some parts of the plugins they use themselves, but that's still much better than having to basically rebuild all your plugins from scratch for rendering.
  2. Draft mode: A createContentBlock method is provided, so the blockRenderFn and blockStyleFn of plugins are used. Downside is you ship Draft and Immutable and bloat your bundle, but you can just your plugins as is.

Assuming good documentation around this, users could basically choose their "lazyness level": Are you lazy and don't want to reimplement nothing at the cost of bundle size? Use Draft mode. Are you not lazy and can reimplement some parts of some plugins to loose 100kb gzip bundle size? Use default mode.

Yeah ignoring the blockRenderFn and blockStyleFn sounds much better than calling them with a partial stub.

As for the rest:

  • decorators - fixing #33 should probably do
  • customStyleMap - that's mostly done will probably still require to provide a wrapper
  • blockRendererMap - probably needs to be similar to customStyleMap to allow a cb (ie. React.createElement) if we want to prevent shipping and coupling with React.

Went ahead and published the blockRendererMap support in 0.10.0 but this issue still needs some work.