nuxt-og-image 2.0.0-beta.7 → 2.0.0-beta.70
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 +312 -97
- package/dist/client/200.html +2 -2
- package/dist/client/404.html +2 -2
- package/dist/client/_nuxt/IconCSS.78433ecd.js +1 -0
- package/dist/client/_nuxt/IconCSS.b41b9663.css +1 -0
- package/dist/client/_nuxt/ImageLoader.7571516f.css +1 -0
- package/dist/client/_nuxt/ImageLoader.b930015f.js +1 -0
- package/dist/client/_nuxt/entry.1311cc29.css +1 -0
- package/dist/client/_nuxt/entry.212e85d9.js +143 -0
- package/dist/client/_nuxt/{error-404.1ff52902.js → error-404.0875e3f6.js} +1 -1
- package/dist/client/_nuxt/error-404.f3dd5020.css +1 -0
- package/dist/client/_nuxt/error-500.06915589.css +1 -0
- package/dist/client/_nuxt/{error-500.f7d30da5.js → error-500.f06aa28f.js} +1 -1
- package/dist/client/_nuxt/index.9dc826bf.js +1 -0
- package/dist/client/_nuxt/index.ffbea0a9.css +1 -0
- package/dist/client/_nuxt/options.f2b6402e.js +1 -0
- package/dist/client/_nuxt/png.04e14eef.js +1 -0
- package/dist/client/_nuxt/{shiki.3a930bb8.js → shiki.a8b6534b.js} +1 -1
- package/dist/client/_nuxt/svg.9ac05c0d.js +1 -0
- package/dist/client/_nuxt/vnodes.c25d5717.js +1 -0
- package/dist/client/index.html +2 -2
- package/dist/client/options/index.html +2 -2
- package/dist/client/png/index.html +2 -2
- package/dist/client/svg/index.html +2 -2
- package/dist/client/vnodes/index.html +2 -2
- package/dist/module.d.ts +101 -11
- package/dist/module.json +2 -2
- package/dist/module.mjs +394 -134
- package/dist/runtime/browserUtil.d.ts +1 -0
- package/dist/runtime/browserUtil.mjs +10 -5
- package/dist/runtime/components/{OgImageDynamic.d.ts → OgImage/Cached.d.ts} +2 -2
- package/dist/runtime/components/OgImage/Cached.mjs +10 -0
- package/dist/runtime/components/{OgImageScreenshot.d.ts → OgImage/Screenshot.d.ts} +2 -2
- package/dist/runtime/components/{OgImageScreenshot.mjs → OgImage/Screenshot.mjs} +2 -2
- package/dist/runtime/components/OgImage/WithoutCache.d.ts +4 -0
- package/dist/runtime/components/OgImage/WithoutCache.mjs +10 -0
- package/dist/runtime/components/OgImage/_OgImageDynamic.d.ts +8 -0
- package/dist/runtime/components/{OgImageDynamic.mjs → OgImage/_OgImageDynamic.mjs} +3 -3
- package/dist/runtime/components/OgImage/_OgImageStatic.d.ts +8 -0
- package/dist/runtime/components/{OgImageStatic.mjs → OgImage/_OgImageStatic.mjs} +3 -3
- package/dist/runtime/components/{OgImageStatic.d.ts → OgImage/index.d.ts} +2 -2
- package/dist/runtime/components/OgImage/index.mjs +10 -0
- package/dist/runtime/components/OgImageTemplate/Fallback.vue +170 -0
- package/dist/runtime/composables/defineOgImage.d.ts +12 -4
- package/dist/runtime/composables/defineOgImage.mjs +31 -49
- package/dist/runtime/composables/util.d.ts +2 -0
- package/dist/runtime/composables/util.mjs +26 -0
- package/dist/runtime/nitro/middleware/og.png.mjs +54 -8
- package/dist/runtime/nitro/middleware/playground.mjs +4 -3
- package/dist/runtime/nitro/plugins/prerender.d.ts +3 -0
- package/dist/runtime/nitro/plugins/prerender.mjs +28 -0
- package/dist/runtime/nitro/providers/browser/lambda.d.ts +1 -1
- package/dist/runtime/nitro/providers/browser/lambda.mjs +3 -3
- package/dist/runtime/nitro/providers/browser/{node.mjs → playwright.mjs} +0 -9
- package/dist/runtime/nitro/providers/browser/universal.d.ts +1 -0
- package/dist/runtime/nitro/providers/browser/universal.mjs +33 -0
- package/dist/runtime/nitro/providers/png/resvg-node.d.ts +4 -0
- package/dist/runtime/nitro/providers/png/resvg-node.mjs +6 -0
- package/dist/runtime/nitro/providers/png/resvg-wasm.d.ts +3 -0
- package/dist/runtime/nitro/providers/png/resvg-wasm.mjs +11 -0
- package/dist/runtime/nitro/providers/{svg2png/universal.d.ts → png/svg2png.d.ts} +2 -3
- package/dist/runtime/nitro/providers/png/svg2png.mjs +11 -0
- package/dist/runtime/nitro/providers/satori/{webworker.d.ts → yoga-wasm.d.ts} +2 -3
- package/dist/runtime/nitro/providers/satori/{webworker.mjs → yoga-wasm.mjs} +4 -5
- package/dist/runtime/nitro/renderers/browser.d.ts +2 -2
- package/dist/runtime/nitro/renderers/browser.mjs +14 -10
- package/dist/runtime/nitro/renderers/satori/index.d.ts +2 -2
- package/dist/runtime/nitro/renderers/satori/index.mjs +27 -32
- package/dist/runtime/nitro/renderers/satori/plugins/emojis.d.ts +1 -1
- package/dist/runtime/nitro/renderers/satori/plugins/emojis.mjs +19 -6
- package/dist/runtime/nitro/renderers/satori/plugins/encoding.d.ts +1 -1
- package/dist/runtime/nitro/renderers/satori/plugins/encoding.mjs +5 -7
- package/dist/runtime/nitro/renderers/satori/plugins/flex.d.ts +1 -1
- package/dist/runtime/nitro/renderers/satori/plugins/flex.mjs +8 -10
- package/dist/runtime/nitro/renderers/satori/plugins/imageSrc.d.ts +1 -1
- package/dist/runtime/nitro/renderers/satori/plugins/imageSrc.mjs +45 -13
- package/dist/runtime/nitro/renderers/satori/plugins/twClasses.d.ts +1 -1
- package/dist/runtime/nitro/renderers/satori/plugins/twClasses.mjs +5 -7
- package/dist/runtime/nitro/renderers/satori/utils.d.ts +4 -5
- package/dist/runtime/nitro/renderers/satori/utils.mjs +28 -17
- package/dist/runtime/nitro/routes/debug.d.ts +8 -0
- package/dist/runtime/nitro/routes/debug.mjs +14 -0
- package/dist/runtime/nitro/routes/font.mjs +2 -2
- package/dist/runtime/nitro/routes/html.mjs +102 -27
- package/dist/runtime/nitro/routes/options.d.ts +2 -2
- package/dist/runtime/nitro/routes/options.mjs +25 -22
- package/dist/runtime/nitro/routes/svg.mjs +5 -3
- package/dist/runtime/nitro/routes/vnode.mjs +5 -3
- package/dist/runtime/nitro/utils-pure.d.ts +2 -2
- package/dist/runtime/nitro/utils-pure.mjs +1 -4
- package/dist/runtime/nitro/utils.d.ts +11 -11
- package/dist/runtime/nitro/utils.mjs +69 -54
- package/dist/runtime/public-assets/__nuxt_og_image__/browser-provider-not-supported.png +0 -0
- package/dist/runtime/public-assets-optional/resvg/resvg.wasm +0 -0
- package/dist/types.d.ts +6 -0
- package/package.json +39 -27
- package/dist/client/_nuxt/IconCSS.a041aca0.js +0 -1
- package/dist/client/_nuxt/ImageLoader.9bf39d71.js +0 -1
- package/dist/client/_nuxt/entry.74018bda.js +0 -5
- package/dist/client/_nuxt/entry.7a8c1ab2.css +0 -1
- package/dist/client/_nuxt/error-404.1469f10f.css +0 -1
- package/dist/client/_nuxt/error-500.92b94fae.css +0 -1
- package/dist/client/_nuxt/error-component.cf7543e5.js +0 -3
- package/dist/client/_nuxt/index.3f356409.js +0 -1
- package/dist/client/_nuxt/options.56a3e5f9.js +0 -1
- package/dist/client/_nuxt/png.37f3e77b.js +0 -1
- package/dist/client/_nuxt/svg.186c6bd1.js +0 -1
- package/dist/client/_nuxt/vnodes.a799f183.js +0 -1
- package/dist/runtime/components/OgImageBasic.island.vue +0 -92
- package/dist/runtime/nitro/providers/svg2png/universal.mjs +0 -9
- /package/dist/runtime/nitro/providers/browser/{node.d.ts → playwright.d.ts} +0 -0
- /package/dist/runtime/nitro/providers/satori/{node.d.ts → default.d.ts} +0 -0
- /package/dist/runtime/nitro/providers/satori/{node.mjs → default.mjs} +0 -0
- /package/dist/runtime/{public-assets → public-assets-optional/inter-font}/inter-latin-ext-400-normal.woff +0 -0
- /package/dist/runtime/{public-assets → public-assets-optional/inter-font}/inter-latin-ext-700-normal.woff +0 -0
- /package/dist/runtime/{public-assets → public-assets-optional/svg2png}/svg2png.wasm +0 -0
- /package/dist/runtime/{public-assets → public-assets-optional/yoga}/yoga.wasm +0 -0
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
Enlightened OG Image generation for Nuxt 3.
|
|
14
14
|
</p>
|
|
15
15
|
|
|
16
|
-
<img src="https://repository-images.githubusercontent.com/578125755/
|
|
16
|
+
<img src="https://repository-images.githubusercontent.com/578125755/90f77ca8-95be-4e06-9600-332afe1ba24f">
|
|
17
17
|
|
|
18
18
|
<p align="center">
|
|
19
19
|
<table>
|
|
@@ -38,7 +38,7 @@ Enlightened OG Image generation for Nuxt 3.
|
|
|
38
38
|
- ▲ Render using [Satori](https://github.com/vercel/satori): Tailwind classes, Google fonts, emoji support and more!
|
|
39
39
|
- 🤖 Or prerender using the Browser: Supporting painless, complex templates
|
|
40
40
|
- 📸 Feeling lazy? Just generate screenshots for every page: hide elements, wait for animations, and more
|
|
41
|
-
- ⚙️ Works on the edge: Vercel Edge and Cloudflare Workers
|
|
41
|
+
- ⚙️ Works on the edge: Vercel Edge, Netlify Edge and Cloudflare Workers
|
|
42
42
|
|
|
43
43
|
## Demos
|
|
44
44
|
|
|
@@ -50,9 +50,11 @@ Enlightened OG Image generation for Nuxt 3.
|
|
|
50
50
|
|
|
51
51
|
```bash
|
|
52
52
|
# Install module
|
|
53
|
-
npm install --save-dev nuxt-og-image
|
|
53
|
+
npm install --save-dev nuxt-og-image@beta
|
|
54
54
|
# Using yarn
|
|
55
|
-
yarn add --dev nuxt-og-image
|
|
55
|
+
yarn add --dev nuxt-og-image@beta
|
|
56
|
+
#
|
|
57
|
+
pnpm add -D nuxt-og-image@beta
|
|
56
58
|
```
|
|
57
59
|
|
|
58
60
|
## Setup
|
|
@@ -67,30 +69,8 @@ export default defineNuxtConfig({
|
|
|
67
69
|
})
|
|
68
70
|
```
|
|
69
71
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
This feature uses Nuxt Islands, which requires Nuxt >= 3.1.
|
|
73
|
-
|
|
74
|
-
### Add your host name
|
|
75
|
-
|
|
76
|
-
The `og:image` meta tag requires the full URL, so you must provide your site host.
|
|
77
|
-
|
|
78
|
-
_nuxt.config.ts_
|
|
79
|
-
|
|
80
|
-
```ts
|
|
81
|
-
export default defineNuxtConfig({
|
|
82
|
-
// Recommended
|
|
83
|
-
runtimeConfig: {
|
|
84
|
-
public: {
|
|
85
|
-
siteUrl: process.env.NUXT_PUBLIC_SITE_URL || 'https://example.com',
|
|
86
|
-
}
|
|
87
|
-
},
|
|
88
|
-
// OR
|
|
89
|
-
ogImage: {
|
|
90
|
-
host: 'https://example.com',
|
|
91
|
-
},
|
|
92
|
-
})
|
|
93
|
-
```
|
|
72
|
+
This module requires [Nuxt Server Components](https://nuxt.com/docs/guide/directory-structure/components#standalone-server-components)
|
|
73
|
+
which will be enabled for you.
|
|
94
74
|
|
|
95
75
|
# Guides
|
|
96
76
|
|
|
@@ -98,31 +78,31 @@ export default defineNuxtConfig({
|
|
|
98
78
|
|
|
99
79
|
For this guide, you will create your Satori OG image using the default component for your home page.
|
|
100
80
|
|
|
101
|
-
### 1. Define
|
|
81
|
+
### 1. Define an OG Image
|
|
102
82
|
|
|
103
|
-
Within your `pages/index.vue`, use `
|
|
104
|
-
|
|
105
|
-
Make sure you have defined some metadata as props will be inferred from it.
|
|
83
|
+
Within your `pages/index.vue`, use `defineOgImage()` or `<OgImage />` to define your `og:image` component.
|
|
106
84
|
|
|
107
85
|
```vue
|
|
108
86
|
<script lang="ts" setup>
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
// 2a. Use the Composition API
|
|
115
|
-
defineOgImageStatic()
|
|
87
|
+
const ogImageOptions = {
|
|
88
|
+
title: 'My awesome home page.',
|
|
89
|
+
}
|
|
90
|
+
// a. Use the Composition API
|
|
91
|
+
defineOgImage(ogImageOptions)
|
|
116
92
|
</script>
|
|
117
93
|
|
|
118
94
|
<template>
|
|
119
95
|
<div>
|
|
120
|
-
<!--
|
|
121
|
-
<
|
|
96
|
+
<!-- b. OR Component API -->
|
|
97
|
+
<OgImage v-bind="ogImageOptions" />
|
|
122
98
|
</div>
|
|
123
99
|
</template>
|
|
124
100
|
```
|
|
125
101
|
|
|
102
|
+
This will use the default template [OgImageBasic](./src/runtime/components/OgImageBasic.island.vue),
|
|
103
|
+
provided by this module.
|
|
104
|
+
|
|
105
|
+
|
|
126
106
|
### 2. View your `og:image`
|
|
127
107
|
|
|
128
108
|
Appending `/__og_image__` to the end of the URL will show you the playground for that pages `og:image`. This provides
|
|
@@ -132,54 +112,58 @@ For example, if your local site is hosted at `http://localhost:3000`, you can vi
|
|
|
132
112
|
|
|
133
113
|
### 3. Customize your `og:image`
|
|
134
114
|
|
|
135
|
-
While you have the playground open, start
|
|
115
|
+
While you have the playground open, start customizing the OG Image by modifying the `ogImageOptions`.
|
|
116
|
+
Full HMR is supported, so you should see your changes instantly.
|
|
136
117
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
defineOgImageStatic({
|
|
140
|
-
title: 'Welcome to my site!',
|
|
141
|
-
background: 'lightblue'
|
|
142
|
-
})
|
|
143
|
-
</script>
|
|
144
|
-
```
|
|
145
|
-
|
|
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.
|
|
118
|
+
Congrats, you've set up your first Satori `og:image`!
|
|
119
|
+
You can check out the [options](./src/runtime/components/OgImageBasic.island.vue) of the default template.
|
|
147
120
|
|
|
148
121
|
## Making your own Satori template
|
|
149
122
|
|
|
150
123
|
Templates for OG images are powered by Nuxt Islands, which are just Vue components. In this guide we'll create a new
|
|
151
124
|
template and use it for our `og:image`.
|
|
152
125
|
|
|
153
|
-
### 1. Create
|
|
154
|
-
|
|
155
|
-
Make a folder in your components directory called `islands`.
|
|
126
|
+
### 1. Create your template component
|
|
156
127
|
|
|
157
|
-
|
|
158
|
-
you can use the following template to begin:
|
|
128
|
+
Make a new file at the path `./components/OgImage/Default.vue` with the following contents:
|
|
159
129
|
|
|
160
130
|
```vue
|
|
161
131
|
<script setup lang="ts">
|
|
162
132
|
const props = defineProps({
|
|
163
133
|
title: String,
|
|
164
134
|
})
|
|
135
|
+
|
|
136
|
+
// inherited attrs can mess up the satori parser
|
|
137
|
+
defineOptions({
|
|
138
|
+
inheritAttrs: false,
|
|
139
|
+
})
|
|
165
140
|
</script>
|
|
166
141
|
|
|
167
142
|
<template>
|
|
168
143
|
<div class="w-full h-full flex text-white bg-blue-500 items-center justify-center">
|
|
169
|
-
<h1
|
|
144
|
+
<h1>
|
|
170
145
|
{{ title }} 👋
|
|
171
146
|
</h1>
|
|
172
147
|
</div>
|
|
173
148
|
</template>
|
|
149
|
+
<style scoped>
|
|
150
|
+
h1 {
|
|
151
|
+
font-size: 70px;
|
|
152
|
+
}
|
|
153
|
+
</style>
|
|
174
154
|
```
|
|
175
155
|
|
|
156
|
+
The convention is to use either the `OgImage` or `OgImageTemplate` folders within `components`.
|
|
157
|
+
|
|
158
|
+
See [componentDirs](#component-dirs) if you prefer to use a different named directory.
|
|
159
|
+
|
|
176
160
|
### 2. Use the new template
|
|
177
161
|
|
|
178
|
-
Now that you have your template, you can use it in for your `
|
|
162
|
+
Now that you have your template, you can use it in for your `defineOgImage` composable.
|
|
179
163
|
|
|
180
164
|
```vue
|
|
181
165
|
<script lang="ts" setup>
|
|
182
|
-
|
|
166
|
+
defineOgImage({
|
|
183
167
|
component: 'MyOgImage',
|
|
184
168
|
title: 'Welcome to my site!'
|
|
185
169
|
})
|
|
@@ -192,7 +176,7 @@ View this image in your browser by appending `/__og_image__` to the end of the U
|
|
|
192
176
|
|
|
193
177
|
Now that you have your template, you can start customizing it.
|
|
194
178
|
|
|
195
|
-
Any options you pass to the `
|
|
179
|
+
Any options you pass to the `defineOgImage` composable will be available in the component. With this in mind, we can
|
|
196
180
|
add support for changing the background color.
|
|
197
181
|
|
|
198
182
|
```vue
|
|
@@ -205,18 +189,23 @@ const props = defineProps({
|
|
|
205
189
|
|
|
206
190
|
<template>
|
|
207
191
|
<div :class="[backgroundColor]" class="w-full h-full flex text-white items-center justify-center">
|
|
208
|
-
<h1
|
|
192
|
+
<h1>
|
|
209
193
|
{{ title }} 👋
|
|
210
194
|
</h1>
|
|
211
195
|
</div>
|
|
212
196
|
</template>
|
|
197
|
+
<style scoped>
|
|
198
|
+
h1 {
|
|
199
|
+
font-size: 70px;
|
|
200
|
+
}
|
|
201
|
+
</style>
|
|
213
202
|
```
|
|
214
203
|
|
|
215
|
-
Now let's
|
|
204
|
+
Now let's customize the background to be green instead.
|
|
216
205
|
|
|
217
206
|
```vue
|
|
218
207
|
<script lang="ts" setup>
|
|
219
|
-
|
|
208
|
+
defineOgImage({
|
|
220
209
|
component: 'MyOgImage',
|
|
221
210
|
title: 'Welcome to my site!',
|
|
222
211
|
backgroundColor: 'bg-green-500'
|
|
@@ -241,6 +230,105 @@ Out of the box, this module provides support for the following:
|
|
|
241
230
|
|
|
242
231
|
If you find Satori is too limiting for your needs, you can always use the `browser` provider to capture browser screenshots instead.
|
|
243
232
|
|
|
233
|
+
|
|
234
|
+
## Bypassing cache
|
|
235
|
+
|
|
236
|
+
Caching og images is enabled by default, if you need to generate dynamically at runtime,
|
|
237
|
+
you can modify the use the `defineOgImageWithoutCache(options)` composable or `<OgImageWithoutCache v-bind="options" />` component.
|
|
238
|
+
|
|
239
|
+
This mode is not compatible with `nuxt generate`.
|
|
240
|
+
|
|
241
|
+
## SSG Images
|
|
242
|
+
|
|
243
|
+
When using `nuxt generate`, you will need to provide some additional configuration.
|
|
244
|
+
|
|
245
|
+
- You must provide a `siteUrl` so that the meta tags can be generated correctly as absolute URLs.
|
|
246
|
+
|
|
247
|
+
```ts
|
|
248
|
+
export default defineNuxtConfig({
|
|
249
|
+
// Recommended
|
|
250
|
+
runtimeConfig: {
|
|
251
|
+
public: {
|
|
252
|
+
siteUrl: process.env.NUXT_PUBLIC_SITE_URL || 'https://example.com',
|
|
253
|
+
}
|
|
254
|
+
},
|
|
255
|
+
// OR
|
|
256
|
+
ogImage: {
|
|
257
|
+
host: 'https://example.com',
|
|
258
|
+
},
|
|
259
|
+
})
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
- You must prerender all pages that use `og:image`.
|
|
263
|
+
|
|
264
|
+
```ts
|
|
265
|
+
export default defineNuxtConfig({
|
|
266
|
+
nitro: {
|
|
267
|
+
prerender: {
|
|
268
|
+
crawlLinks: true, // recommended
|
|
269
|
+
routes: [
|
|
270
|
+
'/',
|
|
271
|
+
// list all routes that use og:image if you're not using crawlLinks
|
|
272
|
+
'/about',
|
|
273
|
+
'/blog',
|
|
274
|
+
'/blog/my-first-post',
|
|
275
|
+
]
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
})
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
## SSR Images
|
|
282
|
+
|
|
283
|
+
### Compatibility
|
|
284
|
+
|
|
285
|
+
Both Satori and Browser will work in Node based environments. Prerendering is fully supported.
|
|
286
|
+
|
|
287
|
+
When you want to generate dynamic images at runtime there are certain Nitro runtime limitations.
|
|
288
|
+
|
|
289
|
+
| Provider | Satori | Browser |
|
|
290
|
+
|---------------------------------------------------------------------------------|-----------------------|---------|
|
|
291
|
+
| Node | ✅ | ✅ |
|
|
292
|
+
| [Vercel](https://nuxt-og-image-playground.vercel.app/) | ✅ | ❌ |
|
|
293
|
+
| [Vercel Edge](https://nuxt-og-image-playground-gkdt.vercel.app/) | ✅ | ❌ |
|
|
294
|
+
| [Cloudflare Pages](https://nuxt-og-image-playground.pages.dev/) | ✅ | ❌ |
|
|
295
|
+
| [Netlify](https://nuxt-og-image-playground-netlify.netlify.app/) | ✅ | ❌ |
|
|
296
|
+
| [Netlify Edge](https://nuxt-og-image-playground-netlify-edge.netlify.app/) | (Soon) | ❌ |
|
|
297
|
+
| [StackBlitz](https://stackblitz.com/edit/nuxt-starter-pxs3wk?file=package.json) | ✅ (emojis don't work) | ❌ |
|
|
298
|
+
|
|
299
|
+
Other providers are yet to be tested. Please create an issue if your nitro preset is not listed.
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
When using `nuxt build`, you can only use the `browser` provider with the `node` Nitro preset.
|
|
303
|
+
|
|
304
|
+
If you intend to use the `browser` provider in production, make sure you include the `playwright` dependency.
|
|
305
|
+
|
|
306
|
+
```bash
|
|
307
|
+
npm i playwright
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
You can get around this by prerendering any pages that use `og:image`. Note that dynamic browser generated images are not supported at all,
|
|
311
|
+
you should use the Satori provider.
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
```ts
|
|
315
|
+
export default defineNuxtConfig({
|
|
316
|
+
nitro: {
|
|
317
|
+
prerender: {
|
|
318
|
+
crawlLinks: true, // recommended
|
|
319
|
+
routes: [
|
|
320
|
+
'/',
|
|
321
|
+
// list all routes that use og:image if you're not using crawlLinks
|
|
322
|
+
'/about',
|
|
323
|
+
'/blog',
|
|
324
|
+
'/blog/my-first-post',
|
|
325
|
+
]
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
})
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
|
|
244
332
|
## Taking screenshots
|
|
245
333
|
|
|
246
334
|
If you want to simply take a screenshot of your page, you can use the `OgImageScreenshot` component or `defineOgImageScreenshot` composable.
|
|
@@ -251,11 +339,11 @@ defineOgImageScreenshot()
|
|
|
251
339
|
</script>
|
|
252
340
|
```
|
|
253
341
|
|
|
254
|
-
Alternatively you can pass the `{ provider: 'browser' }` option to `
|
|
342
|
+
Alternatively you can pass the `{ provider: 'browser' }` option to `defineOgImage`.
|
|
255
343
|
|
|
256
344
|
```vue
|
|
257
345
|
<script lang="ts" setup>
|
|
258
|
-
|
|
346
|
+
defineOgImage({
|
|
259
347
|
component: 'MyAwesomeOgImage',
|
|
260
348
|
// this will take a browser screenshot
|
|
261
349
|
provider: 'browser'
|
|
@@ -282,15 +370,144 @@ _package.json_
|
|
|
282
370
|
}
|
|
283
371
|
```
|
|
284
372
|
|
|
373
|
+
## Custom Fonts / Supporting non-english characters
|
|
374
|
+
|
|
375
|
+
When creating your OG Image, you'll probably want to use a font custom to your project.
|
|
376
|
+
|
|
377
|
+
To make this easier for you, Google Fonts are loaded by default with Inter 400 and Inter 700.
|
|
378
|
+
|
|
379
|
+
You can easily load different Google Fonts by using their name+weight. For example:
|
|
380
|
+
|
|
381
|
+
```ts
|
|
382
|
+
export default defineNuxtConfig({
|
|
383
|
+
ogImage: {
|
|
384
|
+
fonts: [
|
|
385
|
+
// will load the Noto Sans font from Google fonts
|
|
386
|
+
'Noto+Sans:400'
|
|
387
|
+
]
|
|
388
|
+
}
|
|
389
|
+
})
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
This also lets you support non-english characters by adding the appropriate font to your config.
|
|
393
|
+
|
|
394
|
+
For example, to support Hebrew characters, you can use the config:
|
|
395
|
+
|
|
396
|
+
```ts
|
|
397
|
+
export default defineNuxtConfig({
|
|
398
|
+
ogImage: {
|
|
399
|
+
fonts: [
|
|
400
|
+
// will load this font from Google fonts
|
|
401
|
+
'Noto+Sans+Hebrew:400'
|
|
402
|
+
]
|
|
403
|
+
}
|
|
404
|
+
})
|
|
405
|
+
````
|
|
406
|
+
|
|
407
|
+
If you'd like to load a font locally,
|
|
408
|
+
then you can provide the configuration as an object:
|
|
409
|
+
|
|
410
|
+
```ts
|
|
411
|
+
export default defineNuxtConfig({
|
|
412
|
+
ogImage: {
|
|
413
|
+
fonts: [
|
|
414
|
+
{
|
|
415
|
+
name: 'optieinstein',
|
|
416
|
+
weight: 800,
|
|
417
|
+
// path must point to a public font file
|
|
418
|
+
path: '/OPTIEinstein-Black.otf',
|
|
419
|
+
}
|
|
420
|
+
],
|
|
421
|
+
}
|
|
422
|
+
})
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
Make sure to set the font family in your component to match the font name.
|
|
426
|
+
|
|
427
|
+
```vue
|
|
428
|
+
<template>
|
|
429
|
+
<div :style="{ fontFamily: 'optieinstein' }">
|
|
430
|
+
<!-- Your component -->
|
|
431
|
+
</div>
|
|
432
|
+
</template>
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
## Runtime Caching
|
|
436
|
+
|
|
437
|
+
When images are generated at runtime, caching is enabled by default to reduce the load on your server.
|
|
438
|
+
|
|
439
|
+
By default, it will use the default storage engine for your Nitro preset.
|
|
440
|
+
You can customise the storage engine by providing a `runtimeCacheStorage` option to the `ogImage` config.
|
|
441
|
+
|
|
442
|
+
The option takes the same configuration as the Nuxt `nitro.storage` option.
|
|
443
|
+
See the [Nitro Storage Layer](https://nitro.unjs.io/guide/storage) documentation for more details.
|
|
444
|
+
|
|
445
|
+
For example:
|
|
446
|
+
|
|
447
|
+
```ts
|
|
448
|
+
export default defineNuxtConfig({
|
|
449
|
+
ogImage: {
|
|
450
|
+
// cloudflare kv binding example, set your own config
|
|
451
|
+
runtimeCacheStorage: {
|
|
452
|
+
driver: 'cloudflare-kv-binding',
|
|
453
|
+
binding: 'OG_IMAGE_CACHE'
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
})
|
|
457
|
+
````
|
|
458
|
+
|
|
459
|
+
By default, static images will be cached for 24 hours. You can change the image TTL by providing `cacheTtl` when defining the image.
|
|
460
|
+
|
|
461
|
+
```ts
|
|
462
|
+
defineOgImage({
|
|
463
|
+
// ...
|
|
464
|
+
cacheTtl: 60 * 60 * 24 * 7 // 7 days
|
|
465
|
+
})
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
Alternatively, you can change the default cacheTtl time in your nuxt.config.
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
```ts
|
|
472
|
+
export default defineNuxtConfig({
|
|
473
|
+
ogImage: {
|
|
474
|
+
defaults: {
|
|
475
|
+
cacheTtl: 60 * 60 * 24 * 7 // 7 days
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
})
|
|
479
|
+
````
|
|
480
|
+
|
|
481
|
+
You can also provide a configuration for the `cacheKey`. This gives you control over the cache bursting of the images.
|
|
482
|
+
|
|
483
|
+
```vue
|
|
484
|
+
<script lang="ts" setup>
|
|
485
|
+
defineOgImage({
|
|
486
|
+
cacheKey: `${myData.id}:${myData.updatedAt}`,
|
|
487
|
+
})
|
|
488
|
+
</script>
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
If you prefer not to cache your images you can always disable them by providing a `false` value.
|
|
492
|
+
|
|
493
|
+
```ts
|
|
494
|
+
export default defineNuxtConfig({
|
|
495
|
+
ogImage: {
|
|
496
|
+
// no runtime cache
|
|
497
|
+
runtimeCacheStorage: false
|
|
498
|
+
}
|
|
499
|
+
})
|
|
500
|
+
````
|
|
501
|
+
|
|
285
502
|
# API
|
|
286
503
|
|
|
287
504
|
The module exposes a composition and component API to implement your `og:image` generation. You should pick
|
|
288
505
|
whichever one you prefer using.
|
|
289
506
|
|
|
290
|
-
##
|
|
507
|
+
## OgImage / defineOgImage
|
|
291
508
|
|
|
292
|
-
The `
|
|
293
|
-
that will be
|
|
509
|
+
The `OgImage` component and the `defineOgImage` composable creates a static image
|
|
510
|
+
that will be prerendered.
|
|
294
511
|
|
|
295
512
|
The options follow the [OgImageOptions](#OgImageOptions) interface,
|
|
296
513
|
any additional options will be passed to the `component` as props.
|
|
@@ -302,7 +519,7 @@ It is useful for images that do not change at runtime.
|
|
|
302
519
|
```vue
|
|
303
520
|
<script setup lang="ts">
|
|
304
521
|
// a. Composition API
|
|
305
|
-
|
|
522
|
+
defineOgImage({
|
|
306
523
|
component: 'MyOgImageTemplate',
|
|
307
524
|
title: 'Hello world',
|
|
308
525
|
theme: 'dark'
|
|
@@ -311,7 +528,7 @@ defineOgImageStatic({
|
|
|
311
528
|
|
|
312
529
|
<template>
|
|
313
530
|
<!-- b. Component API -->
|
|
314
|
-
<
|
|
531
|
+
<OgImage
|
|
315
532
|
component="MyOgImageTemplate"
|
|
316
533
|
title="Hello world"
|
|
317
534
|
theme="dark"
|
|
@@ -320,9 +537,9 @@ defineOgImageStatic({
|
|
|
320
537
|
```
|
|
321
538
|
|
|
322
539
|
|
|
323
|
-
##
|
|
540
|
+
## OgImageWithoutCache / defineOgImageWithoutCache
|
|
324
541
|
|
|
325
|
-
The `
|
|
542
|
+
The `OgImageWithoutCache` component and the `defineOgImageWithoutCache` composable creates a dynamic image. They are not prerendered and will
|
|
326
543
|
be generated at runtime.
|
|
327
544
|
|
|
328
545
|
The options follow the [OgImageOptions](#OgImageOptions) interface,
|
|
@@ -337,19 +554,19 @@ This feature is not compatible with static sites built using `nuxi generate`.
|
|
|
337
554
|
const dynamicData = await fetch('https://example.com/api')
|
|
338
555
|
|
|
339
556
|
// a. Composition API
|
|
340
|
-
|
|
557
|
+
defineOgImageWithoutCache({
|
|
341
558
|
component: 'MyOgImageTemplate',
|
|
342
559
|
title: 'Hello world',
|
|
343
|
-
dynamicData,
|
|
560
|
+
...dynamicData,
|
|
344
561
|
})
|
|
345
562
|
</script>
|
|
346
563
|
|
|
347
564
|
<template>
|
|
348
565
|
<!-- b. Component API -->
|
|
349
|
-
<
|
|
566
|
+
<OgImageWithoutCache
|
|
350
567
|
component="MyOgImageTemplate"
|
|
351
568
|
title="Hello world"
|
|
352
|
-
|
|
569
|
+
v-bind="dynamicData"
|
|
353
570
|
/>
|
|
354
571
|
</template>
|
|
355
572
|
```
|
|
@@ -396,12 +613,14 @@ The name of the component to use as the template. By default, it uses OgImageBas
|
|
|
396
613
|
- Required: `false`
|
|
397
614
|
|
|
398
615
|
The provider to use to generate the image. The default provider is `satori`.
|
|
399
|
-
When you use `browser` it will use
|
|
616
|
+
When you use `browser` it will use Playwright to generate the image.
|
|
400
617
|
|
|
401
|
-
### `
|
|
618
|
+
### `cache`
|
|
402
619
|
|
|
403
620
|
- Type: `boolean`
|
|
404
|
-
- Default: `true` when
|
|
621
|
+
- Default: `true` when using `defineOgImage`, `false` when dynamic
|
|
622
|
+
|
|
623
|
+
Controls the prerendering of the image. A non-static image is one that will be generated at runtime and not cached.
|
|
405
624
|
|
|
406
625
|
|
|
407
626
|
## OgImageScreenshot / defineOgImageScreenshot
|
|
@@ -495,13 +714,13 @@ defineOgImageScreenshot({
|
|
|
495
714
|
|
|
496
715
|
## Module Config
|
|
497
716
|
|
|
498
|
-
### `
|
|
717
|
+
### `siteUrl`
|
|
499
718
|
|
|
500
719
|
- Type: `string`
|
|
501
720
|
- Default: `undefined`
|
|
502
721
|
- Required: `true`
|
|
503
722
|
|
|
504
|
-
The
|
|
723
|
+
The site URL of your site. This is required when prerendering to generate the absolute path of the `og:image`.
|
|
505
724
|
|
|
506
725
|
### `defaults`
|
|
507
726
|
|
|
@@ -511,15 +730,6 @@ The host of your site. This is required to generate the absolute path of the `og
|
|
|
511
730
|
|
|
512
731
|
The default options to use when generating images.
|
|
513
732
|
|
|
514
|
-
### `forcePrerender`
|
|
515
|
-
|
|
516
|
-
- Type: `boolean`
|
|
517
|
-
- Default: `false`
|
|
518
|
-
- Required: `false`
|
|
519
|
-
|
|
520
|
-
This is enabled when you run `nuxi generate`. It forces all OG images to be pre-rendered as the server is not available to generate
|
|
521
|
-
runtime images.
|
|
522
|
-
|
|
523
733
|
### `fonts`
|
|
524
734
|
|
|
525
735
|
- Type: ``${string}:${number}`[]`
|
|
@@ -546,16 +756,21 @@ export default defineNuxtConfig({
|
|
|
546
756
|
|
|
547
757
|
Options to pass to Satori when generating images. See the [Satori docs](https://github.com/vercel/satori).
|
|
548
758
|
|
|
549
|
-
### `
|
|
759
|
+
### `runtimeSatori`
|
|
550
760
|
|
|
551
761
|
- Type: `boolean`
|
|
552
|
-
- Default: `
|
|
553
|
-
|
|
762
|
+
- Default: `true`
|
|
763
|
+
|
|
764
|
+
Whether to use Satori at runtime. This is useful to disable if you're prerendering all your images.
|
|
765
|
+
|
|
766
|
+
### `runtimeBrowser`
|
|
767
|
+
|
|
768
|
+
- Type: `boolean`
|
|
769
|
+
- Default: `process.dev`
|
|
554
770
|
|
|
555
|
-
|
|
556
|
-
|
|
771
|
+
Whether to use Playwright at runtime. You will need to enable this for production environments and ensure you are using
|
|
772
|
+
a supported nitro preset and have the required dependencies.
|
|
557
773
|
|
|
558
|
-
This is experimental and may not work in all environments.
|
|
559
774
|
|
|
560
775
|
## Examples
|
|
561
776
|
|
package/dist/client/200.html
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
2
|
<html >
|
|
3
3
|
<head><meta charset="utf-8">
|
|
4
|
-
<meta name="viewport" content="width=device-width, initial-scale=1"><link rel="modulepreload" as="script" crossorigin href="/__nuxt_og_image__/client/_nuxt/entry.
|
|
4
|
+
<meta name="viewport" content="width=device-width, initial-scale=1"><link rel="modulepreload" as="script" crossorigin href="/__nuxt_og_image__/client/_nuxt/entry.212e85d9.js"><link rel="preload" as="style" href="/__nuxt_og_image__/client/_nuxt/entry.1311cc29.css"><link rel="prefetch" as="style" href="/__nuxt_og_image__/client/_nuxt/error-404.f3dd5020.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt_og_image__/client/_nuxt/error-404.0875e3f6.js"><link rel="prefetch" as="style" href="/__nuxt_og_image__/client/_nuxt/error-500.06915589.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt_og_image__/client/_nuxt/error-500.f06aa28f.js"><link rel="stylesheet" href="/__nuxt_og_image__/client/_nuxt/entry.1311cc29.css"><script>"use strict";(()=>{const a=window,e=document.documentElement,m=["dark","light"],c=window.localStorage.getItem("nuxt-color-mode")||"system";let n=c==="system"?f():c;const l=e.getAttribute("data-color-mode-forced");l&&(n=l),i(n),a["__NUXT_COLOR_MODE__"]={preference:c,value:n,getColorScheme:f,addColorScheme:i,removeColorScheme:d};function i(o){const t=""+o+"",s="";e.classList?e.classList.add(t):e.className+=" "+t,s&&e.setAttribute("data-"+s,o)}function d(o){const t=""+o+"",s="";e.classList?e.classList.remove(t):e.className=e.className.replace(new RegExp(t,"g"),""),s&&e.removeAttribute("data-"+s)}function r(o){return a.matchMedia("(prefers-color-scheme"+o+")")}function f(){if(a.matchMedia&&r("").media!=="not all"){for(const o of m)if(r(":"+o).matches)return o}return"light"}})();
|
|
5
5
|
</script></head>
|
|
6
|
-
<body ><div id="__nuxt"></div><script>window.__NUXT__={
|
|
6
|
+
<body ><div id="__nuxt"><svg class="nuxt-spa-loading" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 37 25" fill="none" width="80"><path d="M24.236 22.006h10.742L25.563 5.822l-8.979 14.31a4 4 0 0 1-3.388 1.874H2.978l11.631-20 5.897 10.567"></path></svg><style>.nuxt-spa-loading{position:fixed;top:50%;left:50%;transform:translate(-50%, -50%)}.nuxt-spa-loading>path{fill:none;stroke:#00DC82;stroke-width:4px;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:128;stroke-dashoffset:128;animation:nuxt-spa-loading-move 3s linear infinite}@keyframes nuxt-spa-loading-move{100%{stroke-dashoffset:-128}}</style></div><script type="application/json" id="__NUXT_DATA__" data-ssr="false">[{"_errors":1,"serverRendered":2,"data":3,"state":4},{},false,{},{}]</script><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt_og_image__/client",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="module" src="/__nuxt_og_image__/client/_nuxt/entry.212e85d9.js" crossorigin></script></body>
|
|
7
7
|
</html>
|
package/dist/client/404.html
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
2
|
<html >
|
|
3
3
|
<head><meta charset="utf-8">
|
|
4
|
-
<meta name="viewport" content="width=device-width, initial-scale=1"><link rel="modulepreload" as="script" crossorigin href="/__nuxt_og_image__/client/_nuxt/entry.
|
|
4
|
+
<meta name="viewport" content="width=device-width, initial-scale=1"><link rel="modulepreload" as="script" crossorigin href="/__nuxt_og_image__/client/_nuxt/entry.212e85d9.js"><link rel="preload" as="style" href="/__nuxt_og_image__/client/_nuxt/entry.1311cc29.css"><link rel="prefetch" as="style" href="/__nuxt_og_image__/client/_nuxt/error-404.f3dd5020.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt_og_image__/client/_nuxt/error-404.0875e3f6.js"><link rel="prefetch" as="style" href="/__nuxt_og_image__/client/_nuxt/error-500.06915589.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt_og_image__/client/_nuxt/error-500.f06aa28f.js"><link rel="stylesheet" href="/__nuxt_og_image__/client/_nuxt/entry.1311cc29.css"><script>"use strict";(()=>{const a=window,e=document.documentElement,m=["dark","light"],c=window.localStorage.getItem("nuxt-color-mode")||"system";let n=c==="system"?f():c;const l=e.getAttribute("data-color-mode-forced");l&&(n=l),i(n),a["__NUXT_COLOR_MODE__"]={preference:c,value:n,getColorScheme:f,addColorScheme:i,removeColorScheme:d};function i(o){const t=""+o+"",s="";e.classList?e.classList.add(t):e.className+=" "+t,s&&e.setAttribute("data-"+s,o)}function d(o){const t=""+o+"",s="";e.classList?e.classList.remove(t):e.className=e.className.replace(new RegExp(t,"g"),""),s&&e.removeAttribute("data-"+s)}function r(o){return a.matchMedia("(prefers-color-scheme"+o+")")}function f(){if(a.matchMedia&&r("").media!=="not all"){for(const o of m)if(r(":"+o).matches)return o}return"light"}})();
|
|
5
5
|
</script></head>
|
|
6
|
-
<body ><div id="__nuxt"></div><script>window.__NUXT__={
|
|
6
|
+
<body ><div id="__nuxt"><svg class="nuxt-spa-loading" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 37 25" fill="none" width="80"><path d="M24.236 22.006h10.742L25.563 5.822l-8.979 14.31a4 4 0 0 1-3.388 1.874H2.978l11.631-20 5.897 10.567"></path></svg><style>.nuxt-spa-loading{position:fixed;top:50%;left:50%;transform:translate(-50%, -50%)}.nuxt-spa-loading>path{fill:none;stroke:#00DC82;stroke-width:4px;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:128;stroke-dashoffset:128;animation:nuxt-spa-loading-move 3s linear infinite}@keyframes nuxt-spa-loading-move{100%{stroke-dashoffset:-128}}</style></div><script type="application/json" id="__NUXT_DATA__" data-ssr="false">[{"_errors":1,"serverRendered":2,"data":3,"state":4},{},false,{},{}]</script><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt_og_image__/client",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="module" src="/__nuxt_og_image__/client/_nuxt/entry.212e85d9.js" crossorigin></script></body>
|
|
7
7
|
</html>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{g as r,H as u,I as p,n as t,o as l,c as _,s as f,_ as m}from"./entry.212e85d9.js";const d=r({__name:"IconCSS",props:{name:{type:String,required:!0},size:{type:String,default:""}},setup(a){const s=a;u(e=>({"193e663e":i.value}));const n=p();n?.nuxtIcon?.aliases;const c=t(()=>(n?.nuxtIcon?.aliases||{})[s.name]||s.name),i=t(()=>`url('https://api.iconify.design/${c.value.replace(":","/")}.svg')`),o=t(()=>{if(!s.size&&typeof n.nuxtIcon?.size=="boolean"&&!n.nuxtIcon?.size)return;const e=s.size||n.nuxtIcon?.size||"1em";return String(Number(e))===e?`${e}px`:e});return(e,x)=>(l(),_("span",{style:f({width:o.value,height:o.value})},null,4))}});const g=m(d,[["__scopeId","data-v-1172c8f8"]]);export{g as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
span[data-v-1172c8f8]{background-color:currentColor;display:inline-block;-webkit-mask-image:var(--193e663e);mask-image:var(--193e663e);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;vertical-align:middle}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
img[data-v-23ec6856]{height:auto!important;margin:0 auto;max-width:100%;transition:.4s ease-in-out;width:auto!important}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{g as p,r as c,k as m,l as r,n as u,q as d,o as g,c as f,s as y,_ as v}from"./entry.212e85d9.js";const x=p({__name:"ImageLoader",props:{src:String,aspectRatio:Number,description:String},setup(a){const s=a,n=c(),o=c(0);function i(e){const t=n.value,_=Date.now();t.src="",o.value=0,t.style.opacity="0",t.onload=()=>{t.style.opacity="1",o.value=Date.now()-_},t.src=e}m(()=>{r(()=>s.src,e=>{i(e)},{immediate:!0})});const l=u(()=>s.description.replace("%s",o.value.toString()));return r(l,e=>{d.value=e}),(e,t)=>(g(),f("img",{ref_key:"image",ref:n,class:"max-h-full border-1 border-light-500 rounded",style:y({aspectRatio:a.aspectRatio})},null,4))}});const S=v(x,[["__scopeId","data-v-23ec6856"]]);export{S as _};
|