Skip to content
This repository has been archived by the owner on Feb 6, 2023. It is now read-only.

Export DraftPasteProcessor, or better access to its methods #55

Closed
jasonphillips opened this issue Feb 23, 2016 · 17 comments
Closed

Export DraftPasteProcessor, or better access to its methods #55

jasonphillips opened this issue Feb 23, 2016 · 17 comments

Comments

@jasonphillips
Copy link

For use cases in which I have fragments of pre-existing HTML that I need to load into an editor as the initial content, my impression is that I'd need to make use of the built-in DraftPasteProcessor that is part of the paste handling.

Something like this is working for me:

import Draft from 'draft-js';

const {Editor, EditorState, RichUtils, ContentState} = Draft;
import DraftPasteProcessor from 'draft-js/lib/DraftPasteProcessor';

const htmlFragment = '<div><p>Hello <b>world!</b></p><ul><li>again</li></ul></div>';

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

    const processedHTML = DraftPasteProcessor.processHTML(htmlFragment);
    const initialState = ContentState.createFromBlockArray(processedHTML);

    this.state = {editorState: EditorState.createWithContent(initialState)};

But it would appear that DraftPasteProcessor isn't exported along with the built package, so the import syntax is less than ideal, and I cannot use it if including only the dist file on the front-end.

Is there a better method for loading pre-existing HTML content, or could the paste-cleaning tools be included as part of the exported dist?

@hellendag
Copy link

Yep, this makes sense. We hadn't needed this since we've never needed to initialize the editor from HTML at FB, but I certainly see the usefulness.

