11

I have the following rich text document

{  
   "data":{},
   "content":[  
      {  
         "data":{},
         "content":[  
            {  
               "data":{},
               "marks":[ ],
               "value":"test",
               "nodeType":"text"
            }, {  
               "data":{},
               "marks":[],
               "value":"",
               "nodeType":"text"
            }
         ],
         "nodeType":"paragraph"
      },
      {  
         "data":{  
            "target":{  
               "sys":{  
                  "space":{  
                     "sys":{  
                        "type":"Link",
                        "linkType":"Space",
                        "id":"gedg1u5b0yz9"
                     }
                  },
                  "id":"2CzKe2pWvewCiek6w0yyoQ",
                  "type":"Asset",
                  "createdAt":"2019-01-07T22:37:55.473Z",
                  "updatedAt":"2019-01-07T22:37:55.473Z",
                  "environment":{  
                     "sys":{  
                        "id":"master",
                        "type":"Link",
                        "linkType":"Environment"
                     }
                  },
                  "revision":1,
                  "locale":"en-US"
               },
               "fields":{  
                  "title":"Test Image",
                  "description":"Image for testing",
                  "file":{  
                     "url":"//images.ctfassets.net/<hidden>/<hidden>/<hidden>/IMG_2878.JPG",
                     "details":{  
                        "size":3874595,
                        "image":{  
                           "width":5184,
                           "height":3456
                        }
                     },
                     "fileName":"IMG_2878.JPG",
                     "contentType":"image/jpeg"
                  }
               }
            }
         },
         "content":[],
         "nodeType":"embedded-asset-block"
      },
      {  
         "data":{},
         "content":[  
            {  
               "data":{},
               "marks":[],
               "value":"",
               "nodeType":"text"
            }
         ],
         "nodeType":"paragraph"
      }
   ],
   "nodeType":"document"
}

When I use documentToHtmlString (from here https://www.npmjs.com/package/@contentful/rich-text-html-renderer)

documentToHtmlString(document);

It outputs the following

<p>test</p><p></p>

Anyone know how to get it to output the img tag as well?

Seth McClaine
  • 9,142
  • 6
  • 38
  • 64

3 Answers3

13

From https://github.com/contentful/rich-text/issues/58#issuecomment-452236848

You need to specify how to render that You can find more about it here https://github.com/contentful/rich-text/tree/master/packages/rich-text-html-renderer#usage

import { BLOCKS } from '@contentful/rich-text-types';
import { documentToHtmlString } from '@contentful/rich-text-html-renderer';

const options = {
  renderNode: {
    [BLOCKS.EMBEDDED_ENTRY]: (node) => `<custom-component>${customComponentRenderer(node)}</custom-component>`
  }
}

documentToHtmlString(document, options);

My specific resolution was:

const options = {
    renderNode: {
        [BLOCKS.EMBEDDED_ASSET]: ({ data: { target: { fields }}}) =>
            `<img src="${fields.file.url}" height="${fields.file.details.image.height}" width="${fields.file.details.image.width}" alt="${fields.description}"/>`,
    },
};
Ben Winding
  • 10,208
  • 4
  • 80
  • 67
Seth McClaine
  • 9,142
  • 6
  • 38
  • 64
1

This is the original answer and hardcoded dynamic values, I hope it can help the reader to have an immediate answer to the specific problem:

let options = {
  renderNode: {
    'embedded-asset-block': (node) =>
      `<img class="img-fluid" src="${node.data.target.fields.file.url}"/>`
  }
}
let bodyHTML = body ? documentToHtmlString(body, options) : ''
Domenico Zinzi
  • 954
  • 10
  • 18
0
const options = {
    renderNode: {
        [BLOCKS.EMBEDDED_ASSET]: ({ data: { target: { fields }}}) =>
        <div dangerouslySetInnerHTML={{__html: `<img src="${fields.file['en-GB'].url}" alt="${fields.title['en-GB']}"/>`}} />,
    },
};

I found i needed to set dangerouslySetInnerHTML for it to render properly in the browser.

Florian
  • 2,796
  • 1
  • 15
  • 25
David R
  • 173
  • 8
  • I think thats because you are wrapping the image with a div, and I'm still not necessarily sure that you need it. – Seth McClaine Jan 30 '20 at 16:52
  • it was rendering the url path as a string and not html, not sure there is another way to render without the div, for reference - https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml – David R Jan 31 '20 at 17:12