-
Notifications
You must be signed in to change notification settings - Fork 253
/
nuxt-picture.vue
117 lines (109 loc) · 2.85 KB
/
nuxt-picture.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
<template>
<picture :key="nSources[0].src">
<source
v-if="nSources[1]"
:type="nSources[1].type"
:srcset="nSources[1].srcset"
:sizes="nSources[1].sizes"
>
<img
v-bind="{...nImgAttrs, ...imgAttrs}"
:src="nSources[0].src"
:srcset="nSources[0].srcset"
:sizes="nSources[0].sizes"
v-on="$listeners"
>
</picture>
</template>
<script lang="ts">
import type { DefineComponentWithMixin } from '../../types/vue'
import { imageMixin } from './image.mixin'
import { getFileExtension } from '~image'
const defineComponent: DefineComponentWithMixin = (opts: any) => opts
export default defineComponent({
name: 'NuxtPicture',
mixins: [imageMixin],
props: {
legacyFormat: { type: String, default: null },
imgAttrs: { type: Object, default: null }
},
head () {
if (this.preload === true) {
const srcKey = typeof this.nSources[1] !== 'undefined' ? 1 : 0
const link = {
rel: 'preload',
as: 'image',
imagesrcset: this.nSources[srcKey].srcset
}
if (typeof this.nSources[srcKey].sizes !== 'undefined') {
link.imagesizes = this.nSources[srcKey].sizes
}
return {
link: [link]
}
}
return {}
},
computed: {
isTransparent (): boolean {
return ['png', 'webp', 'gif'].includes(this.originalFormat)
},
originalFormat (): string {
return getFileExtension(this.src)
},
nFormat (): string {
if (this.format) {
return this.format
}
if (this.originalFormat === 'svg') {
return 'svg'
}
return 'webp'
},
nLegacyFormat (): string {
if (this.legacyFormat) {
return this.legacyFormat
}
const formats: Record<string, string> = {
webp: this.isTransparent ? 'png' : 'jpeg',
svg: 'png'
}
return formats[this.nFormat] || this.originalFormat
},
nSources (): Array<{ srcset: string, src?: string, type?: string, sizes?: string }> {
if (this.nFormat === 'svg') {
return [{
srcset: this.src
}]
}
const formats = this.nLegacyFormat !== this.nFormat
? [this.nLegacyFormat, this.nFormat]
: [this.nFormat]
const sources = formats.map((format) => {
const { srcset, sizes, src } = this.$img.getSizes(this.src, {
...this.nOptions,
sizes: this.sizes || this.$img.options.screens,
modifiers: {
...this.nModifiers,
format
}
})
return {
src,
type: `image/${format}`,
sizes,
srcset
}
})
return sources
}
},
created () {
if (process.server && process.static) {
// Force compute sources into ssrContext
// eslint-disable-next-line no-unused-expressions
this.nSources
}
}
})
</script>