nuxt-og-image 1.4.13 → 1.4.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -15
- package/dist/module.json +1 -1
- package/dist/module.mjs +2 -2
- package/dist/runtime/components/OgImageBasic.island.vue +81 -11
- package/dist/runtime/nitro/middleware/og.png.mjs +6 -0
- package/dist/runtime/nitro/routes/options.mjs +6 -2
- package/dist/runtime/nitro/routes/svg.mjs +6 -0
- package/dist/runtime/nitro/routes/vnode.mjs +6 -0
- package/dist/runtime/nitro/utils.d.ts +1 -1
- package/dist/runtime/nitro/utils.mjs +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -79,11 +79,11 @@ _nuxt.config.ts_
|
|
|
79
79
|
|
|
80
80
|
```ts
|
|
81
81
|
export default defineNuxtConfig({
|
|
82
|
-
// Recommended
|
|
82
|
+
// Recommended
|
|
83
83
|
runtimeConfig: {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
84
|
+
public: {
|
|
85
|
+
siteUrl: process.env.NUXT_PUBLIC_SITE_URL || 'https://example.com',
|
|
86
|
+
}
|
|
87
87
|
},
|
|
88
88
|
// OR
|
|
89
89
|
ogImage: {
|
|
@@ -114,6 +114,7 @@ useSeoMeta({
|
|
|
114
114
|
// 2a. Use the Composition API
|
|
115
115
|
defineOgImageStatic()
|
|
116
116
|
</script>
|
|
117
|
+
|
|
117
118
|
<template>
|
|
118
119
|
<div>
|
|
119
120
|
<!-- 2b. OR Component API -->
|
|
@@ -127,7 +128,7 @@ defineOgImageStatic()
|
|
|
127
128
|
Appending `/__og_image__` to the end of the URL will show you the playground for that pages `og:image`. This provides
|
|
128
129
|
a live preview of your `og:image` and allows you to edit it in real-time.
|
|
129
130
|
|
|
130
|
-
For example, if your local site is hosted at `
|
|
131
|
+
For example, if your local site is hosted at `http://localhost:3000`, you can view your `og:image` at `http://localhost:3000/__og_image__`.
|
|
131
132
|
|
|
132
133
|
### 3. Customize your `og:image`
|
|
133
134
|
|
|
@@ -136,12 +137,13 @@ While you have the playground open, start customising the OG Image by providing
|
|
|
136
137
|
```vue
|
|
137
138
|
<script lang="ts" setup>
|
|
138
139
|
defineOgImageStatic({
|
|
139
|
-
title: 'Welcome to my site!'
|
|
140
|
+
title: 'Welcome to my site!',
|
|
141
|
+
background: 'lightblue'
|
|
140
142
|
})
|
|
141
143
|
</script>
|
|
142
144
|
```
|
|
143
145
|
|
|
144
|
-
Congrats, you've set up your first Satori `og:image`!
|
|
146
|
+
Congrats, you've set up your first Satori `og:image`! You can checkout the [options](./src/runtime/components/OgImageBasic.island.vue) of the default template.
|
|
145
147
|
|
|
146
148
|
## Making your own Satori template
|
|
147
149
|
|
|
@@ -161,10 +163,13 @@ const props = defineProps({
|
|
|
161
163
|
title: String,
|
|
162
164
|
})
|
|
163
165
|
</script>
|
|
166
|
+
|
|
164
167
|
<template>
|
|
165
|
-
<div class="w-full h-full flex text-white bg-blue-500 items-center justify-center">
|
|
166
|
-
|
|
167
|
-
|
|
168
|
+
<div class="w-full h-full flex text-white bg-blue-500 items-center justify-center">
|
|
169
|
+
<h1 :style="{ fontSize: '70px' }">
|
|
170
|
+
{{ title }} 👋
|
|
171
|
+
</h1>
|
|
172
|
+
</div>
|
|
168
173
|
</template>
|
|
169
174
|
```
|
|
170
175
|
|
|
@@ -197,10 +202,13 @@ const props = defineProps({
|
|
|
197
202
|
backgroundColor: String
|
|
198
203
|
})
|
|
199
204
|
</script>
|
|
205
|
+
|
|
200
206
|
<template>
|
|
201
|
-
<div :class="[backgroundColor]" class="w-full h-full flex text-white items-center justify-center">
|
|
202
|
-
|
|
203
|
-
|
|
207
|
+
<div :class="[backgroundColor]" class="w-full h-full flex text-white items-center justify-center">
|
|
208
|
+
<h1 :style="{ fontSize: '70px' }">
|
|
209
|
+
{{ title }} 👋
|
|
210
|
+
</h1>
|
|
211
|
+
</div>
|
|
204
212
|
</template>
|
|
205
213
|
```
|
|
206
214
|
|
|
@@ -300,6 +308,7 @@ defineOgImageStatic({
|
|
|
300
308
|
theme: 'dark'
|
|
301
309
|
})
|
|
302
310
|
</script>
|
|
311
|
+
|
|
303
312
|
<template>
|
|
304
313
|
<!-- b. Component API -->
|
|
305
314
|
<OgImageStatic
|
|
@@ -325,7 +334,7 @@ This feature is not compatible with static sites built using `nuxi generate`.
|
|
|
325
334
|
|
|
326
335
|
```vue
|
|
327
336
|
<script setup lang="ts">
|
|
328
|
-
const dynamicData = await fetch('https://example.com/api')
|
|
337
|
+
const dynamicData = await fetch('https://example.com/api')
|
|
329
338
|
|
|
330
339
|
// a. Composition API
|
|
331
340
|
defineOgImageDynamic({
|
|
@@ -334,12 +343,13 @@ defineOgImageDynamic({
|
|
|
334
343
|
dynamicData,
|
|
335
344
|
})
|
|
336
345
|
</script>
|
|
346
|
+
|
|
337
347
|
<template>
|
|
338
348
|
<!-- b. Component API -->
|
|
339
349
|
<OgImageDynamic
|
|
340
350
|
component="MyOgImageTemplate"
|
|
341
351
|
title="Hello world"
|
|
342
|
-
:
|
|
352
|
+
:dynamic-data="dynamicData"
|
|
343
353
|
/>
|
|
344
354
|
</template>
|
|
345
355
|
```
|
|
@@ -411,6 +421,7 @@ defineOgImageScreenshot({
|
|
|
411
421
|
delay: 1000,
|
|
412
422
|
})
|
|
413
423
|
</script>
|
|
424
|
+
|
|
414
425
|
<template>
|
|
415
426
|
<!-- b. Component API -->
|
|
416
427
|
<OgImageScreenshot
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -359,9 +359,9 @@ export default async function() {
|
|
|
359
359
|
`;
|
|
360
360
|
}
|
|
361
361
|
if (config.satoriProvider) {
|
|
362
|
-
nitroConfig.virtual["#nuxt-og-image/satori"] = `import
|
|
362
|
+
nitroConfig.virtual["#nuxt-og-image/satori"] = `import satori from '${providerPath}/satori/${isWebWorkerEnv ? "webworker" : "node"}'
|
|
363
363
|
export default async function() {
|
|
364
|
-
return
|
|
364
|
+
return satori
|
|
365
365
|
}`;
|
|
366
366
|
nitroConfig.virtual["#nuxt-og-image/svg2png"] = `
|
|
367
367
|
import svg2png from '${providerPath}/svg2png/universal'
|
|
@@ -1,20 +1,90 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
defineProps({
|
|
2
|
+
const props = defineProps({
|
|
3
3
|
path: String,
|
|
4
|
-
title:
|
|
5
|
-
|
|
4
|
+
title: {
|
|
5
|
+
type: String,
|
|
6
|
+
default: 'Og Image Template',
|
|
7
|
+
},
|
|
8
|
+
description: {
|
|
9
|
+
type: String,
|
|
10
|
+
default: 'Set a description to change me.',
|
|
11
|
+
},
|
|
12
|
+
background: {
|
|
13
|
+
type: String,
|
|
14
|
+
},
|
|
15
|
+
color: {
|
|
16
|
+
type: String,
|
|
17
|
+
},
|
|
18
|
+
padding: {
|
|
19
|
+
type: String,
|
|
20
|
+
default: '0 100px',
|
|
21
|
+
},
|
|
22
|
+
titleFontSize: {
|
|
23
|
+
type: String,
|
|
24
|
+
default: '60px',
|
|
25
|
+
},
|
|
26
|
+
descriptionFontSize: {
|
|
27
|
+
type: String,
|
|
28
|
+
default: '26px',
|
|
29
|
+
},
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
const containerAttrs = computed(() => {
|
|
33
|
+
const isBackgroundTw = props.background?.startsWith('bg-')
|
|
34
|
+
const isColorTw = props.color?.startsWith('text-')
|
|
35
|
+
|
|
36
|
+
const classes = [
|
|
37
|
+
'w-full',
|
|
38
|
+
'h-full',
|
|
39
|
+
'items-center',
|
|
40
|
+
'justify-center',
|
|
41
|
+
]
|
|
42
|
+
const styles: Record<string, any> = {
|
|
43
|
+
padding: props.padding,
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (isBackgroundTw)
|
|
47
|
+
classes.push(props.background)
|
|
48
|
+
else
|
|
49
|
+
styles.backgroundColor = props.background
|
|
50
|
+
|
|
51
|
+
if (isColorTw)
|
|
52
|
+
classes.push(props.color)
|
|
53
|
+
else
|
|
54
|
+
styles.color = props.color
|
|
55
|
+
return { class: classes, style: styles }
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
const titleAttrs = computed(() => {
|
|
59
|
+
const classes = []
|
|
60
|
+
const styles = {
|
|
61
|
+
fontWeight: 'bold',
|
|
62
|
+
marginBottom: '20px',
|
|
63
|
+
fontSize: props.titleFontSize,
|
|
64
|
+
}
|
|
65
|
+
return { class: classes, style: styles }
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
const descriptionAttrs = computed(() => {
|
|
69
|
+
const classes = []
|
|
70
|
+
const styles = {
|
|
71
|
+
fontSize: props.descriptionFontSize,
|
|
72
|
+
}
|
|
73
|
+
return { class: classes, style: styles }
|
|
6
74
|
})
|
|
7
75
|
</script>
|
|
8
76
|
|
|
9
77
|
<template>
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
78
|
+
<div>
|
|
79
|
+
<div v-bind="containerAttrs">
|
|
80
|
+
<div class="flex flex-col">
|
|
81
|
+
<div v-bind="titleAttrs">
|
|
82
|
+
{{ title }}
|
|
83
|
+
</div>
|
|
84
|
+
<div v-bind="descriptionAttrs">
|
|
85
|
+
{{ description }}
|
|
86
|
+
</div>
|
|
18
87
|
</div>
|
|
19
88
|
</div>
|
|
89
|
+
</div>
|
|
20
90
|
</template>
|
|
@@ -15,5 +15,11 @@ export default defineEventHandler(async (e) => {
|
|
|
15
15
|
setHeader(e, "Expires", "0");
|
|
16
16
|
const options = await fetchOptions(e, basePath);
|
|
17
17
|
const provider = await useProvider(options.provider);
|
|
18
|
+
if (!provider) {
|
|
19
|
+
return {
|
|
20
|
+
status: 500,
|
|
21
|
+
body: `Provider ${options.provider} is missing.`
|
|
22
|
+
};
|
|
23
|
+
}
|
|
18
24
|
return provider.createPng(withBase(basePath, useHostname(e)), options);
|
|
19
25
|
});
|
|
@@ -24,8 +24,12 @@ export default defineEventHandler(async (e) => {
|
|
|
24
24
|
const path = query.path;
|
|
25
25
|
const html = await globalThis.$fetch(path);
|
|
26
26
|
const extractedPayload = extractOgImageOptions(html);
|
|
27
|
-
if (!extractedPayload)
|
|
28
|
-
return
|
|
27
|
+
if (!extractedPayload) {
|
|
28
|
+
return {
|
|
29
|
+
status: 500,
|
|
30
|
+
body: `The path ${path} is missing the og-image payload.`
|
|
31
|
+
};
|
|
32
|
+
}
|
|
29
33
|
e.node.req.url = path;
|
|
30
34
|
e.context._nitro.routeRules = void 0;
|
|
31
35
|
const routeRules = getRouteRules(e)?.ogImage;
|
|
@@ -7,5 +7,11 @@ export default defineEventHandler(async (e) => {
|
|
|
7
7
|
const options = await fetchOptions(e, path);
|
|
8
8
|
setHeader(e, "Content-Type", "image/svg+xml");
|
|
9
9
|
const provider = await useProvider(options.provider);
|
|
10
|
+
if (!provider) {
|
|
11
|
+
return {
|
|
12
|
+
status: 500,
|
|
13
|
+
body: `Provider ${options.provider} is missing.`
|
|
14
|
+
};
|
|
15
|
+
}
|
|
10
16
|
return provider.createSvg(withBase(path, useHostname(e)), options);
|
|
11
17
|
});
|
|
@@ -7,5 +7,11 @@ export default defineEventHandler(async (e) => {
|
|
|
7
7
|
const options = await fetchOptions(e, path);
|
|
8
8
|
setHeader(e, "Content-Type", "application/json");
|
|
9
9
|
const provider = await useProvider(options.provider);
|
|
10
|
+
if (!provider) {
|
|
11
|
+
return {
|
|
12
|
+
status: 500,
|
|
13
|
+
body: `Provider ${options.provider} is missing.`
|
|
14
|
+
};
|
|
15
|
+
}
|
|
10
16
|
return provider.createVNode(withBase(path, useHostname(e)), options);
|
|
11
17
|
});
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import type { H3Event } from 'h3';
|
|
3
3
|
import type { OgImageOptions } from '../../types';
|
|
4
4
|
export declare function wasmLoader(key: any, fallback: string, baseUrl: string): {
|
|
5
|
-
loaded(): Promise<
|
|
5
|
+
loaded(): boolean | Promise<any>;
|
|
6
6
|
load(): Promise<any>;
|
|
7
7
|
};
|
|
8
8
|
export declare function fetchOptions(e: H3Event, path: string): Promise<OgImageOptions>;
|
|
@@ -6,11 +6,11 @@ export function wasmLoader(key, fallback, baseUrl) {
|
|
|
6
6
|
let promise;
|
|
7
7
|
let loaded = false;
|
|
8
8
|
return {
|
|
9
|
-
|
|
9
|
+
loaded() {
|
|
10
10
|
if (loaded)
|
|
11
11
|
return true;
|
|
12
12
|
if (typeof promise !== "undefined")
|
|
13
|
-
|
|
13
|
+
return promise;
|
|
14
14
|
return false;
|
|
15
15
|
},
|
|
16
16
|
async load() {
|