paramander / contentful-rich-text-vue-renderer

Render Contentful Rich Text field using Vue
https://www.npmjs.com/package/contentful-rich-text-vue-renderer
MIT License
38 stars 12 forks source link

(Unrecognized node type) embedded-asset-block #50

Open SketchNI opened 1 year ago

SketchNI commented 1 year ago

Hi,

I'm getting a (Unrecognized node type) embedded-asset-block when trying to render content with embedded images.

I'm not even getting output in the browser console.

const embeddedAsset = (node, text) => {
    console.log(node);
    const image = node.data.target;
    return h('img', {
        src: `https://${image.fields.file.url}`,
        alt: image.fields.description
    }, image);
}

...

methods: {
    renderNodes() {
        return {
            [BLOCKS.EMBEDDED_ASSET]: embeddedAsset,
        }
    },
}
tolgap commented 1 year ago

@SketchNI Could you show me the entire RichText component in your template? I think there's something wrong in the usage of your renderNodes().

Btw, your PR fix only adds an img tag for EMBEDDED_ASSET in the default renderers. Some others might want to render images as <figure><img>, or even upload videos. So I think that change might be too opinionated.

SketchNI commented 1 year ago

I never thought about wrapping images in a <figure> or adding a caption.

I'd agree with you that this is opinionated as images are the only thing I need to render that's embedded.

Here is the rich text component.

<template>
   <RichTextRenderer :document="post.content" :markRenderers="renderMarks()" :nodeRenderers="renderNodes()" />
</template>

<script>

import RichTextRenderer from "@/Libraries/contentful-vue.js";
import { BLOCKS, INLINES, MARKS } from '@contentful/rich-text-types';
import { h } from "vue";

export default {
    name: "Show",

    props: ['post', 'url'],

    components: {
        RichTextRenderer
    },

    methods: {
        renderNodes() {
            return {
                [BLOCKS.EMBEDDED_ASSET]: (node, text) => {
                    const image = node.asset.fields;
                    return h('img', {
                        src: `https://${image.file.url}`,
                        alt: image.description
                    }, image);
                },
            }
        },

        renderMarks() {
            return {
                [MARKS.CODE]: (text) => {
                    return h('div', { class: 'not-prose' }, h('pre', { class: 'not-prose' }, h('code', text)));
                },
                [MARKS.BOLD]: (text) => {
                    return h('strong', { class: 'text-sk-red' }, text);
                }
            }
        }
    }
}
</script>
tolgap commented 1 year ago

One final question 😄: Do you have a snippet of Contentful data/document that fails to render for you? Thanks!

SketchNI commented 1 year ago

Everything else renders fine except for images.

{
  "nodeType": "embedded-asset-block",
  "data": {
    "target": {
      "sys": {
        "type": "Link",
        "id": "1Em8oXEtnhz4ADzoT3uUMB",
        "linkType": "Asset"
      }
    }
  },
  "content": [],
  "asset": {
    "sys": {
      "id": "1Em8oXEtnhz4ADzoT3uUMB",
      "type": "Asset",
      "revision": 1,
      "createdAt": "2021-09-01T20:27:30.029Z",
      "updatedAt": "2021-09-01T20:27:30.029Z",
      "environment": {
        "sys": {
          "type": "Link",
          "id": "master",
          "linkType": "Environment"
        }
      },
      "locale": "en-GB",
      "space": {
        "sys": {
          "type": "Link",
          "id": "7f36s5u95g5i",
          "linkType": "Space"
        }
      }
    },
    "fields": {
      "title": "after-fix",
      "description": "Screenshot of the Firefox Tab bar, address bar and bookmarks bar.",
      "file": {
        "fileName": "after-fix.png",
        "contentType": "image/png",
        "details": {
          "size": 18874,
          "image": {
            "width": 1915,
            "height": 101
          }
        },
        "url": "//images.ctfassets.net/7f36s5u95g5i/1Em8oXEtnhz4ADzoT3uUMB/5eb9ccb8687a43c59044e851d10c3d38/after-fix.png"
      }
    }
  }
},
tolgap commented 1 year ago

@SketchNI You are passing the entire image object as the contents of the img tag:

{
  [BLOCKS.EMBEDDED_ASSET]: (node, text) => {
      const image = node.asset.fields;
      return h('img', {
          src: `https://${image.file.url}`,
          alt: image.description
      }, image); // <--- leave this out <img> tags don't have any content in them
    }
},

So make your call

{
  [BLOCKS.EMBEDDED_ASSET]: (node, text) => {
      const image = node.asset.fields;
      return h('img', {
          src: `https://${image.file.url}`,
          alt: image.description
      }); // <--- leave this out <img> tags don't have any content in them
    }
},