Skip to content

Commit

Permalink
feat: allow local import of <SanityImage>
Browse files Browse the repository at this point in the history
  • Loading branch information
danielroe committed Aug 9, 2020
1 parent 387f9fd commit 762df3c
Show file tree
Hide file tree
Showing 12 changed files with 252 additions and 69 deletions.
2 changes: 1 addition & 1 deletion docs/content/en/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ Include credentials in requests made to Sanity. Useful if you want to take advan
### `useCdn`

- Type: **boolean**
- Default: **process.env.NODE_ENV === production**
- Default: **true** in production or **false** if a token has been passed in

### `minimal`

Expand Down
53 changes: 50 additions & 3 deletions docs/content/en/helpers/images.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,30 @@ category: Helpers
position: 10
---

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. For more details on the props it accepts, see [the Sanity documentation](https://www.sanity.io/docs/image-urls) - all those options are accepted. The only required prop is `assetId`.
## Global helper

Alternatively, 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).
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.

## Example
### Props

#### `assetId`

The Sanity asset ID (of the form `image-G3i4emG6B8JnTmGoN0UjgAp8-300x450-jpg`).

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

#### `projectId` and `dataset`

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

- Type: **string**

#### 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.

### Example

```vue
<template>
Expand All @@ -19,3 +38,31 @@ Alternatively, if you are procedurally generating your image URLs you may wish t
/>
</template>
```

## Local import

You may wish to import `SanityImage` only in the components that need it. If you do so, you can do so - but note that you will need to provide your `projectId` (and `dataset` if not `production`):

### Example

```vue
<template>
<SanityImage
project-id="my-project-id"
asset-id="image-G3i4emG6B8JnTmGoN0UjgAp8-300x450-jpg"
auto="format"
/>
</template>
<script>
import { SanityImage } from '@nuxtjs/sanity/components/sanity-image'
export default {
components: { SanityImage },
}
</script>
```

