nuxt-og-image 2.0.0-beta.6 → 2.0.0-beta.60
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 +311 -97
- package/dist/client/200.html +2 -2
- package/dist/client/404.html +2 -2
- package/dist/client/_nuxt/IconCSS.b41b9663.css +1 -0
- package/dist/client/_nuxt/IconCSS.c2e73ab2.js +1 -0
- package/dist/client/_nuxt/ImageLoader.7571516f.css +1 -0
- package/dist/client/_nuxt/ImageLoader.ed4bfccb.js +1 -0
- package/dist/client/_nuxt/entry.862302d7.css +1 -0
- package/dist/client/_nuxt/entry.f51ac6f7.js +7 -0
- package/dist/client/_nuxt/{error-404.1ff52902.js → error-404.a94c6c21.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.3955092a.js} +1 -1
- package/dist/client/_nuxt/index.17db8b1a.js +1 -0
- package/dist/client/_nuxt/index.403133d8.css +1 -0
- package/dist/client/_nuxt/options.3e6c211b.js +1 -0
- package/dist/client/_nuxt/png.23a5e57c.js +1 -0
- package/dist/client/_nuxt/{shiki.3a930bb8.js → shiki.2980d306.js} +1 -1
- package/dist/client/_nuxt/svg.a8bba1f1.js +1 -0
- package/dist/client/_nuxt/{vnodes.a799f183.js → vnodes.64d635d6.js} +1 -1
- 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 +401 -141
- 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 -3
- package/dist/runtime/components/OgImage/Cached.mjs +10 -0
- package/dist/runtime/components/{OgImageScreenshot.d.ts → OgImage/Screenshot.d.ts} +2 -4
- package/dist/runtime/components/{OgImageScreenshot.mjs → OgImage/Screenshot.mjs} +2 -2
- package/dist/runtime/components/{OgImageStatic.d.ts → OgImage/WithoutCache.d.ts} +2 -3
- package/dist/runtime/components/OgImage/WithoutCache.mjs +10 -0
- package/dist/runtime/components/OgImage/_OgImageDynamic.d.ts +7 -0
- package/dist/runtime/components/{OgImageDynamic.mjs → OgImage/_OgImageDynamic.mjs} +3 -3
- package/dist/runtime/components/OgImage/_OgImageStatic.d.ts +7 -0
- package/dist/runtime/components/{OgImageStatic.mjs → OgImage/_OgImageStatic.mjs} +3 -3
- package/dist/runtime/components/OgImage/index.d.ts +4 -0
- package/dist/runtime/components/OgImage/index.mjs +9 -0
- package/dist/runtime/components/OgImageTemplate/Fallback.vue +155 -0
- package/dist/runtime/composables/defineOgImage.d.ts +12 -4
- package/dist/runtime/composables/defineOgImage.mjs +46 -20
- 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 +6 -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 +100 -25
- 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 +3 -2
- package/dist/runtime/nitro/utils-pure.mjs +9 -10
- package/dist/runtime/nitro/utils.d.ts +11 -11
- package/dist/runtime/nitro/utils.mjs +68 -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 +38 -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/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/dist/module.mjs
CHANGED
|
@@ -1,29 +1,34 @@
|
|
|
1
1
|
import { readFile, writeFile } from 'node:fs/promises';
|
|
2
|
-
import { defineNuxtModule, createResolver,
|
|
2
|
+
import { useNuxt, addTemplate, defineNuxtModule, useLogger, createResolver, installModule, addServerHandler, addImports, addComponent, addServerPlugin } from '@nuxt/kit';
|
|
3
3
|
import { execa } from 'execa';
|
|
4
4
|
import chalk from 'chalk';
|
|
5
5
|
import defu from 'defu';
|
|
6
6
|
import { toRouteMatcher, createRouter } from 'radix3';
|
|
7
|
-
import { joinURL } from 'ufo';
|
|
8
|
-
import { resolve, relative } from 'pathe';
|
|
7
|
+
import { withBase, joinURL } from 'ufo';
|
|
8
|
+
import { resolve, relative, dirname } from 'pathe';
|
|
9
9
|
import { tinyws } from 'tinyws';
|
|
10
10
|
import sirv from 'sirv';
|
|
11
11
|
import { pathExists, copy, mkdirp } from 'fs-extra';
|
|
12
|
-
import {
|
|
12
|
+
import { globby } from 'globby';
|
|
13
|
+
import { updateSiteConfig, requireSiteConfig } from 'nuxt-site-config-kit';
|
|
13
14
|
import playwrightCore from 'playwright-core';
|
|
14
15
|
import { existsSync } from 'node:fs';
|
|
15
16
|
import { createBirpcGroup } from 'birpc';
|
|
16
17
|
import { stringify, parse } from 'flatted';
|
|
18
|
+
import { addDependency } from 'nypm';
|
|
19
|
+
import { provider } from 'std-env';
|
|
17
20
|
|
|
18
21
|
async function createBrowser() {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
if (process.dev || process.env.prerender) {
|
|
23
|
+
try {
|
|
24
|
+
const { Launcher } = await import(String("chrome-launcher"));
|
|
25
|
+
const chromePath = Launcher.getFirstInstallation();
|
|
26
|
+
return await playwrightCore.chromium.launch({
|
|
27
|
+
headless: true,
|
|
28
|
+
executablePath: chromePath
|
|
29
|
+
});
|
|
30
|
+
} catch (e) {
|
|
31
|
+
}
|
|
27
32
|
}
|
|
28
33
|
try {
|
|
29
34
|
return await playwrightCore.chromium.launch({
|
|
@@ -54,9 +59,9 @@ async function screenshot(browser, options) {
|
|
|
54
59
|
width: options.width || 1200,
|
|
55
60
|
height: options.height || 630
|
|
56
61
|
});
|
|
57
|
-
const isHtml = options.path
|
|
62
|
+
const isHtml = options.html || options.path?.startsWith("html:");
|
|
58
63
|
if (isHtml) {
|
|
59
|
-
const html = options.html || options.path
|
|
64
|
+
const html = options.html || options.path?.substring(5);
|
|
60
65
|
await page.evaluate((html2) => {
|
|
61
66
|
document.open("text/html");
|
|
62
67
|
document.write(html2);
|
|
@@ -65,10 +70,13 @@ async function screenshot(browser, options) {
|
|
|
65
70
|
await page.waitForLoadState("networkidle");
|
|
66
71
|
} else {
|
|
67
72
|
await page.goto(`${options.host}${options.path}`, {
|
|
68
|
-
timeout: 1e4,
|
|
73
|
+
timeout: process.env.prerender || process.dev ? 1e4 : 3500,
|
|
69
74
|
waitUntil: "networkidle"
|
|
70
75
|
});
|
|
71
76
|
}
|
|
77
|
+
const screenshotOptions = {
|
|
78
|
+
timeout: process.env.prerender || process.dev ? 1e4 : 3500
|
|
79
|
+
};
|
|
72
80
|
if (options.delay)
|
|
73
81
|
await page.waitForTimeout(options.delay);
|
|
74
82
|
if (options.mask) {
|
|
@@ -78,8 +86,10 @@ async function screenshot(browser, options) {
|
|
|
78
86
|
}, options.mask);
|
|
79
87
|
}
|
|
80
88
|
if (options.selector)
|
|
81
|
-
return await page.locator(options.selector).screenshot();
|
|
82
|
-
|
|
89
|
+
return await page.locator(options.selector).screenshot(screenshotOptions);
|
|
90
|
+
const screenshot2 = await page.screenshot(screenshotOptions);
|
|
91
|
+
await page.close();
|
|
92
|
+
return screenshot2;
|
|
83
93
|
}
|
|
84
94
|
|
|
85
95
|
function setupPlaygroundRPC(nuxt, config) {
|
|
@@ -113,7 +123,7 @@ function setupPlaygroundRPC(nuxt, config) {
|
|
|
113
123
|
const birpc = createBirpcGroup(serverFunctions, []);
|
|
114
124
|
nuxt.hook("builder:watch", (e, path) => {
|
|
115
125
|
if (e === "change")
|
|
116
|
-
birpc.
|
|
126
|
+
birpc.broadcast.refresh.asEvent(path);
|
|
117
127
|
});
|
|
118
128
|
const middleware = async (req, res) => {
|
|
119
129
|
if (req.ws) {
|
|
@@ -164,13 +174,15 @@ function getBodyJson(req) {
|
|
|
164
174
|
});
|
|
165
175
|
}
|
|
166
176
|
|
|
167
|
-
function
|
|
177
|
+
function decodeHtml(html) {
|
|
178
|
+
return html.replace(/</g, "<").replace(/>/g, ">").replace(/&/g, "&").replace(/¢/g, "\xA2").replace(/£/g, "\xA3").replace(/¥/g, "\xA5").replace(/€/g, "\u20AC").replace(/©/g, "\xA9").replace(/®/g, "\xAE").replace(/"/g, '"').replace(/'/g, "'").replace(/'/g, "'").replace(///g, "/").replace(/&#([0-9]+);/g, (full, int) => {
|
|
179
|
+
return String.fromCharCode(Number.parseInt(int));
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
function decodeObjectHtmlEntities(obj) {
|
|
168
183
|
Object.entries(obj).forEach(([key, value]) => {
|
|
169
|
-
if (typeof value === "string")
|
|
170
|
-
obj[key] = value
|
|
171
|
-
return String.fromCharCode(parseInt(int));
|
|
172
|
-
});
|
|
173
|
-
}
|
|
184
|
+
if (typeof value === "string")
|
|
185
|
+
obj[key] = decodeHtml(value);
|
|
174
186
|
});
|
|
175
187
|
return obj;
|
|
176
188
|
}
|
|
@@ -194,54 +206,207 @@ function extractOgImageOptions(html) {
|
|
|
194
206
|
else
|
|
195
207
|
options.description = html.match(/<meta name="description" content="(.*?)">/)?.[1];
|
|
196
208
|
}
|
|
197
|
-
return
|
|
209
|
+
return decodeObjectHtmlEntities(options);
|
|
198
210
|
}
|
|
199
211
|
return false;
|
|
200
212
|
}
|
|
201
|
-
|
|
202
|
-
|
|
213
|
+
|
|
214
|
+
const SVG2PNGWasmPlaceholder = '"/* NUXT_OG_IMAGE_SVG2PNG_WASM */"';
|
|
215
|
+
const YogaWasmPlaceholder = '"/* NUXT_OG_IMAGE_YOGA_WASM */"';
|
|
216
|
+
const ReSVGWasmPlaceholder = '"/* NUXT_OG_IMAGE_RESVG_WASM */"';
|
|
217
|
+
const Wasms = [
|
|
218
|
+
{
|
|
219
|
+
placeholder: SVG2PNGWasmPlaceholder,
|
|
220
|
+
path: "svg2png/svg2png.wasm",
|
|
221
|
+
file: "svg2png.wasm"
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
placeholder: ReSVGWasmPlaceholder,
|
|
225
|
+
path: "resvg/resvg.wasm",
|
|
226
|
+
file: "resvg.wasm"
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
placeholder: YogaWasmPlaceholder,
|
|
230
|
+
path: "yoga/yoga.wasm",
|
|
231
|
+
file: "yoga.wasm"
|
|
232
|
+
}
|
|
233
|
+
];
|
|
234
|
+
const DefaultRuntimeCompatibility = {
|
|
235
|
+
// node-server runtime
|
|
236
|
+
browser: "playwright",
|
|
237
|
+
satori: "default",
|
|
238
|
+
wasm: "fetch",
|
|
239
|
+
png: "resvg-node"
|
|
240
|
+
};
|
|
241
|
+
const RuntimeCompatibility = {
|
|
242
|
+
"nitro-dev": {
|
|
243
|
+
wasm: "fetch",
|
|
244
|
+
browser: "universal"
|
|
245
|
+
},
|
|
246
|
+
"stackblitz": {
|
|
247
|
+
browser: false,
|
|
248
|
+
satori: "yoga-wasm",
|
|
249
|
+
wasm: "inline",
|
|
250
|
+
png: "resvg-wasm"
|
|
251
|
+
},
|
|
252
|
+
"netlify": {
|
|
253
|
+
browser: "lambda",
|
|
254
|
+
wasm: "inline"
|
|
255
|
+
},
|
|
256
|
+
"netlify-edge": {
|
|
257
|
+
wasm: "inline",
|
|
258
|
+
png: "resvg-wasm"
|
|
259
|
+
},
|
|
260
|
+
"vercel": {
|
|
261
|
+
// exceeds 50mb limit
|
|
262
|
+
browser: false
|
|
263
|
+
},
|
|
264
|
+
"vercel-edge": {
|
|
265
|
+
browser: false,
|
|
266
|
+
wasm: "import",
|
|
267
|
+
wasmImportQuery: "?module",
|
|
268
|
+
png: "resvg-wasm"
|
|
269
|
+
},
|
|
270
|
+
"cloudflare-pages": {
|
|
271
|
+
browser: false,
|
|
272
|
+
wasm: "import",
|
|
273
|
+
png: "resvg-wasm"
|
|
274
|
+
},
|
|
275
|
+
"cloudflare": {
|
|
276
|
+
browser: false,
|
|
277
|
+
wasm: "import"
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
const autodetectableProviders = {
|
|
282
|
+
azure_static: "azure",
|
|
283
|
+
cloudflare_pages: "cloudflare-pages",
|
|
284
|
+
netlify: "netlify",
|
|
285
|
+
stormkit: "stormkit",
|
|
286
|
+
vercel: "vercel",
|
|
287
|
+
cleavr: "cleavr"
|
|
288
|
+
};
|
|
289
|
+
const autodetectableStaticProviders = {
|
|
290
|
+
netlify: "netlify-static",
|
|
291
|
+
vercel: "vercel-static"
|
|
292
|
+
};
|
|
293
|
+
function detectTarget(options = {}) {
|
|
294
|
+
return options?.static ? autodetectableStaticProviders[provider] : autodetectableProviders[provider];
|
|
295
|
+
}
|
|
296
|
+
function getNitroPreset(nuxt) {
|
|
297
|
+
return process.env.NITRO_PRESET || nuxt.options.nitro.preset || detectTarget() || "node-server";
|
|
298
|
+
}
|
|
299
|
+
function getNitroProviderCompatibility(nuxt) {
|
|
300
|
+
if (provider === "stackblitz")
|
|
301
|
+
return defu(RuntimeCompatibility.stackblitz, DefaultRuntimeCompatibility);
|
|
302
|
+
if (nuxt.options.dev || nuxt.options._prepare || nuxt.options._generate) {
|
|
303
|
+
return defu({
|
|
304
|
+
wasm: "fetch",
|
|
305
|
+
browser: "universal"
|
|
306
|
+
}, DefaultRuntimeCompatibility);
|
|
307
|
+
}
|
|
308
|
+
const target = getNitroPreset(nuxt);
|
|
309
|
+
const compatibility = RuntimeCompatibility[target];
|
|
310
|
+
if (compatibility === false)
|
|
311
|
+
return false;
|
|
312
|
+
return defu(compatibility || {}, DefaultRuntimeCompatibility);
|
|
313
|
+
}
|
|
314
|
+
function ensureDependencies(nuxt, dep) {
|
|
315
|
+
return Promise.all(dep.map((d) => {
|
|
316
|
+
return addDependency(d, { cwd: nuxt.options.rootDir });
|
|
317
|
+
}));
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
function extendTypes(module, template) {
|
|
321
|
+
const nuxt = useNuxt();
|
|
322
|
+
addTemplate({
|
|
323
|
+
filename: `${module}.d.ts`,
|
|
324
|
+
getContents: () => {
|
|
325
|
+
const s = template();
|
|
326
|
+
return `// Generated by ${module}
|
|
327
|
+
${s}
|
|
328
|
+
export {}
|
|
329
|
+
`;
|
|
330
|
+
}
|
|
331
|
+
});
|
|
332
|
+
nuxt.hooks.hook("prepare:types", ({ references }) => {
|
|
333
|
+
references.push({ path: resolve(nuxt.options.buildDir, `${module}.d.ts`) });
|
|
334
|
+
});
|
|
203
335
|
}
|
|
204
336
|
|
|
205
337
|
const PATH = "/__nuxt_og_image__";
|
|
206
338
|
const PATH_ENTRY = `${PATH}/entry`;
|
|
207
339
|
const PATH_PLAYGROUND = `${PATH}/client`;
|
|
208
|
-
const edgeProvidersSupported = [
|
|
209
|
-
"cloudflare",
|
|
210
|
-
"vercel-edge",
|
|
211
|
-
"netlify-edge"
|
|
212
|
-
];
|
|
213
340
|
const module = defineNuxtModule({
|
|
214
341
|
meta: {
|
|
215
342
|
name: "nuxt-og-image",
|
|
216
343
|
compatibility: {
|
|
217
|
-
nuxt: "^3.
|
|
344
|
+
nuxt: "^3.6.1",
|
|
218
345
|
bridge: false
|
|
219
346
|
},
|
|
220
347
|
configKey: "ogImage"
|
|
221
348
|
},
|
|
222
349
|
defaults(nuxt) {
|
|
223
|
-
const siteUrl = process.env.NUXT_PUBLIC_SITE_URL || process.env.NUXT_SITE_URL || nuxt.options.runtimeConfig.public?.siteUrl || nuxt.options.runtimeConfig.siteUrl;
|
|
224
350
|
return {
|
|
225
|
-
|
|
226
|
-
forcePrerender: !nuxt.options.dev && nuxt.options._generate,
|
|
227
|
-
siteUrl,
|
|
351
|
+
enabled: true,
|
|
228
352
|
defaults: {
|
|
229
|
-
component: "
|
|
353
|
+
component: "OgImageTemplateFallback",
|
|
230
354
|
width: 1200,
|
|
231
|
-
height: 630
|
|
355
|
+
height: 630,
|
|
356
|
+
// default is to cache the image for 24 hours
|
|
357
|
+
cache: true,
|
|
358
|
+
cacheTtl: 24 * 60 * 60 * 1e3
|
|
232
359
|
},
|
|
233
|
-
|
|
234
|
-
|
|
360
|
+
componentDirs: ["OgImage", "OgImageTemplate"],
|
|
361
|
+
runtimeSatori: true,
|
|
362
|
+
runtimeBrowser: nuxt.options.dev,
|
|
235
363
|
fonts: [],
|
|
364
|
+
runtimeCacheStorage: true,
|
|
236
365
|
satoriOptions: {},
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
playground: process.env.NODE_ENV === "development" || nuxt.options.dev
|
|
366
|
+
playground: process.env.NODE_ENV === "development" || nuxt.options.dev,
|
|
367
|
+
debug: false
|
|
240
368
|
};
|
|
241
369
|
},
|
|
242
370
|
async setup(config, nuxt) {
|
|
243
|
-
const
|
|
244
|
-
|
|
371
|
+
const logger = useLogger("nuxt-og-image");
|
|
372
|
+
logger.level = config.debug || nuxt.options.debug ? 4 : 3;
|
|
373
|
+
if (config.enabled === false) {
|
|
374
|
+
logger.debug("The module is disabled, skipping setup.");
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
const { resolve, resolvePath } = createResolver(import.meta.url);
|
|
378
|
+
logger.debug("Using Nitro preset", getNitroPreset(nuxt));
|
|
379
|
+
const nitroCompatibility = getNitroProviderCompatibility(nuxt);
|
|
380
|
+
logger.debug("Nitro compatibility", nitroCompatibility);
|
|
381
|
+
const nitroTarget = process.env.NITRO_PRESET || nuxt.options.nitro.preset;
|
|
382
|
+
if (!nitroCompatibility) {
|
|
383
|
+
logger.warn(`\`nuxt-og-image\` does not support the nitro target \`${nitroTarget}\`. Please make an issue. `);
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
if (!nitroCompatibility.browser && config.runtimeBrowser) {
|
|
387
|
+
config.runtimeBrowser = false;
|
|
388
|
+
logger.warn(`\`nuxt-og-image\` does not support the nitro target \`${nitroTarget}\` with the runtime browser. Set runtimeBrowser: false to stop seeing this.`);
|
|
389
|
+
}
|
|
390
|
+
if (config.runtimeBrowser && nitroCompatibility.browser === "lambda") {
|
|
391
|
+
logger.info(`\`nuxt-og-image\` is deploying to nitro target \`${nitroTarget}\` that installs extra dependencies.`);
|
|
392
|
+
await ensureDependencies(nuxt, ["puppeteer-core@14.1.1", "@sparticuz/chrome-aws-lambda@14.1.1"]);
|
|
393
|
+
}
|
|
394
|
+
await installModule(await resolvePath("nuxt-site-config"));
|
|
395
|
+
await updateSiteConfig({
|
|
396
|
+
_context: "nuxt-og-image:config",
|
|
397
|
+
url: config.siteUrl || config.host
|
|
398
|
+
});
|
|
399
|
+
requireSiteConfig("nuxt-og-image", {
|
|
400
|
+
url: "Required to generate absolute URLs for the og:image."
|
|
401
|
+
}, { prerender: true });
|
|
402
|
+
nuxt.options.nitro.storage = nuxt.options.nitro.storage || {};
|
|
403
|
+
if (nuxt.options._generate) {
|
|
404
|
+
nuxt.options.nitro.storage["og-image"] = {
|
|
405
|
+
driver: "memory"
|
|
406
|
+
};
|
|
407
|
+
} else if (config.runtimeCacheStorage && !nuxt.options.dev && typeof config.runtimeCacheStorage === "object") {
|
|
408
|
+
nuxt.options.nitro.storage["og-image"] = config.runtimeCacheStorage;
|
|
409
|
+
}
|
|
245
410
|
if (!config.fonts.length)
|
|
246
411
|
config.fonts = ["Inter:400", "Inter:700"];
|
|
247
412
|
const distResolve = (p) => {
|
|
@@ -251,34 +416,27 @@ const module = defineNuxtModule({
|
|
|
251
416
|
return resolve(`../dist/${p}`);
|
|
252
417
|
};
|
|
253
418
|
nuxt.options.experimental.componentIslands = true;
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
getContents: () => {
|
|
257
|
-
return `// Generated by nuxt-og-image
|
|
258
|
-
interface NuxtOgImageNitroRules {
|
|
419
|
+
extendTypes("nuxt-og-image", () => {
|
|
420
|
+
return `interface NuxtOgImageNitroRules {
|
|
259
421
|
ogImage?: false | Record<string, any>
|
|
260
422
|
}
|
|
261
423
|
declare module 'nitropack' {
|
|
262
424
|
interface NitroRouteRules extends NuxtOgImageNitroRules {}
|
|
263
425
|
interface NitroRouteConfig extends NuxtOgImageNitroRules {}
|
|
264
|
-
}
|
|
265
|
-
export {}
|
|
266
|
-
`;
|
|
267
|
-
}
|
|
268
|
-
});
|
|
269
|
-
nuxt.hooks.hook("prepare:types", ({ references }) => {
|
|
270
|
-
references.push({ path: resolve(nuxt.options.buildDir, "nuxt-og-image.d.ts") });
|
|
426
|
+
}`;
|
|
271
427
|
});
|
|
272
428
|
addServerHandler({
|
|
273
429
|
lazy: true,
|
|
274
430
|
handler: resolve("./runtime/nitro/middleware/og.png")
|
|
275
431
|
});
|
|
276
|
-
["html", "options", "svg", "vnode", "font"].forEach((type) => {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
432
|
+
["html", "options", "svg", "vnode", "font", "debug"].forEach((type) => {
|
|
433
|
+
if (type !== "debug" || config.debug) {
|
|
434
|
+
addServerHandler({
|
|
435
|
+
lazy: true,
|
|
436
|
+
route: `/api/og-image-${type}`,
|
|
437
|
+
handler: resolve(`./runtime/nitro/routes/${type}`)
|
|
438
|
+
});
|
|
439
|
+
}
|
|
282
440
|
});
|
|
283
441
|
nuxt.hook("devtools:customTabs", (iframeTabs) => {
|
|
284
442
|
iframeTabs.push({
|
|
@@ -307,7 +465,17 @@ export {}
|
|
|
307
465
|
});
|
|
308
466
|
}
|
|
309
467
|
nuxt.options.optimization.treeShake.composables.client["nuxt-og-image"] = [];
|
|
310
|
-
[
|
|
468
|
+
[
|
|
469
|
+
// deprecated
|
|
470
|
+
"Dynamic",
|
|
471
|
+
"Static",
|
|
472
|
+
// new
|
|
473
|
+
"index",
|
|
474
|
+
"Cached",
|
|
475
|
+
"WithoutCache",
|
|
476
|
+
"Screenshot"
|
|
477
|
+
].forEach((name) => {
|
|
478
|
+
name = name === "index" ? "defineOgImage" : `defineOgImage${name}`;
|
|
311
479
|
addImports({
|
|
312
480
|
name,
|
|
313
481
|
from: resolve("./runtime/composables/defineOgImage")
|
|
@@ -315,104 +483,197 @@ export {}
|
|
|
315
483
|
nuxt.options.optimization.treeShake.composables.client["nuxt-og-image"].push(name);
|
|
316
484
|
});
|
|
317
485
|
await addComponent({
|
|
318
|
-
name: "
|
|
319
|
-
filePath: resolve("./runtime/components/
|
|
486
|
+
name: "OgImageTemplateFallback",
|
|
487
|
+
filePath: resolve("./runtime/components/OgImageTemplate/Fallback.vue"),
|
|
320
488
|
island: true
|
|
321
489
|
});
|
|
322
|
-
[
|
|
490
|
+
[
|
|
491
|
+
// deprecated
|
|
492
|
+
"Static",
|
|
493
|
+
"Dynamic",
|
|
494
|
+
// new
|
|
495
|
+
"index",
|
|
496
|
+
"Cached",
|
|
497
|
+
"WithoutCache",
|
|
498
|
+
"Screenshot"
|
|
499
|
+
].forEach((name) => {
|
|
323
500
|
addComponent({
|
|
324
|
-
name
|
|
325
|
-
filePath: resolve(`./runtime/components/${name}`)
|
|
501
|
+
name: name === "index" ? "OgImage" : `OgImage${name}`,
|
|
502
|
+
filePath: resolve(`./runtime/components/OgImage/${name}`)
|
|
326
503
|
});
|
|
327
504
|
});
|
|
505
|
+
const ogImageComponents = [];
|
|
506
|
+
nuxt.hook("components:extend", (components) => {
|
|
507
|
+
components.forEach((component) => {
|
|
508
|
+
let valid = false;
|
|
509
|
+
config.componentDirs.forEach((dir) => {
|
|
510
|
+
if (component.pascalName.startsWith(dir) || component.kebabName.startsWith(dir))
|
|
511
|
+
valid = true;
|
|
512
|
+
});
|
|
513
|
+
if (valid) {
|
|
514
|
+
component.island = true;
|
|
515
|
+
component.mode = "server";
|
|
516
|
+
ogImageComponents.push({ pascalName: component.pascalName, kebabName: component.kebabName });
|
|
517
|
+
}
|
|
518
|
+
});
|
|
519
|
+
});
|
|
520
|
+
addTemplate({
|
|
521
|
+
filename: "og-image-component-names.mjs",
|
|
522
|
+
getContents() {
|
|
523
|
+
return `export const componentNames = ${JSON.stringify(ogImageComponents)}`;
|
|
524
|
+
},
|
|
525
|
+
options: { mode: "server" }
|
|
526
|
+
});
|
|
328
527
|
const runtimeDir = resolve("./runtime");
|
|
329
528
|
nuxt.options.build.transpile.push(runtimeDir);
|
|
330
|
-
|
|
331
|
-
const
|
|
332
|
-
|
|
333
|
-
|
|
529
|
+
addServerPlugin(resolve("./runtime/nitro/plugins/prerender"));
|
|
530
|
+
const customAssetDirs = [
|
|
531
|
+
// allows us to show custom error images
|
|
532
|
+
resolve("./runtime/public-assets")
|
|
334
533
|
];
|
|
534
|
+
if (config.runtimeSatori) {
|
|
535
|
+
if (config.fonts.includes("Inter:400"))
|
|
536
|
+
customAssetDirs.push(resolve("./runtime/public-assets-optional/inter-font"));
|
|
537
|
+
if (nitroCompatibility.png === "resvg-wasm" && nitroCompatibility.wasm === "fetch")
|
|
538
|
+
customAssetDirs.push(resolve("./runtime/public-assets-optional/resvg"));
|
|
539
|
+
else if (nitroCompatibility.png === "svg2png" && nitroCompatibility.wasm === "fetch")
|
|
540
|
+
customAssetDirs.push(resolve("./runtime/public-assets-optional/svg2png"));
|
|
541
|
+
if (nitroCompatibility.satori === "yoga-wasm")
|
|
542
|
+
customAssetDirs.push(resolve("./runtime/public-assets-optional/yoga"));
|
|
543
|
+
}
|
|
335
544
|
nuxt.hooks.hook("modules:done", async () => {
|
|
336
545
|
nuxt.hooks.callHook("og-image:config", config);
|
|
337
|
-
nuxt.options.runtimeConfig["nuxt-og-image"] = {
|
|
546
|
+
nuxt.options.runtimeConfig["nuxt-og-image"] = {
|
|
547
|
+
satoriOptions: config.satoriOptions,
|
|
548
|
+
runtimeSatori: config.runtimeSatori,
|
|
549
|
+
runtimeBrowser: config.runtimeBrowser,
|
|
550
|
+
// @ts-expect-error runtime type
|
|
551
|
+
defaults: config.defaults,
|
|
552
|
+
// avoid adding credentials
|
|
553
|
+
runtimeCacheStorage: typeof config.runtimeCacheStorage === "boolean" ? "default" : config.runtimeCacheStorage.driver,
|
|
554
|
+
// convert the fonts to uniform type to fix ts issue
|
|
555
|
+
fonts: config.fonts.map((f) => {
|
|
556
|
+
if (typeof f === "string") {
|
|
557
|
+
const [name, weight] = f.split(":");
|
|
558
|
+
return {
|
|
559
|
+
name,
|
|
560
|
+
weight
|
|
561
|
+
};
|
|
562
|
+
}
|
|
563
|
+
return f;
|
|
564
|
+
}),
|
|
565
|
+
assetDirs: [
|
|
566
|
+
resolve(nuxt.options.srcDir, nuxt.options.dir.public),
|
|
567
|
+
...customAssetDirs,
|
|
568
|
+
// always add runtime dirs for prerendering to work, these are just used as scan roots
|
|
569
|
+
resolve("./runtime/public-assets-optional/inter-font"),
|
|
570
|
+
resolve("./runtime/public-assets-optional/resvg"),
|
|
571
|
+
resolve("./runtime/public-assets-optional/yoga"),
|
|
572
|
+
resolve("./runtime/public-assets-optional/svg2png")
|
|
573
|
+
]
|
|
574
|
+
};
|
|
338
575
|
});
|
|
339
|
-
const useSatoriWasm = provider === "stackblitz";
|
|
340
576
|
nuxt.hooks.hook("nitro:config", async (nitroConfig) => {
|
|
341
577
|
nitroConfig.externals = defu(nitroConfig.externals || {}, {
|
|
342
578
|
inline: [runtimeDir]
|
|
343
579
|
});
|
|
344
|
-
if (config.
|
|
580
|
+
if (config.runtimeBrowser) {
|
|
345
581
|
nitroConfig.alias = nitroConfig.alias || {};
|
|
346
582
|
nitroConfig.alias.electron = "unenv/runtime/mock/proxy-cjs";
|
|
347
583
|
nitroConfig.alias.bufferutil = "unenv/runtime/mock/proxy-cjs";
|
|
348
584
|
nitroConfig.alias["utf-8-validate"] = "unenv/runtime/mock/proxy-cjs";
|
|
349
585
|
}
|
|
350
586
|
nitroConfig.publicAssets = nitroConfig.publicAssets || [];
|
|
351
|
-
|
|
587
|
+
customAssetDirs.forEach((dir) => {
|
|
588
|
+
nitroConfig.publicAssets.push({ dir, maxAge: 31536e3 });
|
|
589
|
+
});
|
|
352
590
|
const providerPath = `${runtimeDir}/nitro/providers`;
|
|
353
|
-
if (config.
|
|
354
|
-
nitroConfig.virtual["#nuxt-og-image/browser"] =
|
|
355
|
-
|
|
356
|
-
|
|
591
|
+
if (config.runtimeBrowser) {
|
|
592
|
+
nitroConfig.virtual["#nuxt-og-image/browser"] = `
|
|
593
|
+
let browser
|
|
357
594
|
export default async function() {
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
` : `export default async function() {
|
|
361
|
-
return () => {}
|
|
595
|
+
browser = browser || await import('${providerPath}/browser/${nitroCompatibility.browser}').then((m) => m.default || m)
|
|
596
|
+
return browser
|
|
362
597
|
}
|
|
363
598
|
`;
|
|
364
599
|
}
|
|
365
|
-
if (config.
|
|
366
|
-
nitroConfig.virtual["#nuxt-og-image/satori"] = `import satori from '${providerPath}/satori/${
|
|
367
|
-
export default
|
|
600
|
+
if (config.runtimeSatori) {
|
|
601
|
+
nitroConfig.virtual["#nuxt-og-image/satori"] = `import satori from '${providerPath}/satori/${nitroCompatibility.satori}'
|
|
602
|
+
export default function() {
|
|
368
603
|
return satori
|
|
369
604
|
}`;
|
|
370
|
-
nitroConfig.virtual["#nuxt-og-image/
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
605
|
+
nitroConfig.virtual["#nuxt-og-image/png"] = `import png from '${providerPath}/png/${nitroCompatibility.png}'
|
|
606
|
+
export default function() {
|
|
607
|
+
return png
|
|
608
|
+
}
|
|
609
|
+
`;
|
|
375
610
|
}
|
|
376
611
|
nitroConfig.virtual["#nuxt-og-image/provider"] = `
|
|
377
|
-
import satori from '${relative(nuxt.options.rootDir, resolve("./runtime/nitro/renderers/satori"))}'
|
|
378
|
-
import browser from '${relative(nuxt.options.rootDir, resolve("./runtime/nitro/renderers/browser"))}'
|
|
612
|
+
${config.runtimeSatori ? `import satori from '${relative(nuxt.options.rootDir, resolve("./runtime/nitro/renderers/satori"))}'` : ""}
|
|
613
|
+
${config.runtimeBrowser ? `import browser from '${relative(nuxt.options.rootDir, resolve("./runtime/nitro/renderers/browser"))}'` : ""}
|
|
379
614
|
|
|
380
615
|
export async function useProvider(provider) {
|
|
381
616
|
if (provider === 'satori')
|
|
382
|
-
return satori
|
|
617
|
+
return ${config.runtimeSatori ? "satori" : "null"}
|
|
383
618
|
if (provider === 'browser')
|
|
384
|
-
return browser
|
|
619
|
+
return ${config.runtimeBrowser ? "browser" : "null"}
|
|
620
|
+
return null
|
|
385
621
|
}
|
|
386
622
|
`;
|
|
387
623
|
});
|
|
388
624
|
nuxt.hooks.hook("nitro:init", async (nitro) => {
|
|
389
625
|
let screenshotQueue = [];
|
|
390
626
|
nitro.hooks.hook("compiled", async (_nitro) => {
|
|
391
|
-
if (
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
627
|
+
if (!config.runtimeSatori || nuxt.options.dev)
|
|
628
|
+
return;
|
|
629
|
+
if (config.fonts.includes("Inter:400"))
|
|
630
|
+
await copy(resolve("./runtime/public-assets-optional/inter-font/inter-latin-ext-400-normal.woff"), resolve(_nitro.options.output.publicDir, "inter-latin-ext-400-normal.woff"));
|
|
631
|
+
if (config.fonts.includes("Inter:700"))
|
|
632
|
+
await copy(resolve("./runtime/public-assets-optional/inter-font/inter-latin-ext-700-normal.woff"), resolve(_nitro.options.output.publicDir, "inter-latin-ext-700-normal.woff"));
|
|
633
|
+
const configuredEntry = nitro.options.rollupConfig?.output.entryFileNames;
|
|
634
|
+
const wasmProviderPath = resolve(_nitro.options.output.serverDir, typeof configuredEntry === "string" ? configuredEntry : "index.mjs");
|
|
635
|
+
const paths = [wasmProviderPath];
|
|
636
|
+
const chunks = await globby([`${_nitro.options.output.serverDir}/chunks/**/*.mjs`], { absolute: true });
|
|
637
|
+
paths.push(...chunks);
|
|
638
|
+
for (const path of paths) {
|
|
639
|
+
if (!await pathExists(path))
|
|
640
|
+
continue;
|
|
641
|
+
let contents = await readFile(path, "utf-8");
|
|
642
|
+
let updated = false;
|
|
643
|
+
if (_nitro.options.preset.includes("vercel") && path === wasmProviderPath) {
|
|
644
|
+
contents = contents.replace(".cwd(),", '?.cwd || "/",');
|
|
645
|
+
updated = true;
|
|
398
646
|
}
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
647
|
+
if (_nitro.options.preset.includes("netlify") && path.endsWith("netlify.mjs")) {
|
|
648
|
+
const match = "// TODO: handle event.isBase64Encoded\n });";
|
|
649
|
+
contents = contents.replace(match, `${match}
|
|
650
|
+
|
|
651
|
+
const headers = normalizeOutgoingHeaders(r.headers);
|
|
652
|
+
// image buffers must be base64 encoded
|
|
653
|
+
if (Buffer.isBuffer(r.body) && headers["content-type"].startsWith("image/")) {
|
|
654
|
+
return {
|
|
655
|
+
statusCode: r.status,
|
|
656
|
+
headers,
|
|
657
|
+
body: r.body.toString("base64"),
|
|
658
|
+
isBase64Encoded: true
|
|
659
|
+
};
|
|
660
|
+
}`);
|
|
661
|
+
updated = true;
|
|
662
|
+
}
|
|
663
|
+
for (const wasm of Wasms) {
|
|
664
|
+
if (contents.includes(wasm.placeholder)) {
|
|
665
|
+
if (nitroCompatibility.wasm === "import") {
|
|
666
|
+
contents = contents.replace(wasm.placeholder, `import("./${wasm.file}${nitroCompatibility.wasmImportQuery || ""}").then(m => m.default || m)`);
|
|
667
|
+
await copy(resolve(`./runtime/public-assets-optional/${wasm.path}`), resolve(dirname(path), wasm.file));
|
|
668
|
+
} else if (nitroCompatibility.wasm === "inline") {
|
|
669
|
+
const wasmBuffer = await readFile(resolve(`./runtime/public-assets-optional/${wasm.path}`));
|
|
670
|
+
contents = contents.replace(wasm.placeholder, `Buffer.from("${wasmBuffer}", "base64")`);
|
|
671
|
+
}
|
|
672
|
+
updated = true;
|
|
414
673
|
}
|
|
415
674
|
}
|
|
675
|
+
if (updated)
|
|
676
|
+
await writeFile(path, contents, { encoding: "utf-8" });
|
|
416
677
|
}
|
|
417
678
|
});
|
|
418
679
|
const _routeRulesMatcher = toRouteMatcher(
|
|
@@ -425,7 +686,6 @@ export async function useProvider(provider) {
|
|
|
425
686
|
if (!html)
|
|
426
687
|
return;
|
|
427
688
|
const extractedOptions = extractOgImageOptions(html);
|
|
428
|
-
ctx.contents = stripOgImageOptions(html);
|
|
429
689
|
const routeRules = defu({}, ..._routeRulesMatcher.matchAll(ctx.route).reverse());
|
|
430
690
|
if (!extractedOptions || routeRules.ogImage === false)
|
|
431
691
|
return;
|
|
@@ -435,7 +695,7 @@ export async function useProvider(provider) {
|
|
|
435
695
|
...extractedOptions,
|
|
436
696
|
...routeRules.ogImage || {}
|
|
437
697
|
};
|
|
438
|
-
if ((nuxt.options._generate || entry.
|
|
698
|
+
if ((nuxt.options._generate || entry.cache) && entry.provider === "browser")
|
|
439
699
|
screenshotQueue.push(entry);
|
|
440
700
|
});
|
|
441
701
|
if (nuxt.options.dev)
|
|
@@ -444,21 +704,6 @@ export async function useProvider(provider) {
|
|
|
444
704
|
await nuxt.callHook("og-image:prerenderScreenshots", screenshotQueue);
|
|
445
705
|
if (screenshotQueue.length === 0)
|
|
446
706
|
return;
|
|
447
|
-
for (const entry of screenshotQueue) {
|
|
448
|
-
if (entry.route && Object.keys(entry).length === 1) {
|
|
449
|
-
const html = await $fetch(entry.route);
|
|
450
|
-
const extractedOptions = extractOgImageOptions(html);
|
|
451
|
-
const routeRules = defu({}, ..._routeRulesMatcher.matchAll(entry.route).reverse());
|
|
452
|
-
Object.assign(entry, {
|
|
453
|
-
// @ts-expect-error runtime
|
|
454
|
-
path: extractedOptions.component ? `/api/og-image-html?path=${entry.route}` : entry.route,
|
|
455
|
-
...extractedOptions,
|
|
456
|
-
...routeRules.ogImage || {}
|
|
457
|
-
});
|
|
458
|
-
}
|
|
459
|
-
if (entry.component)
|
|
460
|
-
entry.html = await $fetch(entry.path);
|
|
461
|
-
}
|
|
462
707
|
nitro.logger.info("Ensuring chromium install for og:image generation...");
|
|
463
708
|
const installChromeProcess = execa("npx", ["playwright", "install", "chromium"], {
|
|
464
709
|
stdio: "inherit"
|
|
@@ -485,12 +730,27 @@ export async function useProvider(provider) {
|
|
|
485
730
|
browser = await createBrowser();
|
|
486
731
|
if (browser) {
|
|
487
732
|
nitro.logger.info(`Prerendering ${screenshotQueue.length} og:image screenshots...`);
|
|
733
|
+
for (const entry of screenshotQueue) {
|
|
734
|
+
if (entry.route && Object.keys(entry).length === 1) {
|
|
735
|
+
const html = await $fetch(entry.route, { baseURL: withBase(nuxt.options.app.baseURL, host) });
|
|
736
|
+
const extractedOptions = extractOgImageOptions(html);
|
|
737
|
+
const routeRules = defu({}, ..._routeRulesMatcher.matchAll(entry.route).reverse());
|
|
738
|
+
Object.assign(entry, {
|
|
739
|
+
// @ts-expect-error runtime
|
|
740
|
+
path: extractedOptions.component ? `/api/og-image-html?path=${entry.route}` : entry.route,
|
|
741
|
+
...extractedOptions,
|
|
742
|
+
...routeRules.ogImage || {}
|
|
743
|
+
});
|
|
744
|
+
}
|
|
745
|
+
if (entry.component)
|
|
746
|
+
entry.html = await globalThis.$fetch(entry.path);
|
|
747
|
+
}
|
|
488
748
|
for (const k in screenshotQueue) {
|
|
489
749
|
const entry = screenshotQueue[k];
|
|
490
750
|
const start = Date.now();
|
|
491
751
|
let hasError = false;
|
|
492
|
-
const
|
|
493
|
-
const filename = joinURL(
|
|
752
|
+
const dirname2 = joinURL(nitro.options.output.publicDir, entry.route, "/__og_image__/");
|
|
753
|
+
const filename = joinURL(dirname2, "/og.png");
|
|
494
754
|
try {
|
|
495
755
|
const imgBuffer = await screenshot(browser, {
|
|
496
756
|
...config.defaults || {},
|
|
@@ -498,7 +758,7 @@ export async function useProvider(provider) {
|
|
|
498
758
|
host
|
|
499
759
|
});
|
|
500
760
|
try {
|
|
501
|
-
await mkdirp(
|
|
761
|
+
await mkdirp(dirname2);
|
|
502
762
|
} catch (e) {
|
|
503
763
|
}
|
|
504
764
|
await writeFile(filename, imgBuffer);
|
|
@@ -522,7 +782,7 @@ export async function useProvider(provider) {
|
|
|
522
782
|
}
|
|
523
783
|
screenshotQueue = [];
|
|
524
784
|
};
|
|
525
|
-
if (
|
|
785
|
+
if (nuxt.options._generate) {
|
|
526
786
|
nitro.hooks.hook("rollup:before", async () => {
|
|
527
787
|
await captureScreenshots();
|
|
528
788
|
});
|