Since your use case demonstrates that HTML-to-BlockMap is relevant outside of paste behavior, I should probably even rename the utility. (It should also export a single function. I want to remove processText from this module, since it's independent of anything else happening in the module.)

Then the utility could be exported from the top-level module along with the convert functions.

@hellendag
Copy link

cc @CLowbrow

@mitermayer
Copy link
Contributor

This would be a great to have, would make easier on the migration process from other text editors specially when there is already saved content

@dustin-H
Copy link
Contributor

+1

@jasonphillips
Copy link
Author

On a related note, at present the pasteProcessor relies on a browser implementation at two points (expects global document object, and global HTMLEntity class). I was testing a process of converting existing HTML content into draft-ready objects on the server and quickly ran into this limitation.

One can of course get around it with something like jsdom:

import jsdom from 'jsdom';

let window = jsdom.jsdom().defaultView;
global.document = window.document;
global.HTMLElement = window.HTMLElement;

import DraftPasteProcessor from 'draft-js/lib/DraftPasteProcessor';
DraftPasteProcessor.processHTML(...) //etc

That suffices for my conversion process on the server for now, though I wondered whether a tighter module for converting HTML to draft content without a full browser / document implementation might be worth having.

@mitermayer
Copy link
Contributor

any PR's on the way for this feature ?

@CLowbrow
Copy link
Contributor

Yep I'm going to do this sometime this week.

@CLowbrow
Copy link
Contributor

CLowbrow commented Mar 1, 2016

As an exploration I wrote something that exposes the paste handler at the top level with an api that's something like:

import Draft from 'draft-js';
const {getBlocksFromHTML, getSafeBodyFromHTML} = Draft;

// getSafeBodyFromHTML is how we generate a dom tree that won't auto-run JS in the browser
let myBlocks = getBlocksFromHTML('<p> hello! </p>', getSafeBodyFromHTML);

This add two things to the main Draft object, which I don't like so much, but I feel like if I don't expose our internal way of generating the dom tree I'm setting people up to do this in a way that isn't secure in the browser. (I'm putting that second argument in getBlocksFromHTML so that people can write a JSDom generator, for example, and plug it in).

It might be best to put these things draft-js/lib/ so as not to make Draft super complicated.

Thoughts?

@jamonholmgren
Copy link

That is exactly what we also need, @CLowbrow.

@jasonphillips
Copy link
Author

That approach looks good, and particularly the helpful option to pass a custom getSafeBody function so that I can use jsdom or something similar on the server. I might suggest that this second argument just default to the internal getSafeBodyFromHTML when not provided, so that users doing this in the browser have no need to worry about that complication, but either way it seems very reasonable to me.

ghost pushed a commit that referenced this issue Mar 10, 2016
Summary:Optional second parameter to pass in a function that will generate a dom element from whichever implementation.

Should help with #55
Closes #174

Reviewed By: hellendag

Differential Revision: D3023635

fb-gh-sync-id: 71b83c05610279d67c6e84f29565ed645bc4be30
shipit-source-id: 71b83c05610279d67c6e84f29565ed645bc4be30
@lincolndbryant
Copy link

Thanks for looking into this. We're still blocked from adopting DraftJS due to this, a release would be awesome. :)

@omerts
Copy link

omerts commented Jul 19, 2016

There is now a convertFromHtml method so initializing with default html could be done like:

const {Editor, EditorState, ContentState, convertFromHTML} = Draft;

const processedHTML = convertFromHTML('<div><p>Hello <b>world!</b></p><ul><li>again</li></ul></div>');
class PlainTextEditorExample extends React.Component {
  constructor(props) {
    super(props);

    const initialState = ContentState.createFromBlockArray(processedHTML);

    this.state = {editorState: EditorState.createWithContent(initialState)};
...

@akshaygoyal88
Copy link

@omerts
Hi,
This do not works if html contains img tag.

@hobenkr88
Copy link

hobenkr88 commented Dec 28, 2016

Hey @akshaygoyal88 , I'm having the same trouble with img tags being stripped (as are <hr /> tags). Were you able to find a workaround? I tried extending the block render map. This seems to work for defining new tags if you wanted to extend html using the web components (for example, polyfills like polymer and xtags), but it seems there's some distinction between existing html tags and custom ones.

I realize i could emulate a horizontal rule and image relatively simply, but part of me cries at this thought since a large part of what thrilled me about draft was how it fixed contenteditable (allowing for more semantic WYSIWYG).

As a side note, since this thread seems to address some of what FB didn't intend with this library, I'd like to bring up what might be a somewhat strange use-case, but mabe not all that uncommon.

I would kind of like to use draft as a means to edit content for site where draft isn't used to render the content. For this it would be desirable to save the content directly as HTML rather than in a raw format as is kind of suggested by the draft js docs. I understand the motivation for the convertToRaw means of storage. It is certainly appealing, but i also consider storing a page without dependency on a js library a valuable attribute.

Seeing as you've addressed the worthiness of converting HTML to a block array, would you consider adding the conversion of a block array to HTML as part of the core? Please forgive me it I've overlooked where this functionality already exists, but as far as I can tell, it's been filled in by some 3rd party libraries (they do the job well, but add their own level of configuration, and it would be nice to see this as part of the core library).

I recognize that this library isn't going away anytime soon, so storing as raw is not really a practical issue, but I would love to see the ability to convert back to HTML. What those of you at FB have created and opened up to the open source community is really great. That said, ideas on the internet are expressed in HTML.

Are there any plans to support converting a raw state back to HTML? It's supported relatively well already through related libraries, but is there any thought to support this functionality?

Thanks for sharing the amazing work you're doing and sharing :)

@akshaygoyal88
Copy link

akshaygoyal88 commented Dec 28, 2016

Hi @hobenkr88 ,
I have done it in this way while saving data in database I converted it to RAW as this

var content = JSON.stringify(convertToRaw(this.state.editorState.getCurrentContent()))

For Editing content
you can initialize editor with content as below code
this.setState({editorState:EditorState.createWithContent(convertFromRaw(JSON.parse(content)))})

For displaying data on html web page you can convert it to html as below code

<p dangerouslySetInnerHTML={{__html: stateToHTML(convertFromRaw(JSON.parse(content)))}}>

You need to import stateToHTML from plugin draft-js-export-html

Please let me know if this answers to your query or you can chat with me on akshay.goyal1008@gmail.com

@davidchang
Copy link
Contributor

yes, converting to HTML exists in the plugin @akshaygoyal88 mentioned and can basically be considered the canonical solution; there is an interest to keep the core Draft.js code as slim as possible. having a plugin ecosystem where consumers can cherry pick what they want is generally better than bloating the codebase with all sorts of functionality that isn't core and could live elsewhere.

while the web is expressed in HTML, native apps are not :)

@hobenkr88
Copy link

Thanks for the explanation :)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests