Search code examples
markdownsveltesveltekitsanity

Portabletext-svelte image from rich formatted text


I use Sanity.IO for my blog and sveltekit. I use portabletext-svelte to change the json to html text and tailwindcss prose to make it pretty.

I know i have to build the URL so for that i have the "urlForImage" plugin from Sanity. But that's the part I'm stuck at, i don't know where to go from here.

The relevant sveltekit code so far:

<script lang="ts">
    import { urlForImage } from '$lib/config/sanity';
        import { PortableText } from '@portabletext/svelte';
</script>


<div class="prose">
    <article>
<PortableText
    value={post.postContent}
    components={{
    types: {
    image: //I don't understand how to solve this part
                }
                   }} 
/>
</article>
</div>

The json from sanity

{
  "_createdAt": "2023-03-02T08:52:40Z",
  "_id": "94e68ce8-794d-4908-a3f0-b8d6cb43229d",
  "_rev": "eCV6NYKLVadBWx2oaZJcVU",
  "_type": "post",
  "_updatedAt": "2023-03-15T16:35:28Z",
  "author": {
    "_ref": "13ad7ac4-c0b9-4ed9-8988-d6a1e2ebdc73",
    "_type": "reference"
  },
  "category": {
    "_ref": "c678fe22-5690-4237-a40f-ba59d5c18dd2",
    "_type": "reference"
  },
  "coverImage": {
    "_type": "image",
    "asset": {
      "_ref": "image-420bc2cbbd3877c5d07846205a20bf80df74b2fb-1920x1280-jpg",
      "_type": "reference"
    }
  },
  "date": "2023-03-15T07:00:00.000Z",
  "postContent": [
   ** {
      "_key": "e12adbc7e20b",
      "_type": "image",
      "alt": "responsiv webdesign eksempel",
      "asset": {
        "_ref": "image-241a2b7696ec60e6eab200e31132a64c4e81c5c1-1920x1280-jpg",
        "_type": "reference"
      }**
    },
    {
      "_key": "a9cff6857934",
      "_type": "block",
      "children": [
        {
          "_key": "27c0ad5175ee0",
          "_type": "span",
          "marks": [
            "strong"
          ],
          "text": "Hastighet"
        }
      ],
      "markDefs": [],
      "style": "h2"
    },
    {
      "_key": "ed13d7943bbf",
      "_type": "block",
      "children": [
        {
          "_key": "27ef9db1574a",
          "_type": "span",
          "marks": [],
          "text": ""
        }
      ],
      "markDefs": [],
      "style": "normal"
    },
    {
      "_key": "4de5389fd4cd",
      "_type": "block",
      "children": [
        {
          "_key": "7fa4550eb274",
          "_type": "span",
          "marks": [],
          "text": "I dagens digitale tidsalder er det viktig å ha en online tilstedeværelse for virksomheten din. Men det er ikke nok å bare ha en nettside. Du må sørge for at den er optimalisert både for ytelse og søkemotoroptimalisering (SEO)."
        }
      ],
      "markDefs": [],
      "style": "normal"
    },

I have already solved the cover image part:

<img
class="h-full w-full object-cover"
src={urlForImage($postData.post.coverImage)
.crop('focalpoint')
.width(826)
.height(384)
.url()}
alt="blog banner" />

I get this in the console on my browser. enter image description here

I've tried to include all the relevant info i can, let me know if if it's not enough.

Tried alot of solutions from examples i found on sanity.io's blog, but it turned out all of them were depreciated :/


Solution

  • You have to explicitly tell the renderer how to deal with image blocks by giving it a component to use. It could be something simple like this:

    <script>
        import { urlForImage } from '$lib/config/sanity';
        export let portableText;
    </script>
    
    <img src={imageUrl(portableText.value).url()} alt="" />
    

    and then you pass this component to the PortableText component:

    <script lang="ts">
      import { PortableText } from '@portabletext/svelte';
      import Image from './Image.svelte';
    </script>
    
    <PortableText
      value={post.postContent}
      components={{
        types: {
          image: Image
        }
      }} 
    />