Skip to content

Commit

Permalink
feat: add storyblok provider (nuxt#133)
Browse files Browse the repository at this point in the history
Co-authored-by: Pooya Parsa <[email protected]>
  • Loading branch information
flozero and pi0 authored Apr 6, 2021
1 parent 3d40d66 commit 7ddc289
Show file tree
Hide file tree
Showing 8 changed files with 342 additions and 2 deletions.
1 change: 1 addition & 0 deletions docs/content/en/3.providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@ There are plenty of image service providers. Nuxt image has a generic way to wor
- [`Imgix`](/providers/imgix)
- [`IPX`](/providers/ipx) (selfhosted)
- [`Twicpics`](/providers/twicpics)
- [`Storyblok`](/providers/storyblok)

If you are looking for a specific provider outside of this list, you can [create your own provider](/advanced/custom-provider).
180 changes: 180 additions & 0 deletions docs/content/en/4.providers/storyblok.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
---
menuTitle: Storyblok
title: Storyblok Provider
description: 'Nuxt Image internally use Storyblok as static provider.'
category: Providers
---

Integration between [Storyblok](https://www.storyblok.com/docs/image-service/) and the image module. To use this provider you just need to specify the base url of your service in Storyblok.

```js{}[nuxt.config.js]
export default {
image: {
storyblok: {
baseURL: 'https://img2.storyblok.com'
}
}
}
```

## Storyblok modifiers

I am following all modifiers present on [Storyblok image service](https://www.storyblok.com/docs/image-service/)

### Resizing

Check [Storyblok documentation](https://www.storyblok.com/docs/image-service#resizing) if you want to know more.

the logic is:

- If you not defining the width or height it's taking the original image size.
- If you defined only the width or height it will resize proportionaly based ont he one defined

Example:

```html
<div>Original</div>
<NuxtImg
provider="storyblok"
src="https://a.storyblok.com/f/39898/3310x2192/e4ec08624e/demo-image.jpeg"
/>

<div>Resized static</div>
<NuxtImg
width="500"
height="500"
provider="storyblok"
src="https://a.storyblok.com/f/39898/3310x2192/e4ec08624e/demo-image.jpeg"
/>

<div>Proportional to Width</div>
<NuxtImg
width="500"
provider="storyblok"
src="https://a.storyblok.com/f/39898/3310x2192/e4ec08624e/demo-image.jpeg"
/>

<div>Proportional to Height</div>
<NuxtImg
height="500"
provider="storyblok"
src="https://a.storyblok.com/f/39898/3310x2192/e4ec08624e/demo-image.jpeg"
/>
```

### Fit in with background or not

Check [Storyblok documentation](https://www.storyblok.com/docs/image-service#fit-in) if you want to know more.

If you want to use it just add a props `fit="in"`. Take care that storyblok only support `fit-in`.

You can also use the fill filters to fill your fit-in with a specific background. If you not defining value it will be transparent.

Example:

```html
<div>Fit in with background CCCCCC</div>
<NuxtImg
width="200"
height="200"
fit="in"
:modifiers="{ filters: { fill: 'CCCCCC' } }"
provider="storyblok"
src="https://a.storyblok.com/f/39898/3310x2192/e4ec08624e/demo-image.jpeg"
/>
```

### Format

Check [Storyblok documentation](https://www.storyblok.com/docs/image-service#changing-the-format) if you want to know more.

You can modify your image format. Supported format are `webp`, `jpeg` and `png`.

Example:

```html
<h3>Format</h3>
<NuxtImg
width="200"
format="webp"
provider="storyblok"
src="https://a.storyblok.com/f/39898/3310x2192/e4ec08624e/demo-image.jpeg"
/>
```

### Quality

Check [Storyblok documentation](https://www.storyblok.com/docs/image-service#quality-optimization) if you want to know more.

You can update your image quality by defining the quality filters.

Example:

```html
<div class="flex">
<div>Resized and 10% Quality</div>
<NuxtImg
provider="storyblok"
width="200"
quality="10"
src="https://a.storyblok.com/f/39898/3310x2192/e4ec08624e/demo-image.jpeg"
/>
</div>
```

### Facial detection

Check [Storyblok documentation](https://www.storyblok.com/docs/image-service#facial-detection-and-smart-cropping) if you want to know more.

To have a smart crop just define a smart property inside modifier.

Example:

```html
<h3>Facial detection</h3>

<div>Resized without Smart Crop</div>
<NuxtImg
width="600"
height="130"
provider="storyblok"
src="https://a.storyblok.com/f/39898/2250x1500/c15735a73c/demo-image-human.jpeg"
/>

<div>Resized with Smart Crop</div>
<NuxtImg
width="600"
height="130"
:modifiers="{ smart: true }"
provider="storyblok"
src="https://a.storyblok.com/f/39898/2250x1500/c15735a73c/demo-image-human.jpeg"
/>
```

### Custom focal point

Check [Storyblok documentation](https://www.storyblok.com/docs/image-service#custom-focal-point) if you want to know more.

Storyblok offer you the focalize on a specific part of your image. Just use `focal` filters.

Example:

```html
<div>Focus on the bottom of the image</div>
<NuxtImg
width="600"
height="130"
:modifiers="{ filters: { focal: '450x500:550x600' } }"
provider="storyblok"
src="https://a.storyblok.com/f/39898/1000x600/d962430746/demo-image-human.jpeg"
/>

<div>Focus on the top of the image</div>
<NuxtImg
width="600"
height="130"
:modifiers="{ filters: { focal: '450x0:550x100' } }"
provider="storyblok"
src="https://a.storyblok.com/f/39898/1000x600/d962430746/demo-image-human.jpeg"
/>
```
3 changes: 3 additions & 0 deletions playground/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ export default <NuxtConfig> {
twicpics: {
baseURL: 'https://nuxt-demo.twic.pics'
},
storyblok: {
baseURL: 'https://img2.storyblok.com'
},
cloudinary: {
baseURL: 'https://res.cloudinary.com/nuxt/image/upload'
},
Expand Down
109 changes: 108 additions & 1 deletion playground/pages/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,114 @@

<h2>JPEG image on Imagekit</h2>
<NuxtImg provider="imagekit" src="/img/plant.jpeg" />
</p<select>

<h2>JPEG image on Storyblok</h2>
<h3>Resizing</h3>
<div class="flex">
<div>Original</div>
<NuxtImg
provider="storyblok"
src="https://a.storyblok.com/f/39898/3310x2192/e4ec08624e/demo-image.jpeg"
/>
</div>
<div class="flex">
<div>Resized static</div>
<NuxtImg
width="500"
height="500"
provider="storyblok"
src="https://a.storyblok.com/f/39898/3310x2192/e4ec08624e/demo-image.jpeg"
/>
</div>
<div class="flex">
<div>Proportional to Width</div>
<NuxtImg
width="500"
provider="storyblok"
src="https://a.storyblok.com/f/39898/3310x2192/e4ec08624e/demo-image.jpeg"
/>
</div>
<div class="flex">
<div>Proportional to Height</div>
<NuxtImg
height="500"
provider="storyblok"
src="https://a.storyblok.com/f/39898/3310x2192/e4ec08624e/demo-image.jpeg"
/>
</div>
<h3>Fit-in</h3>
<div class="flex">
<div>Fit in with background CCCCCC</div>
<NuxtImg
width="200"
height="200"
fit="in"
:modifiers="{ filters: { fill: 'CCCCCC' } }"
provider="storyblok"
src="https://a.storyblok.com/f/39898/3310x2192/e4ec08624e/demo-image.jpeg"
/>
</div>
<h3>Format</h3>
<div class="flex">
<div>Change image format</div>
<NuxtImg
width="200"
format="webp"
provider="storyblok"
src="https://a.storyblok.com/f/39898/3310x2192/e4ec08624e/demo-image.jpeg"
/>
</div>
<h3>Quality</h3>
<div class="flex">
<div>Resized and 10% Quality</div>
<NuxtImg
width="200"
quality="10"
provider="storyblok"
src="https://a.storyblok.com/f/39898/3310x2192/e4ec08624e/demo-image.jpeg"
/>
</div>
<h3>Facial detection</h3>
<div class="flex">
<div>Resized without Smart Crop</div>
<NuxtImg
width="600"
height="130"
provider="storyblok"
src="https://a.storyblok.com/f/39898/2250x1500/c15735a73c/demo-image-human.jpeg"
/>
</div>
<div class="flex">
<div>Resized with Smart Crop</div>
<NuxtImg
width="600"
height="130"
:modifiers="{ smart: true }"
provider="storyblok"
src="https://a.storyblok.com/f/39898/2250x1500/c15735a73c/demo-image-human.jpeg"
/>
</div>
<h3>Custom focal point</h3>
<div class="flex">
<div>Focus on the bottom of the image</div>
<NuxtImg
width="600"
height="130"
:modifiers="{ filters: { focal: '450x500:550x600' } }"
provider="storyblok"
src="https://a.storyblok.com/f/39898/1000x600/d962430746/demo-image-human.jpeg"
/>
</div>
<div class="flex">
<div>Focus on the top of the image</div>
<NuxtImg
width="600"
height="130"
:modifiers="{ filters: { focal: '450x0:550x100' } }"
provider="storyblok"
src="https://a.storyblok.com/f/39898/1000x600/d962430746/demo-image-human.jpeg"
/>
</div>
</div>
</div>
</template>
Expand Down
2 changes: 2 additions & 0 deletions playground/pages/picture.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
<h2>JPEG image on Fastly</h2>
<NuxtPicture width="900" placeholder provider="fastly" src="/image.jpg" /> -->
<!-- <h2>JPEG image on Storyblok</h2>
<NuxtPicture width="900" placeholder provider="storyblok" src="https://a.storyblok.com/f/39898/2250x1500/c15735a73c/demo-image-human.jpeg" /> -->
</div>
</div>
</template>
Expand Down
3 changes: 2 additions & 1 deletion src/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ const BuiltInProviders = [
'imgix',
'ipx',
'static',
'twicpics'
'twicpics',
'storyblok'
]

export interface ImageModuleProvider {
Expand Down
45 changes: 45 additions & 0 deletions src/runtime/providers/storyblok.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import type { ProviderGetImage } from 'src'
import { withBase, joinURL, parseURL } from 'ufo'

// https://www.storyblok.com/docs/image-service
const storyblockCDN = 'https://img2.storyblok.com'

export const getImage: ProviderGetImage = (src, { modifiers = {}, baseURL = storyblockCDN } = {}) => {
const {
fit,
smart,
width = '0',
height = '0',
filters = {},
format,
quality
} = modifiers

const doResize = width !== '0' || height !== '0'

if (format) {
filters.format = format + ''
}

if (quality) {
filters.quality = quality + ''
}

const _filters = Object.entries(filters || {}).map(e => `${e[0]}(${e[1]})`).join(':')

const options = joinURL(
fit && `fit-${fit}`,
doResize ? `${width}x${height}` : undefined,
smart && 'smart',
_filters && ('filters:' + _filters)
)

// TODO: check if hostname is https://a.storyblok.com ?
const { pathname } = parseURL(src)

const url = withBase(joinURL(options, pathname), baseURL)

return {
url
}
}
1 change: 1 addition & 0 deletions src/types/module.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export interface ImageProviders {
imagekit?: any
imgix?: any
twicpics?: any
storyblok?: any,
ipx?: Partial<IPXOptions>
static?: Partial<IPXOptions>
}
Expand Down

0 comments on commit 7ddc289

Please sign in to comment.