Skip to content

Commit

Permalink
feat: allow using scoped slots for full control of <SanityImage>
Browse files Browse the repository at this point in the history
  • Loading branch information
danielroe committed Oct 6, 2020
1 parent 5441028 commit c40313d
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 20 deletions.
20 changes: 20 additions & 0 deletions docs/content/en/helpers/images.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ title: Image formatting
description: 'Access text, images, and other media with Nuxt and the Sanity headless CMS.'
category: Helpers
position: 11
version: 0.33
---

## Global helper
Expand Down Expand Up @@ -63,6 +64,25 @@ export default {
</script>
```

## Renderless usage

If you pass in a default scopedSlot you can use the `<SanityImage>` component as a renderless component to allow you to take full control of the functionality.

### Example

```vue
<template>
<SanityImage
asset-id="image-G3i4emG6B8JnTmGoN0UjgAp8-300x450-jpg"
auto="format"
>
<template #default="{ src }">
<img :src="src" />
</template>
</SanityImage>
</template>
```

## Other resources

If you are procedurally generating your image URLs you may wish to use [the `@sanity/image-url` package](https://github.com/sanity-io/image-url).
29 changes: 16 additions & 13 deletions src/components/sanity-image.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ export const SanityImage = extendVue({
...(isTemplated
? { required: true }
: {
default: projectId,
}),
default: projectId,
}),
},
dataset: {
type: String,
Expand Down Expand Up @@ -85,7 +85,7 @@ export const SanityImage = extendVue({
type: String,
validator: value =>
['clip', 'crop', 'fill', 'fillmax', 'max', 'scale', 'min'].includes(
value,
value
),
},
/**
Expand Down Expand Up @@ -174,7 +174,7 @@ export const SanityImage = extendVue({
*/
w: { type: [Number, String] },
},
render (h, { props, data }) {
render(h, { props, data, scopedSlots }) {
const keys: Array<keyof typeof props> = [
'auto',
'bg',
Expand All @@ -201,7 +201,7 @@ export const SanityImage = extendVue({
]

const queryParams = keys
.map((prop) => {
.map(prop => {
const urlFormat = prop.replace(/[A-Z]./, r => '-' + r[1].toLowerCase())
return props[prop] ? `${urlFormat}=${props[prop]}` : undefined
})
Expand All @@ -212,15 +212,18 @@ export const SanityImage = extendVue({
const format = parts.pop()

const src = `${baseURL}/${props.projectId}/${props.dataset}/${parts.join(
'-',
'-'
)}.${format}${queryParams ? '?' + queryParams : ''}`

return h('img', {
...data,
attrs: {
...data.attrs,
src,
},
})
// console.log('render -> scopedSlots', scopedSlots)
return scopedSlots.default
? scopedSlots.default({ src })
: h('img', {
...data,
attrs: {
...data.attrs,
src,
},
})
},
})
3 changes: 3 additions & 0 deletions test/unit/__snapshots__/sanity-image.test.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`SanityImage provides a valid renderless component 1`] = `<img src="https://cdn.sanity.io/images/undefined/production/G3i4emG6B8JnTmGoN0UjgAp8-300x450.jpg?auto=format">`;
36 changes: 29 additions & 7 deletions test/unit/sanity-image.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,30 +12,52 @@ const getWrapper = (propsData: Record<string, any>) =>
const projectId = 'test-project'

describe('SanityImage', () => {
test('it parses asset IDs correctly', () => {
it('parses asset IDs correctly', () => {
const wrapper = getWrapper({
assetId: 'image-7aa06723bb01a7a79055b6d6f5be80329a0e5b58-780x1170-jpg',
})

expect(wrapper.attributes().src).toBe(
`https://cdn.sanity.io/images/${projectId}/production/7aa06723bb01a7a79055b6d6f5be80329a0e5b58-780x1170.jpg`,
`https://cdn.sanity.io/images/${projectId}/production/7aa06723bb01a7a79055b6d6f5be80329a0e5b58-780x1170.jpg`
)
})

test('it correctly adds query params', () => {
it('correctly adds query params', () => {
const wrapper = getWrapper({
assetId: 'image-7aa06723bb01a7a79055b6d6f5be80329a0e5b58-780x1170-jpg',
w: 20,
h: '21',
})

expect(wrapper.attributes().src).toBe(
`https://cdn.sanity.io/images/${projectId}/production/7aa06723bb01a7a79055b6d6f5be80329a0e5b58-780x1170.jpg?h=21&w=20`,
`https://cdn.sanity.io/images/${projectId}/production/7aa06723bb01a7a79055b6d6f5be80329a0e5b58-780x1170.jpg?h=21&w=20`
)
})

it('provides a valid renderless component', () => {
const wrapper = mount(
{
template: `
<SanityImage
asset-id="image-G3i4emG6B8JnTmGoN0UjgAp8-300x450-jpg"
auto="format"
>
<template #default="{ src }">
<img :src="src" />
</template>
</SanityImage>
`,
},
{
components: { SanityImage },
}
)

expect(wrapper.html()).toMatchSnapshot()
})
})

describe('it validates props', () => {
describe('SanityImage prop validation', () => {
const mockError = jest.fn()
console.error = mockError

Expand Down Expand Up @@ -71,7 +93,7 @@ describe('it validates props', () => {

failures.forEach(([key, values]) => {
it(`fails for ${key}`, () => {
values.forEach((value) => {
values.forEach(value => {
getWrapper({
assetId:
'image-7aa06723bb01a7a79055b6d6f5be80329a0e5b58-780x1170-jpg',
Expand All @@ -92,7 +114,7 @@ describe('it validates props', () => {

validOptions.forEach(([key, values]) => {
it(`succeeds for ${key}`, () => {
values.forEach((value) => {
values.forEach(value => {
getWrapper({
assetId:
'image-7aa06723bb01a7a79055b6d6f5be80329a0e5b58-780x1170-jpg',
Expand Down

0 comments on commit c40313d

Please sign in to comment.