Skip to content

Commit

Permalink
feat: add <SanityFile> component to assist with auto-generating fil…
Browse files Browse the repository at this point in the history
…e URLs

closes #70
  • Loading branch information
danielroe committed Apr 11, 2021
1 parent db4408a commit 0b2d353
Show file tree
Hide file tree
Showing 4 changed files with 178 additions and 0 deletions.
69 changes: 69 additions & 0 deletions docs/content/en/helpers/files.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
title: Files
description: 'Access text, images, and other media with Nuxt and the Sanity headless CMS.'
category: Helpers
position: 12
version: 0.80
---

## Global helper

This module defines a global `<SanityFile>` component to assist with auto-generating your file URLs. It is a lightweight functional component that simply turns the props into a valid file URL.

### Props

#### `assetId`

The Sanity asset ID (of the form `file-41773b5c55bc5414ab7554a75eefddf8e2e14524-txt`).

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

#### `projectId` and `dataset`

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

- Type: **string**

#### `download`

- Type: **string** or **boolean**
- Default: `false`

If set, the URL will contain a download link to that asset. If set to a string, the file will download to that filename. Otherwise, the original filename will be used (if saved in Sanity). If the original filename is not available, the id of the file will be used instead. See [the Sanity documentation](https://www.sanity.io/docs/file-type).

### Example

```vue
<template>
<SanityFile asset-id="file-41773b5c55bc5414ab7554a75eefddf8e2e14524-txt">
<template #default="{ src }">
<a :href="src">Click here to read this text file</a>
</template>
</SanityFile>
</template>
```

## Local import

You may wish to import `SanityFile` only in the components that need it, if you have disabled the global `imageHelper` option.

### Example

```vue
<template>
<SanityFile asset-id="file-41773b5c55bc5414ab7554a75eefddf8e2e14524-txt" download="myfile.txt">
<template #default="{ src }">
<a :href="src">Click here to download</a>
</template>
</SanityFile>
</template>
<script>
import { SanityFile } from '@nuxtjs/sanity/dist/components/sanity-file'
export default {
components: { SanityFile },
}
</script>
```
45 changes: 45 additions & 0 deletions src/components/sanity-file.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { extendVue } from './vue'

// eslint-disable-next-line
import type { SanityConfiguration } from '..'

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

export const SanityFile = extendVue({
name: 'SanityImage',
functional: true,
props: {
assetId: { type: String, required: true },
projectId: {
type: String,
default: null,
},
dataset: {
type: String,
default: null,
},
download: {
type: [String, Boolean],
default: false,
},
},
render (h, { props, parent, scopedSlots }) {
const parts = props.assetId.split('-').slice(1)
const format = parts.pop()

const projectId = props.projectId || (parent && parent.$sanity.config.projectId)
const dataset = props.dataset || (parent.$sanity && parent.$sanity.config.dataset) || 'production'

let src = `${baseURL}/${projectId}/${dataset}/${parts.join(
'-',
)}.${format}`

if (props.download) {
src = src + '?dl=' + (typeof props.download === 'string' ? props.download : '')
}

return scopedSlots.default({ src }) || h('span')
},
})

export default SanityFile
5 changes: 5 additions & 0 deletions test/unit/__snapshots__/sanity-file.test.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`SanityFile allows injecting download params 1`] = `<a href="https://cdn.sanity.io/files/test-project/production/41773b5c55bc5414ab7554a75eefddf8e2e14524.txt?dl=myfile.txt">Click here to download</a>`;

exports[`SanityFile provides a valid renderless component 1`] = `<a href="https://cdn.sanity.io/files/test-project/production/41773b5c55bc5414ab7554a75eefddf8e2e14524.txt">Click here to read</a>`;
59 changes: 59 additions & 0 deletions test/unit/sanity-file.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { mount } from '@vue/test-utils'

import { SanityFile } from '../../src/components/sanity-file'

const projectId = 'test-project'

describe('SanityFile', () => {
it('provides a valid renderless component', () => {
const wrapper = mount(
{
template: `
<SanityFile asset-id="file-41773b5c55bc5414ab7554a75eefddf8e2e14524-txt">
<template #default="{ src }">
<a :href="src">Click here to read</a>
</template>
</SanityFile>
`,
},
{
mocks: {
$sanity: {
config: {
projectId,
},
},
},
components: { SanityFile },
},
)

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

it('allows injecting download params', () => {
const wrapper = mount(
{
template: `
<SanityFile asset-id="file-41773b5c55bc5414ab7554a75eefddf8e2e14524-txt" download="myfile.txt">
<template #default="{ src }">
<a :href="src">Click here to download</a>
</template>
</SanityFile>
`,
},
{
mocks: {
$sanity: {
config: {
projectId,
},
},
},
components: { SanityFile },
},
)

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

0 comments on commit 0b2d353

Please sign in to comment.