## 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).
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"prepare": "yarn build",
"prepublishOnly": "yarn test",
"release": "yarn build && yarn test && release-it",
"test": "yarn lint && jest --runInBand"
"test": "yarn lint && yarn build && jest --runInBand"
},
"dependencies": {
"defu": "^3.1.0"
Expand Down
45 changes: 43 additions & 2 deletions siroc.config.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,49 @@
import { PackageOptions } from 'siroc'
import { resolve } from 'path'
import { readdirSync } from 'fs-extra'

import type { PackageOptions } from 'siroc'
import type { RollupOptions } from 'rollup'

import dts from 'rollup-plugin-dts'
import esbuild from 'rollup-plugin-esbuild'

const components = readdirSync('./src/components')
const externals = ['chalk', 'consola', 'defu', 'fs-extra']

const config: PackageOptions = {
rollup: {
externals: ['chalk', 'consola', 'defu', 'fs-extra'],
externals,
},
hooks: {
'build:extendRollup' (_pkg, { rollupConfig }) {
const config = components.map((filename): RollupOptions[] => {
const base = filename.split('.').slice(0, -1).join('.')
return [{
input: resolve(`./src/components/${filename}`),
output: {
file: resolve(`./dist/${base}.js`),
format: 'es',
},
external: externals,
plugins: [
esbuild(),
],
},
{
input: resolve(`./src/components/${filename}`),
output: {
file: resolve(`./dist/${base}.d.ts`),
format: 'es',
},
external: externals,
plugins: [
dts(),
],
}]
}).flat()

rollupConfig.push(...config)
},
},
}

Expand Down
10 changes: 1 addition & 9 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ export interface SanityConfiguration {
token?: string
}

const isProd = process.env.NODE_ENV === 'production'

const enc = encodeURIComponent

export function getQs (query: string, params: Record<string, any> = {}) {
Expand All @@ -27,13 +25,7 @@ export function getQs (query: string, params: Record<string, any> = {}) {
}

export function createClient (config: SanityConfiguration) {
const {
projectId,
dataset = 'production',
useCdn = isProd,
withCredentials = false,
token,
} = config
const { projectId, dataset, useCdn, withCredentials, token } = config
return {
clone: () =>
createClient({ projectId, dataset, useCdn, withCredentials, token }),
Expand Down
35 changes: 23 additions & 12 deletions templates/sanity-image.js → src/components/sanity-image.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,30 @@
// @ts-check

import Vue from 'vue'
import { extendVue } from '../vue'

const baseURL = 'https://cdn.sanity.io/images'

export const SanityImage = Vue.extend({
const projectId = '<%= options.projectId %>'
const dataset = '<%= options.dataset %>'

const isTemplated = projectId.includes('options')

export const SanityImage = extendVue({
functional: true,
props: {
//
assetId: { type: String, required: true },
//
projectId: {
type: String,
...(isTemplated
? { required: true }
: {
default: projectId,
}),
},
dataset: {
type: String,
default: isTemplated ? 'production' : dataset,
},
/**
* Set auto=format to automatically return an image in webp formatting if the browser supports it.
*/
Expand Down Expand Up @@ -160,10 +175,7 @@ export const SanityImage = Vue.extend({
w: { type: [Number, String] },
},
render (h, { props, data }) {
/**
* @type {Array<keyof typeof props>} keys
*/
const keys = [
const keys: Array<keyof typeof props> = [
'auto',
'bg',
'blur',
Expand Down Expand Up @@ -199,17 +211,16 @@ export const SanityImage = Vue.extend({
const parts = props.assetId.split('-').slice(1)
const format = parts.pop()

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

return h('img', {
...data,
attrs: {
...data.attrs,
src,
class: [data.class, data.staticClass].filter(Boolean).join(' '),
},
})
},
})

Vue.component('SanityImage', SanityImage)
12 changes: 10 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,12 @@ export interface SanityModuleOptions extends Partial<SanityConfiguration> {
*/
imageHelper?: boolean
}
const isProd = process.env.NODE_ENV === 'production'

const DEFAULTS: SanityModuleOptions = {
imageHelper: true,
dataset: 'production',
withCredentials: false,
}
const CONFIG_KEY = 'sanity'

Expand Down Expand Up @@ -66,6 +70,7 @@ const nuxtModule: Module<SanityModuleOptions> = function (moduleOptions) {
this.options[CONFIG_KEY],
moduleOptions,
sanityConfig,
{ useCdn: isProd && !moduleOptions.token && !this.options[CONFIG_KEY].token },
DEFAULTS,
)

Expand Down Expand Up @@ -98,6 +103,9 @@ const nuxtModule: Module<SanityModuleOptions> = function (moduleOptions) {
fileName: 'sanity/plugin.js',
options: {
client: useOfficialClient,
components: {
imageHelper: options.imageHelper,
},
sanityConfig: JSON.stringify({
useCdn: options.useCdn,
projectId: options.projectId,
Expand All @@ -109,8 +117,8 @@ const nuxtModule: Module<SanityModuleOptions> = function (moduleOptions) {
})

if (options.imageHelper) {
this.addPlugin({
src: resolve(__dirname, '../templates/sanity-image.js'),
this.addTemplate({
src: resolve(__dirname, '../dist/sanity-image.js'),
fileName: 'sanity/sanity-image.js',
options: {
projectId: options.projectId,
Expand Down
5 changes: 5 additions & 0 deletions src/vue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import type { FunctionalComponentOptions } from 'vue'
import type { ExtendedVue } from 'vue/types/vue'
import type { RecordPropsDefinition } from 'vue/types/options'

export const extendVue = <Props>(definition: FunctionalComponentOptions<Props, RecordPropsDefinition<Props>>) => definition as unknown as ExtendedVue<Vue, {}, {}, {}, Props>
7 changes: 7 additions & 0 deletions templates/plugin.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import Vue from 'vue'

<%= options.client
? "import createClient from '@sanity/client'"
: "import { createClient } from '@nuxtjs/sanity'"
%>

<% if (options.components.imageHelper) { %>
import { SanityImage } from './sanity-image'
Vue.component('SanityImage', SanityImage)
<% } %>

const options = JSON.parse('<%= options.sanityConfig %>')

/**
Expand Down
16 changes: 6 additions & 10 deletions test/e2e/module.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,23 @@ describe('module with default options', () => {
},
})
test('should inject core plugin with correct options', () => {
expect(ctx.nuxt.moduleContainer.addPlugin).toBeCalledTimes(2)

expect(ctx).toNuxtPluginAdded({
src: expect.stringContaining('plugin.js'),
fileName: 'sanity/plugin.js',
options: {
client: true,
components: {
imageHelper: true,
},
sanityConfig: JSON.stringify({
useCdn: false,
projectId,
dataset,
withCredentials: false,
}),
},
})

expect(ctx).toNuxtPluginAdded({
src: expect.stringContaining('sanity-image.js'),
fileName: 'sanity/sanity-image.js',
options: {
projectId,
dataset,
},
})
expect(ctx.nuxt.moduleContainer.addTemplate).toBeCalled()
})
})
29 changes: 0 additions & 29 deletions test/unit/sanity-image.test.js

This file was deleted.

Loading

0 comments on commit 762df3c

Please sign in to comment.