nuxt-og-image 2.0.0-beta.6 → 2.0.0-beta.61
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 +402 -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 -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 +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,208 @@ 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
|
+
stackblitz: "stackblitz"
|
|
289
|
+
};
|
|
290
|
+
const autodetectableStaticProviders = {
|
|
291
|
+
netlify: "netlify-static",
|
|
292
|
+
vercel: "vercel-static"
|
|
293
|
+
};
|
|
294
|
+
function detectTarget(options = {}) {
|
|
295
|
+
return options?.static ? autodetectableStaticProviders[provider] : autodetectableProviders[provider];
|
|
296
|
+
}
|
|
297
|
+
function getNitroPreset(nuxt) {
|
|
298
|
+
return process.env.NITRO_PRESET || nuxt.options.nitro.preset || detectTarget() || "node-server";
|
|
299
|
+
}
|
|
300
|
+
function getNitroProviderCompatibility(nuxt) {
|
|
301
|
+
if (provider === "stackblitz")
|
|
302
|
+
return defu(RuntimeCompatibility.stackblitz, DefaultRuntimeCompatibility);
|
|
303
|
+
if (nuxt.options.dev || nuxt.options._prepare || nuxt.options._generate) {
|
|
304
|
+
return defu({
|
|
305
|
+
wasm: "fetch",
|
|
306
|
+
browser: "universal"
|
|
307
|
+
}, DefaultRuntimeCompatibility);
|
|
308
|
+
}
|
|
309
|
+
const target = getNitroPreset(nuxt);
|
|
310
|
+
const compatibility = RuntimeCompatibility[target];
|
|
311
|
+
if (compatibility === false)
|
|
312
|
+
return false;
|
|
313
|
+
return defu(compatibility || {}, DefaultRuntimeCompatibility);
|
|
314
|
+
}
|
|
315
|
+
function ensureDependencies(nuxt, dep) {
|
|
316
|
+
return Promise.all(dep.map((d) => {
|
|
317
|
+
return addDependency(d, { cwd: nuxt.options.rootDir });
|
|
318
|
+
}));
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
function extendTypes(module, template) {
|
|
322
|
+
const nuxt = useNuxt();
|
|
323
|
+
addTemplate({
|
|
324
|
+
filename: `${module}.d.ts`,
|
|
325
|
+
getContents: () => {
|
|
326
|
+
const s = template();
|
|
327
|
+
return `// Generated by ${module}
|
|
328
|
+
${s}
|
|
329
|
+
export {}
|
|
330
|
+
`;
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
nuxt.hooks.hook("prepare:types", ({ references }) => {
|
|
334
|
+
references.push({ path: resolve(nuxt.options.buildDir, `${module}.d.ts`) });
|
|
335
|
+
});
|
|
203
336
|
}
|
|
204
337
|
|
|
205
338
|
const PATH = "/__nuxt_og_image__";
|
|
206
339
|
const PATH_ENTRY = `${PATH}/entry`;
|
|
207
340
|
const PATH_PLAYGROUND = `${PATH}/client`;
|
|
208
|
-
const edgeProvidersSupported = [
|
|
209
|
-
"cloudflare",
|
|
210
|
-
"vercel-edge",
|
|
211
|
-
"netlify-edge"
|
|
212
|
-
];
|
|
213
341
|
const module = defineNuxtModule({
|
|
214
342
|
meta: {
|
|
215
343
|
name: "nuxt-og-image",
|
|
216
344
|
compatibility: {
|
|
217
|
-
nuxt: "^3.
|
|
345
|
+
nuxt: "^3.6.1",
|
|
218
346
|
bridge: false
|
|
219
347
|
},
|
|
220
348
|
configKey: "ogImage"
|
|
221
349
|
},
|
|
222
350
|
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
351
|
return {
|
|
225
|
-
|
|
226
|
-
forcePrerender: !nuxt.options.dev && nuxt.options._generate,
|
|
227
|
-
siteUrl,
|
|
352
|
+
enabled: true,
|
|
228
353
|
defaults: {
|
|
229
|
-
component: "
|
|
354
|
+
component: "OgImageTemplateFallback",
|
|
230
355
|
width: 1200,
|
|
231
|
-
height: 630
|
|
356
|
+
height: 630,
|
|
357
|
+
// default is to cache the image for 24 hours
|
|
358
|
+
cache: true,
|
|
359
|
+
cacheTtl: 24 * 60 * 60 * 1e3
|
|
232
360
|
},
|
|
233
|
-
|
|
234
|
-
|
|
361
|
+
componentDirs: ["OgImage", "OgImageTemplate"],
|
|
362
|
+
runtimeSatori: true,
|
|
363
|
+
runtimeBrowser: nuxt.options.dev,
|
|
235
364
|
fonts: [],
|
|
365
|
+
runtimeCacheStorage: true,
|
|
236
366
|
satoriOptions: {},
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
playground: process.env.NODE_ENV === "development" || nuxt.options.dev
|
|
367
|
+
playground: process.env.NODE_ENV === "development" || nuxt.options.dev,
|
|
368
|
+
debug: false
|
|
240
369
|
};
|
|
241
370
|
},
|
|
242
371
|
async setup(config, nuxt) {
|
|
243
|
-
const
|
|
244
|
-
|
|
372
|
+
const logger = useLogger("nuxt-og-image");
|
|
373
|
+
logger.level = config.debug || nuxt.options.debug ? 4 : 3;
|
|
374
|
+
if (config.enabled === false) {
|
|
375
|
+
logger.debug("The module is disabled, skipping setup.");
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
const { resolve, resolvePath } = createResolver(import.meta.url);
|
|
379
|
+
logger.debug("Using Nitro preset", getNitroPreset(nuxt));
|
|
380
|
+
const nitroCompatibility = getNitroProviderCompatibility(nuxt);
|
|
381
|
+
logger.debug("Nitro compatibility", nitroCompatibility);
|
|
382
|
+
const nitroTarget = process.env.NITRO_PRESET || nuxt.options.nitro.preset;
|
|
383
|
+
if (!nitroCompatibility) {
|
|
384
|
+
logger.warn(`\`nuxt-og-image\` does not support the nitro target \`${nitroTarget}\`. Please make an issue. `);
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
if (!nitroCompatibility.browser && config.runtimeBrowser) {
|
|
388
|
+
config.runtimeBrowser = false;
|
|
389
|
+
logger.warn(`\`nuxt-og-image\` does not support the nitro target \`${nitroTarget}\` with the runtime browser. Set runtimeBrowser: false to stop seeing this.`);
|
|
390
|
+
}
|
|
391
|
+
if (config.runtimeBrowser && nitroCompatibility.browser === "lambda") {
|
|
392
|
+
logger.info(`\`nuxt-og-image\` is deploying to nitro target \`${nitroTarget}\` that installs extra dependencies.`);
|
|
393
|
+
await ensureDependencies(nuxt, ["puppeteer-core@14.1.1", "@sparticuz/chrome-aws-lambda@14.1.1"]);
|
|
394
|
+
}
|
|
395
|
+
await installModule(await resolvePath("nuxt-site-config"));
|
|
396
|
+
await updateSiteConfig({
|
|
397
|
+
_context: "nuxt-og-image:config",
|
|
398
|
+
url: config.siteUrl || config.host
|
|
399
|
+
});
|
|
400
|
+
requireSiteConfig("nuxt-og-image", {
|
|
401
|
+
url: "Required to generate absolute URLs for the og:image."
|
|
402
|
+
}, { prerender: true });
|
|
403
|
+
nuxt.options.nitro.storage = nuxt.options.nitro.storage || {};
|
|
404
|
+
if (nuxt.options._generate) {
|
|
405
|
+
nuxt.options.nitro.storage["og-image"] = {
|
|
406
|
+
driver: "memory"
|
|
407
|
+
};
|
|
408
|
+
} else if (config.runtimeCacheStorage && !nuxt.options.dev && typeof config.runtimeCacheStorage === "object") {
|
|
409
|
+
nuxt.options.nitro.storage["og-image"] = config.runtimeCacheStorage;
|
|
410
|
+
}
|
|
245
411
|
if (!config.fonts.length)
|
|
246
412
|
config.fonts = ["Inter:400", "Inter:700"];
|
|
247
413
|
const distResolve = (p) => {
|
|
@@ -251,34 +417,27 @@ const module = defineNuxtModule({
|
|
|
251
417
|
return resolve(`../dist/${p}`);
|
|
252
418
|
};
|
|
253
419
|
nuxt.options.experimental.componentIslands = true;
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
getContents: () => {
|
|
257
|
-
return `// Generated by nuxt-og-image
|
|
258
|
-
interface NuxtOgImageNitroRules {
|
|
420
|
+
extendTypes("nuxt-og-image", () => {
|
|
421
|
+
return `interface NuxtOgImageNitroRules {
|
|
259
422
|
ogImage?: false | Record<string, any>
|
|
260
423
|
}
|
|
261
424
|
declare module 'nitropack' {
|
|
262
425
|
interface NitroRouteRules extends NuxtOgImageNitroRules {}
|
|
263
426
|
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") });
|
|
427
|
+
}`;
|
|
271
428
|
});
|
|
272
429
|
addServerHandler({
|
|
273
430
|
lazy: true,
|
|
274
431
|
handler: resolve("./runtime/nitro/middleware/og.png")
|
|
275
432
|
});
|
|
276
|
-
["html", "options", "svg", "vnode", "font"].forEach((type) => {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
433
|
+
["html", "options", "svg", "vnode", "font", "debug"].forEach((type) => {
|
|
434
|
+
if (type !== "debug" || config.debug) {
|
|
435
|
+
addServerHandler({
|
|
436
|
+
lazy: true,
|
|
437
|
+
route: `/api/og-image-${type}`,
|
|
438
|
+
handler: resolve(`./runtime/nitro/routes/${type}`)
|
|
439
|
+
});
|
|
440
|
+
}
|
|
282
441
|
});
|
|
283
442
|
nuxt.hook("devtools:customTabs", (iframeTabs) => {
|
|
284
443
|
iframeTabs.push({
|
|
@@ -307,7 +466,17 @@ export {}
|
|
|
307
466
|
});
|
|
308
467
|
}
|
|
309
468
|
nuxt.options.optimization.treeShake.composables.client["nuxt-og-image"] = [];
|
|
310
|
-
[
|
|
469
|
+
[
|
|
470
|
+
// deprecated
|
|
471
|
+
"Dynamic",
|
|
472
|
+
"Static",
|
|
473
|
+
// new
|
|
474
|
+
"index",
|
|
475
|
+
"Cached",
|
|
476
|
+
"WithoutCache",
|
|
477
|
+
"Screenshot"
|
|
478
|
+
].forEach((name) => {
|
|
479
|
+
name = name === "index" ? "defineOgImage" : `defineOgImage${name}`;
|
|
311
480
|
addImports({
|
|
312
481
|
name,
|
|
313
482
|
from: resolve("./runtime/composables/defineOgImage")
|
|
@@ -315,104 +484,197 @@ export {}
|
|
|
315
484
|
nuxt.options.optimization.treeShake.composables.client["nuxt-og-image"].push(name);
|
|
316
485
|
});
|
|
317
486
|
await addComponent({
|
|
318
|
-
name: "
|
|
319
|
-
filePath: resolve("./runtime/components/
|
|
487
|
+
name: "OgImageTemplateFallback",
|
|
488
|
+
filePath: resolve("./runtime/components/OgImageTemplate/Fallback.vue"),
|
|
320
489
|
island: true
|
|
321
490
|
});
|
|
322
|
-
[
|
|
491
|
+
[
|
|
492
|
+
// deprecated
|
|
493
|
+
"Static",
|
|
494
|
+
"Dynamic",
|
|
495
|
+
// new
|
|
496
|
+
"index",
|
|
497
|
+
"Cached",
|
|
498
|
+
"WithoutCache",
|
|
499
|
+
"Screenshot"
|
|
500
|
+
].forEach((name) => {
|
|
323
501
|
addComponent({
|
|
324
|
-
name
|
|
325
|
-
filePath: resolve(`./runtime/components/${name}`)
|
|
502
|
+
name: name === "index" ? "OgImage" : `OgImage${name}`,
|
|
503
|
+
filePath: resolve(`./runtime/components/OgImage/${name}`)
|
|
326
504
|
});
|
|
327
505
|
});
|
|
506
|
+
const ogImageComponents = [];
|
|
507
|
+
nuxt.hook("components:extend", (components) => {
|
|
508
|
+
components.forEach((component) => {
|
|
509
|
+
let valid = false;
|
|
510
|
+
config.componentDirs.forEach((dir) => {
|
|
511
|
+
if (component.pascalName.startsWith(dir) || component.kebabName.startsWith(dir))
|
|
512
|
+
valid = true;
|
|
513
|
+
});
|
|
514
|
+
if (valid) {
|
|
515
|
+
component.island = true;
|
|
516
|
+
component.mode = "server";
|
|
517
|
+
ogImageComponents.push({ pascalName: component.pascalName, kebabName: component.kebabName });
|
|
518
|
+
}
|
|
519
|
+
});
|
|
520
|
+
});
|
|
521
|
+
addTemplate({
|
|
522
|
+
filename: "og-image-component-names.mjs",
|
|
523
|
+
getContents() {
|
|
524
|
+
return `export const componentNames = ${JSON.stringify(ogImageComponents)}`;
|
|
525
|
+
},
|
|
526
|
+
options: { mode: "server" }
|
|
527
|
+
});
|
|
328
528
|
const runtimeDir = resolve("./runtime");
|
|
329
529
|
nuxt.options.build.transpile.push(runtimeDir);
|
|
330
|
-
|
|
331
|
-
const
|
|
332
|
-
|
|
333
|
-
|
|
530
|
+
addServerPlugin(resolve("./runtime/nitro/plugins/prerender"));
|
|
531
|
+
const customAssetDirs = [
|
|
532
|
+
// allows us to show custom error images
|
|
533
|
+
resolve("./runtime/public-assets")
|
|
334
534
|
];
|
|
535
|
+
if (config.runtimeSatori) {
|
|
536
|
+
if (config.fonts.includes("Inter:400"))
|
|
537
|
+
customAssetDirs.push(resolve("./runtime/public-assets-optional/inter-font"));
|
|
538
|
+
if (nitroCompatibility.png === "resvg-wasm" && nitroCompatibility.wasm === "fetch")
|
|
539
|
+
customAssetDirs.push(resolve("./runtime/public-assets-optional/resvg"));
|
|
540
|
+
else if (nitroCompatibility.png === "svg2png" && nitroCompatibility.wasm === "fetch")
|
|
541
|
+
customAssetDirs.push(resolve("./runtime/public-assets-optional/svg2png"));
|
|
542
|
+
if (nitroCompatibility.satori === "yoga-wasm")
|
|
543
|
+
customAssetDirs.push(resolve("./runtime/public-assets-optional/yoga"));
|
|
544
|
+
}
|
|
335
545
|
nuxt.hooks.hook("modules:done", async () => {
|
|
336
546
|
nuxt.hooks.callHook("og-image:config", config);
|
|
337
|
-
nuxt.options.runtimeConfig["nuxt-og-image"] = {
|
|
547
|
+
nuxt.options.runtimeConfig["nuxt-og-image"] = {
|
|
548
|
+
satoriOptions: config.satoriOptions,
|
|
549
|
+
runtimeSatori: config.runtimeSatori,
|
|
550
|
+
runtimeBrowser: config.runtimeBrowser,
|
|
551
|
+
// @ts-expect-error runtime type
|
|
552
|
+
defaults: config.defaults,
|
|
553
|
+
// avoid adding credentials
|
|
554
|
+
runtimeCacheStorage: typeof config.runtimeCacheStorage === "boolean" ? "default" : config.runtimeCacheStorage.driver,
|
|
555
|
+
// convert the fonts to uniform type to fix ts issue
|
|
556
|
+
fonts: config.fonts.map((f) => {
|
|
557
|
+
if (typeof f === "string") {
|
|
558
|
+
const [name, weight] = f.split(":");
|
|
559
|
+
return {
|
|
560
|
+
name,
|
|
561
|
+
weight
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
return f;
|
|
565
|
+
}),
|
|
566
|
+
assetDirs: [
|
|
567
|
+
resolve(nuxt.options.srcDir, nuxt.options.dir.public),
|
|
568
|
+
...customAssetDirs,
|
|
569
|
+
// always add runtime dirs for prerendering to work, these are just used as scan roots
|
|
570
|
+
resolve("./runtime/public-assets-optional/inter-font"),
|
|
571
|
+
resolve("./runtime/public-assets-optional/resvg"),
|
|
572
|
+
resolve("./runtime/public-assets-optional/yoga"),
|
|
573
|
+
resolve("./runtime/public-assets-optional/svg2png")
|
|
574
|
+
]
|
|
575
|
+
};
|
|
338
576
|
});
|
|
339
|
-
const useSatoriWasm = provider === "stackblitz";
|
|
340
577
|
nuxt.hooks.hook("nitro:config", async (nitroConfig) => {
|
|
341
578
|
nitroConfig.externals = defu(nitroConfig.externals || {}, {
|
|
342
579
|
inline: [runtimeDir]
|
|
343
580
|
});
|
|
344
|
-
if (config.
|
|
581
|
+
if (config.runtimeBrowser) {
|
|
345
582
|
nitroConfig.alias = nitroConfig.alias || {};
|
|
346
583
|
nitroConfig.alias.electron = "unenv/runtime/mock/proxy-cjs";
|
|
347
584
|
nitroConfig.alias.bufferutil = "unenv/runtime/mock/proxy-cjs";
|
|
348
585
|
nitroConfig.alias["utf-8-validate"] = "unenv/runtime/mock/proxy-cjs";
|
|
349
586
|
}
|
|
350
587
|
nitroConfig.publicAssets = nitroConfig.publicAssets || [];
|
|
351
|
-
|
|
588
|
+
customAssetDirs.forEach((dir) => {
|
|
589
|
+
nitroConfig.publicAssets.push({ dir, maxAge: 31536e3 });
|
|
590
|
+
});
|
|
352
591
|
const providerPath = `${runtimeDir}/nitro/providers`;
|
|
353
|
-
if (config.
|
|
354
|
-
nitroConfig.virtual["#nuxt-og-image/browser"] =
|
|
355
|
-
|
|
356
|
-
|
|
592
|
+
if (config.runtimeBrowser) {
|
|
593
|
+
nitroConfig.virtual["#nuxt-og-image/browser"] = `
|
|
594
|
+
let browser
|
|
357
595
|
export default async function() {
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
` : `export default async function() {
|
|
361
|
-
return () => {}
|
|
596
|
+
browser = browser || await import('${providerPath}/browser/${nitroCompatibility.browser}').then((m) => m.default || m)
|
|
597
|
+
return browser
|
|
362
598
|
}
|
|
363
599
|
`;
|
|
364
600
|
}
|
|
365
|
-
if (config.
|
|
366
|
-
nitroConfig.virtual["#nuxt-og-image/satori"] = `import satori from '${providerPath}/satori/${
|
|
367
|
-
export default
|
|
601
|
+
if (config.runtimeSatori) {
|
|
602
|
+
nitroConfig.virtual["#nuxt-og-image/satori"] = `import satori from '${providerPath}/satori/${nitroCompatibility.satori}'
|
|
603
|
+
export default function() {
|
|
368
604
|
return satori
|
|
369
605
|
}`;
|
|
370
|
-
nitroConfig.virtual["#nuxt-og-image/
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
606
|
+
nitroConfig.virtual["#nuxt-og-image/png"] = `import png from '${providerPath}/png/${nitroCompatibility.png}'
|
|
607
|
+
export default function() {
|
|
608
|
+
return png
|
|
609
|
+
}
|
|
610
|
+
`;
|
|
375
611
|
}
|
|
376
612
|
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"))}'
|
|
613
|
+
${config.runtimeSatori ? `import satori from '${relative(nuxt.options.rootDir, resolve("./runtime/nitro/renderers/satori"))}'` : ""}
|
|
614
|
+
${config.runtimeBrowser ? `import browser from '${relative(nuxt.options.rootDir, resolve("./runtime/nitro/renderers/browser"))}'` : ""}
|
|
379
615
|
|
|
380
616
|
export async function useProvider(provider) {
|
|
381
617
|
if (provider === 'satori')
|
|
382
|
-
return satori
|
|
618
|
+
return ${config.runtimeSatori ? "satori" : "null"}
|
|
383
619
|
if (provider === 'browser')
|
|
384
|
-
return browser
|
|
620
|
+
return ${config.runtimeBrowser ? "browser" : "null"}
|
|
621
|
+
return null
|
|
385
622
|
}
|
|
386
623
|
`;
|
|
387
624
|
});
|
|
388
625
|
nuxt.hooks.hook("nitro:init", async (nitro) => {
|
|
389
626
|
let screenshotQueue = [];
|
|
390
627
|
nitro.hooks.hook("compiled", async (_nitro) => {
|
|
391
|
-
if (
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
628
|
+
if (!config.runtimeSatori || nuxt.options.dev)
|
|
629
|
+
return;
|
|
630
|
+
if (config.fonts.includes("Inter:400"))
|
|
631
|
+
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"));
|
|
632
|
+
if (config.fonts.includes("Inter:700"))
|
|
633
|
+
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"));
|
|
634
|
+
const configuredEntry = nitro.options.rollupConfig?.output.entryFileNames;
|
|
635
|
+
const wasmProviderPath = resolve(_nitro.options.output.serverDir, typeof configuredEntry === "string" ? configuredEntry : "index.mjs");
|
|
636
|
+
const paths = [wasmProviderPath];
|
|
637
|
+
const chunks = await globby([`${_nitro.options.output.serverDir}/chunks/**/*.mjs`], { absolute: true });
|
|
638
|
+
paths.push(...chunks);
|
|
639
|
+
for (const path of paths) {
|
|
640
|
+
if (!await pathExists(path))
|
|
641
|
+
continue;
|
|
642
|
+
let contents = await readFile(path, "utf-8");
|
|
643
|
+
let updated = false;
|
|
644
|
+
if (_nitro.options.preset.includes("vercel") && path === wasmProviderPath) {
|
|
645
|
+
contents = contents.replace(".cwd(),", '?.cwd || "/",');
|
|
646
|
+
updated = true;
|
|
398
647
|
}
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
648
|
+
if (_nitro.options.preset.includes("netlify") && path.endsWith("netlify.mjs")) {
|
|
649
|
+
const match = "// TODO: handle event.isBase64Encoded\n });";
|
|
650
|
+
contents = contents.replace(match, `${match}
|
|
651
|
+
|
|
652
|
+
const headers = normalizeOutgoingHeaders(r.headers);
|
|
653
|
+
// image buffers must be base64 encoded
|
|
654
|
+
if (Buffer.isBuffer(r.body) && headers["content-type"].startsWith("image/")) {
|
|
655
|
+
return {
|
|
656
|
+
statusCode: r.status,
|
|
657
|
+
headers,
|
|
658
|
+
body: r.body.toString("base64"),
|
|
659
|
+
isBase64Encoded: true
|
|
660
|
+
};
|
|
661
|
+
}`);
|
|
662
|
+
updated = true;
|
|
663
|
+
}
|
|
664
|
+
for (const wasm of Wasms) {
|
|
665
|
+
if (contents.includes(wasm.placeholder)) {
|
|
666
|
+
if (nitroCompatibility.wasm === "import") {
|
|
667
|
+
contents = contents.replace(wasm.placeholder, `import("./${wasm.file}${nitroCompatibility.wasmImportQuery || ""}").then(m => m.default || m)`);
|
|
668
|
+
await copy(resolve(`./runtime/public-assets-optional/${wasm.path}`), resolve(dirname(path), wasm.file));
|
|
669
|
+
} else if (nitroCompatibility.wasm === "inline") {
|
|
670
|
+
const wasmBuffer = await readFile(resolve(`./runtime/public-assets-optional/${wasm.path}`));
|
|
671
|
+
contents = contents.replace(wasm.placeholder, `Buffer.from("${wasmBuffer}", "base64")`);
|
|
672
|
+
}
|
|
673
|
+
updated = true;
|
|
414
674
|
}
|
|
415
675
|
}
|
|
676
|
+
if (updated)
|
|
677
|
+
await writeFile(path, contents, { encoding: "utf-8" });
|
|
416
678
|
}
|
|
417
679
|
});
|
|
418
680
|
const _routeRulesMatcher = toRouteMatcher(
|
|
@@ -425,7 +687,6 @@ export async function useProvider(provider) {
|
|
|
425
687
|
if (!html)
|
|
426
688
|
return;
|
|
427
689
|
const extractedOptions = extractOgImageOptions(html);
|
|
428
|
-
ctx.contents = stripOgImageOptions(html);
|
|
429
690
|
const routeRules = defu({}, ..._routeRulesMatcher.matchAll(ctx.route).reverse());
|
|
430
691
|
if (!extractedOptions || routeRules.ogImage === false)
|
|
431
692
|
return;
|
|
@@ -435,7 +696,7 @@ export async function useProvider(provider) {
|
|
|
435
696
|
...extractedOptions,
|
|
436
697
|
...routeRules.ogImage || {}
|
|
437
698
|
};
|
|
438
|
-
if ((nuxt.options._generate || entry.
|
|
699
|
+
if ((nuxt.options._generate || entry.cache) && entry.provider === "browser")
|
|
439
700
|
screenshotQueue.push(entry);
|
|
440
701
|
});
|
|
441
702
|
if (nuxt.options.dev)
|
|
@@ -444,21 +705,6 @@ export async function useProvider(provider) {
|
|
|
444
705
|
await nuxt.callHook("og-image:prerenderScreenshots", screenshotQueue);
|
|
445
706
|
if (screenshotQueue.length === 0)
|
|
446
707
|
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
708
|
nitro.logger.info("Ensuring chromium install for og:image generation...");
|
|
463
709
|
const installChromeProcess = execa("npx", ["playwright", "install", "chromium"], {
|
|
464
710
|
stdio: "inherit"
|
|
@@ -485,12 +731,27 @@ export async function useProvider(provider) {
|
|
|
485
731
|
browser = await createBrowser();
|
|
486
732
|
if (browser) {
|
|
487
733
|
nitro.logger.info(`Prerendering ${screenshotQueue.length} og:image screenshots...`);
|
|
734
|
+
for (const entry of screenshotQueue) {
|
|
735
|
+
if (entry.route && Object.keys(entry).length === 1) {
|
|
736
|
+
const html = await $fetch(entry.route, { baseURL: withBase(nuxt.options.app.baseURL, host) });
|
|
737
|
+
const extractedOptions = extractOgImageOptions(html);
|
|
738
|
+
const routeRules = defu({}, ..._routeRulesMatcher.matchAll(entry.route).reverse());
|
|
739
|
+
Object.assign(entry, {
|
|
740
|
+
// @ts-expect-error runtime
|
|
741
|
+
path: extractedOptions.component ? `/api/og-image-html?path=${entry.route}` : entry.route,
|
|
742
|
+
...extractedOptions,
|
|
743
|
+
...routeRules.ogImage || {}
|
|
744
|
+
});
|
|
745
|
+
}
|
|
746
|
+
if (entry.component)
|
|
747
|
+
entry.html = await globalThis.$fetch(entry.path);
|
|
748
|
+
}
|
|
488
749
|
for (const k in screenshotQueue) {
|
|
489
750
|
const entry = screenshotQueue[k];
|
|
490
751
|
const start = Date.now();
|
|
491
752
|
let hasError = false;
|
|
492
|
-
const
|
|
493
|
-
const filename = joinURL(
|
|
753
|
+
const dirname2 = joinURL(nitro.options.output.publicDir, entry.route, "/__og_image__/");
|
|
754
|
+
const filename = joinURL(dirname2, "/og.png");
|
|
494
755
|
try {
|
|
495
756
|
const imgBuffer = await screenshot(browser, {
|
|
496
757
|
...config.defaults || {},
|
|
@@ -498,7 +759,7 @@ export async function useProvider(provider) {
|
|
|
498
759
|
host
|
|
499
760
|
});
|
|
500
761
|
try {
|
|
501
|
-
await mkdirp(
|
|
762
|
+
await mkdirp(dirname2);
|
|
502
763
|
} catch (e) {
|
|
503
764
|
}
|
|
504
765
|
await writeFile(filename, imgBuffer);
|
|
@@ -522,7 +783,7 @@ export async function useProvider(provider) {
|
|
|
522
783
|
}
|
|
523
784
|
screenshotQueue = [];
|
|
524
785
|
};
|
|
525
|
-
if (
|
|
786
|
+
if (nuxt.options._generate) {
|
|
526
787
|
nitro.hooks.hook("rollup:before", async () => {
|
|
527
788
|
await captureScreenshots();
|
|
528
789
|
});
|