Draft-js: Is it possible to call `convertFromHTML` on NodeJS?

Created on 9 Aug 2016  路  5Comments  路  Source: facebook/draft-js

Do you want to request a _feature_ or report a _bug_?

I want to migrate from my legacy html content in DB to Draft Raw Object.

var raw = converrtToRaw(ContentState.createFromBlockArray(convertFromHTML('<div></div>)))

What is the current behavior?

convertFromHTML requires document object.

ReferenceError: document is not defined
    at getSafeBodyFromHTML (/PROJECT_DIRECTORY/node_modules/draft-js/lib/getSafeBodyFromHTML.js:27:19)

If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem via https://jsfiddle.net or similar.

Run the below codes in Node

const djs = require('draft-js')
console.log(djs.convertFromHTML('<div></div>'))

What is the expected behavior?

return {blocks: [...], ....}

Which versions of Draft.js, and which browser / OS are affected by this issue? Did this work in previous versions of Draft.js?

Node v4.4.4

Most helpful comment

I was just playing around with a similar implementation.

Rather than executing within a synthetic dom, you can use the DOMBuilder input to the convertFromHTML, which is just an alias for convertFromHTMLtoContentBlocks and has this signature:

function convertFromHTMLtoContentBlocks(
    html: string,
    DOMBuilder: Function = getSafeBodyFromHTML,
    blockRenderMap?: DraftBlockRenderMap = DefaultDraftBlockRenderMap,
)

You can instantiate a simple DOMBuilder using jsdom like so:

function simpleDOMBuilder(html) {
    const {
        document,
        HTMLElement,
        HTMLAnchorElement,
    } = (new JSDOM(`<!DOCTYPE html>`)).window;

    global.HTMLElement = HTMLElement;
    global.HTMLAnchorElement = HTMLAnchorElement;

    const doc = document.implementation.createHTMLDocument('foo');
    doc.documentElement.innerHTML = html;
    const root = doc.getElementsByTagName('body')[0];
    return root;
}

Then pass this to convertFromHTML as an argument:

const blocks = convertFromHTML(html, simpleDOMBuilder);

Note: You still need to attach the variables HTMLElement and HTMLAnchorElement to global because they are used for type checking within convertFromHTMLtoContentBlocks.

All 5 comments

You could probably do this using jsdom.

It works.

Code:

const jsdom = require('jsdom')
jsdom.env('', function (err, window) {
  global.window = window
  global.document = window.document
  global.navigator = window.navigator
  global.HTMLElement = window.HTMLElement
  const djs = require('draft-js')
  console.log(djs.convertToRaw(djs.ContentState.createFromBlockArray(djs.convertFromHTML('<div>Hello</div>'))))
  process.exit(0)
})

Result:

{ entityMap: {},
  blocks:
   [ { key: '2scc',
       text: 'Hello',
       type: 'unstyled',
       depth: 0,
       inlineStyleRanges: [],
       entityRanges: [] } ] }

But, I should set global variables.
Is there any better way?

Cool! There is probably no better way, though you could create a separate VM context to load jsdom and Draft into if you don't want to pollute your main one. I don't see us making changes to support this better since convertFromHTML is designed around a browser implementation so I'm going to close this out.

I was just playing around with a similar implementation.

Rather than executing within a synthetic dom, you can use the DOMBuilder input to the convertFromHTML, which is just an alias for convertFromHTMLtoContentBlocks and has this signature:

function convertFromHTMLtoContentBlocks(
    html: string,
    DOMBuilder: Function = getSafeBodyFromHTML,
    blockRenderMap?: DraftBlockRenderMap = DefaultDraftBlockRenderMap,
)

You can instantiate a simple DOMBuilder using jsdom like so:

function simpleDOMBuilder(html) {
    const {
        document,
        HTMLElement,
        HTMLAnchorElement,
    } = (new JSDOM(`<!DOCTYPE html>`)).window;

    global.HTMLElement = HTMLElement;
    global.HTMLAnchorElement = HTMLAnchorElement;

    const doc = document.implementation.createHTMLDocument('foo');
    doc.documentElement.innerHTML = html;
    const root = doc.getElementsByTagName('body')[0];
    return root;
}

Then pass this to convertFromHTML as an argument:

const blocks = convertFromHTML(html, simpleDOMBuilder);

Note: You still need to attach the variables HTMLElement and HTMLAnchorElement to global because they are used for type checking within convertFromHTMLtoContentBlocks.

I am facing issue with span tags and also strong tags are also not working here is my code.
can any one help me for this

    const { JSDOM } = jsdom;
    const { window } = new JSDOM();
    const { document } = (new JSDOM(`<!DOCTYPE html>`)).window;
    global.document = document;
    global.navigator = window.navigator
    global.HTMLElement = window.HTMLElement
    const djs = require('draft-js')
    const html = '<p>Hey this <span>editor</span> rocks 馃榾</p>';
    const json=djs.convertToRaw(djs.ContentState.createFromBlockArray(djs.convertFromHTML(html)))
    console.log("Hello",json);
    var jQuery = require('jquery')(window);
Was this page helpful?
0 / 5 - 0 ratings