Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions docs/content/2.helpers/1.portable-text.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ This module defines a global `<SanityContent>` component that can turn [portable

As of v2, `<SanityContent>` uses [`@portabletext/vue`](https://github.com/portabletext/vue-portabletext) for rendering portable text. This means features and properties available to `@portabletext/vue` also work with `<SanityContent>`. Please refer to their [Usage guide](https://github.com/portabletext/vue-portabletext?tab=readme-ov-file#basic-usage) for advanced configuration options.


::warning
This render change introduces **breaking changes** for `<SanityContent>` v2 components. Refer to the following upgrade guide:
* To reflect `@portabletext/vue`'s props, `blocks` β†’ `value` and `serializers` β†’ `components` attribute name changes have been made. The property types remain the same.
Expand All @@ -18,6 +19,13 @@ This render change introduces **breaking changes** for `<SanityContent>` v2 comp
</template>
```

### Image handling

The `<SanityContent>` component automatically handles Sanity images using the `<SanityImage>` component, including using NuxtImg if installed, for optimization and transformation support. Any props you want to pass to Sanity image can be added as attributes to the image block in Sanity Studio. At this moment it is not set up to handle image hotspot and crop.

To override you can pass an custom image component as shown below.


### Example with custom components

```vue
Expand Down Expand Up @@ -46,6 +54,19 @@ const components = {
}), {
...props.value,
}),
// You can override the default image component if needed
image: props => h('CustomImageComponent', {
...props.value,
}),
// Example of handling caption and attribution in a custom component
imageWithCaption: props => {
const { asset, caption, attribution, crop, hotspot } = props.value
return h('div', { class: 'custom-image-wrapper' }, [
h('img', { src: `https://cdn.sanity.io/images/.../${asset._ref}` }),
caption && h('p', { class: 'caption' }, caption),
attribution && h('p', { class: 'attribution' }, attribution)
])
},
},
marks: {
// Custom marks handling
Expand All @@ -55,6 +76,66 @@ const components = {
</script>
```

### Image Block Structure

The automatic image handling works with the standard Sanity portable text image block structure:

```json
{
"_type": "image",
"asset": {
"_type": "reference",
"_ref": "image-61991cfbe9182124c18ee1829c07910faadd100e-2048x1366-png"
},
"caption": "This is the caption (ignored by default component)",
"attribution": "Public domain (ignored by default component)",
"crop": {
"top": 0.028131868131868132,
"bottom": 0.15003663003663004,
"left": 0.01875,
"right": 0.009375000000000022
},
"hotspot": {
"x": 0.812500000000001,
"y": 0.27963369963369955,
"height": 0.3248351648351647,
"width": 0.28124999999999994
}
}
```

The component automatically extracts the `_ref` from the asset object and passes it to the `SanityImage` component along with any `crop` and `hotspot` data for proper image transformation. Caption and attribution data are ignored by the default image component.

### Disabling Default Image Handling

If you want to handle images yourself or disable the automatic image handling entirely, you can use the `disableDefaultImageComponent` prop:

```vue
<template>
<!-- Disable automatic image handling -->
<SanityContent
:value="content"
:disableDefaultImageComponent="true"
/>

<!-- Or provide your own image component -->
<SanityContent
:value="content"
:disableDefaultImageComponent="true"
:components="{
types: {
image: props => h('MyCustomImage', {
assetId: props.value.asset._ref,
caption: props.value.caption
})
}
}"
/>
</template>
```

When `disableDefaultImageComponent` is set to `true`, the component will not automatically handle image blocks. If you don't provide your own image component in the `components.types.image` prop, PortableText will show a warning about the missing component.

::warning
If you want to use the same components in multiple places, consider creating your own component (e.g. `<MySanityContent>`) which wraps SanityContent with your default components. By creating `~/components/MySanityContent.vue` you should be able to use this everywhere in your app without importing it.
::
Expand Down
71 changes: 56 additions & 15 deletions docs/content/2.helpers/2.images.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,68 @@
## Global helper
## `<SanityImage>`

This module defines a global `<SanityImage>` component to assist with auto-generating your image URLs. It is a lightweight functional component that simply turns the props into a valid image URL.
This module provides a global `<SanityImage>` component to assist with rendering images from Sanity.

### Props
By default, it is a lightweight functional component that turns the given props into a valid image URL. However, if you have [`@nuxt/image`](https://image.nuxt.com/) installed, it will automatically use `<NuxtImg>` for improved performance.

#### `assetId`
### Nuxt Image Integration

The Sanity asset ID (of the form `image-G3i4emG6B8JnTmGoN0UjgAp8-300x450-jpg`).
When `@nuxt/image` is installed in your project, `<SanityImage>` will automatically detect it and render a `<NuxtImg>` component instead of a regular `<img>` tag. This allows you to leverage the powerful features of Nuxt Image, such as resizing, format conversion, and optimizations.

To enable the Sanity provider within Nuxt Image, you need to configure it in your `nuxt.config.ts`:

```ts [nuxt.config.ts]
export default defineNuxtConfig({
image: {
sanity: {
projectId: 'your-project-id',
dataset: 'your-dataset-name'
}
},

sanity: {
// module options
}
})
```

You can now use `<SanityImage>` as before, and it will pass all its attributes to `<NuxtImg>`. All attributes supported by both `<NuxtImg>` and the [Sanity image API](https://www.sanity.io/docs/image-urls) can be passed as props.

```vue
<template>
<!-- This will render a <NuxtImg> component -->
<SanityImage
asset-id="image-G3i4emG6B8JnTmGoN0UjgAp8-300x450-jpg"
w="300"
h="450"
auto="format"
/>
</template>
```

### Basic Usage

If you are not using `@nuxt/image`, `<SanityImage>` will generate a standard `<img>` tag.

#### Props

##### `assetId`

The Sanity asset ID, which has the format `image-G3i4emG6B8JnTmGoN0UjgAp8-300x450-jpg`.

- Type: **string**
- **Required**

#### `projectId` and `dataset`
##### `projectId` and `dataset`

These default to the `projectId` and `dataset` passed into the module options but can be overridden.
These default to the `projectId` and `dataset` from the module options, but can be overridden as props.

- Type: **string**

#### Image transformation props
##### Image transformation props

All other image transformation options are valid props - see [the Sanity documentation](https://www.sanity.io/docs/image-urls) for more details.
All other image transformation options from the [Sanity documentation](https://www.sanity.io/docs/image-urls) are also valid props.

### Example
#### Example

```vue
<template>
Expand All @@ -32,9 +73,9 @@ All other image transformation options are valid props - see [the Sanity documen
</template>
```

## Renderless usage
## Renderless Usage

If you pass in a default scoped slot you can use the `<SanityImage>` component as a renderless component to allow you to take full control of the functionality.
By passing a default scoped slot, you can use the `<SanityImage>` component in a renderless fashion to take full control of the rendered markup.

### Example

Expand All @@ -51,9 +92,9 @@ If you pass in a default scoped slot you can use the `<SanityImage>` component a
</template>
```

## Using @sanity/image-url
## Using `@sanity/image-url`

If the `SanityImage` helper doesn't cover your needs, you can use [the `@sanity/image-url` package](https://github.com/sanity-io/image-url). One way to add it to your Nuxt project is through a plugin:
If the `<SanityImage>` component does not cover your specific needs, you can use the official [`@sanity/image-url`](https://github.com/sanity-io/image-url) package. One way to integrate it is through a Nuxt plugin:

```js{}[plugins/sanity-image-builder.js]
import imageUrlBuilder from '@sanity/image-url'
Expand All @@ -69,7 +110,7 @@ export default defineNuxtPlugin(() => {
})
```

Then you can use the global `$urlFor` helper:
This will provide a global `$urlFor` helper that you can use in your templates:

```vue
<template>
Expand Down
8 changes: 7 additions & 1 deletion playground/nuxt.config.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
const viewerToken = process.env.NUXT_SANITY_VISUAL_EDITING_TOKEN

export default defineNuxtConfig({
modules: ['@nuxtjs/sanity'],
modules: ['@nuxtjs/sanity', '@nuxt/image'],
app: {
head: {
script: [{ src: 'https://unpkg.com/tailwindcss-jit-cdn' }],
},
},
compatibilityDate: '2024-08-19',
image: {
sanity: {
projectId: 'j1o4tmjp',
dataset: 'production',
},
},
sanity: {
globalHelper: true,
apiVersion: '2021-03-26',
Expand Down
1 change: 1 addition & 0 deletions playground/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"start": "nuxi start"
},
"dependencies": {
"@nuxt/image": "^1.11.0",
"@nuxtjs/sanity": "latest",
"@sanity/client": "latest",
"nuxt": "4.1.3",
Expand Down
74 changes: 74 additions & 0 deletions playground/pages/text.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@
SanityContent (Vue-PortableText)
</h2>
<p>This example uses the <a href="https://github.com/portabletext/vue-portabletext">vue-portabletext</a> library for rendering content.</p>

<h3 class="text-lg font-semibold mt-4">
With Automatic Image Handling
</h3>
<p>The images below are automatically rendered using the SanityImage component without any configuration needed!</p>
<SanityContent :value="contentWithImages" />

<h3 class="text-lg font-semibold mt-8">
With Custom Components
</h3>
<SanityContent
:value="value"
:components="components"
Expand Down Expand Up @@ -48,6 +58,70 @@ const components = {
},
}

// Content with images that will be automatically handled
const contentWithImages = [
{
_key: 'd810da8ac845',
_type: 'block',
children: [
{
_key: 'd810da8ac8450',
_type: 'span',
marks: [],
text: 'Here is some text with an image below:',
},
],
markDefs: [],
style: 'normal',
},
{
_key: 'example-image-1',
_type: 'image',
asset: {
_type: 'reference',
_ref: 'image-5b433475b541fc1f2903d9b281efdde7ac9c28a5-780x1170-jpg',
},
crop: {
top: 0.1,
bottom: 0.1,
left: 0.1,
right: 0.1,
},
hotspot: {
x: 0.5,
y: 0.5,
height: 0.8,
width: 0.8,
},
w: 300,
h: 450,
},
{
_key: 'd810da8ac846',
_type: 'block',
children: [
{
_key: 'd810da8ac8460',
_type: 'span',
marks: [],
text: 'And here is another image with different dimensions:',
},
],
markDefs: [],
style: 'normal',
},
{
_key: 'example-image-2',
_type: 'image',
asset: {
_type: 'reference',
_ref: 'image-5b433475b541fc1f2903d9b281efdde7ac9c28a5-780x1170-jpg',
},
w: 600,
h: 400,
},
]

const value = [
{
_type: 'lazyRegisteredComponent',
Expand Down
3 changes: 3 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading