nuxt-og-image 2.0.0-beta.9 → 2.0.0
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 +18 -517
- package/dist/client/200.html +2 -2
- package/dist/client/404.html +2 -2
- package/dist/client/_nuxt/IconCSS.48ffa50d.js +1 -0
- package/dist/client/_nuxt/IconCSS.b41b9663.css +1 -0
- package/dist/client/_nuxt/ImageLoader.51157bac.js +1 -0
- package/dist/client/_nuxt/ImageLoader.7571516f.css +1 -0
- package/dist/client/_nuxt/entry.1311cc29.css +1 -0
- package/dist/client/_nuxt/entry.74c20cae.js +143 -0
- package/dist/client/_nuxt/{error-404.02537f9e.js → error-404.102f7671.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.a60bf0b5.js → error-500.f8617a9a.js} +1 -1
- package/dist/client/_nuxt/index.212ef337.js +1 -0
- package/dist/client/_nuxt/index.ffbea0a9.css +1 -0
- package/dist/client/_nuxt/options.fa4f11fe.js +1 -0
- package/dist/client/_nuxt/png.eb47fcca.js +1 -0
- package/dist/client/_nuxt/{shiki.aace8ca2.js → shiki.b89869e1.js} +1 -1
- package/dist/client/_nuxt/svg.04901249.js +1 -0
- package/dist/client/_nuxt/vnodes.b05f3d68.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 +375 -115
- package/dist/runtime/browserUtil.d.ts +1 -0
- package/dist/runtime/browserUtil.mjs +7 -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/OgImage/Dynamic.d.ts +8 -0
- package/dist/runtime/components/{OgImageDynamic.mjs → OgImage/Dynamic.mjs} +3 -3
- 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/Static.d.ts +8 -0
- package/dist/runtime/components/{OgImageStatic.mjs → OgImage/Static.mjs} +3 -3
- package/dist/runtime/components/{OgImageStatic.d.ts → OgImage/WithoutCache.d.ts} +2 -2
- package/dist/runtime/components/OgImage/WithoutCache.mjs +10 -0
- package/dist/runtime/components/OgImage/index.d.ts +5 -0
- package/dist/runtime/components/OgImage/index.mjs +10 -0
- package/dist/runtime/components/OgImageTemplate/Fallback.vue +156 -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/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 -12
- 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 +100 -26
- package/dist/runtime/nitro/routes/options.d.ts +2 -2
- package/dist/runtime/nitro/routes/options.mjs +21 -20
- package/dist/runtime/nitro/routes/svg.mjs +2 -2
- package/dist/runtime/nitro/routes/vnode.mjs +2 -2
- package/dist/runtime/nitro/utils-pure.d.ts +0 -1
- package/dist/runtime/nitro/utils-pure.mjs +1 -4
- package/dist/runtime/nitro/utils.d.ts +11 -11
- package/dist/runtime/nitro/utils.mjs +67 -53
- 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.ef0613e7.js +0 -1
- package/dist/client/_nuxt/ImageLoader.a4418cab.js +0 -1
- package/dist/client/_nuxt/entry.09f25aaf.css +0 -1
- package/dist/client/_nuxt/entry.fc9150b0.js +0 -5
- 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.8148b615.js +0 -3
- package/dist/client/_nuxt/index.80f38ec7.js +0 -1
- package/dist/client/_nuxt/options.cc3fd02b.js +0 -1
- package/dist/client/_nuxt/png.62758167.js +0 -1
- package/dist/client/_nuxt/svg.853cdaad.js +0 -1
- package/dist/client/_nuxt/vnodes.69b24963.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,30 +1,34 @@
|
|
|
1
1
|
import { readFile, writeFile } from 'node:fs/promises';
|
|
2
|
-
import { defineNuxtModule,
|
|
2
|
+
import { useNuxt, addTemplate, defineNuxtModule, useLogger, createResolver, addServerHandler, addImports, addComponent, hasNuxtModule, 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
7
|
import { withBase, joinURL } from 'ufo';
|
|
8
|
-
import { resolve, relative } from 'pathe';
|
|
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 {
|
|
13
|
-
import {
|
|
12
|
+
import { globby } from 'globby';
|
|
13
|
+
import { installNuxtSiteConfig, updateSiteConfig, requireSiteConfig } from 'nuxt-site-config-kit';
|
|
14
14
|
import playwrightCore from 'playwright-core';
|
|
15
15
|
import { existsSync } from 'node:fs';
|
|
16
16
|
import { createBirpcGroup } from 'birpc';
|
|
17
17
|
import { stringify, parse } from 'flatted';
|
|
18
|
+
import { addDependency } from 'nypm';
|
|
19
|
+
import { provider } from 'std-env';
|
|
18
20
|
|
|
19
21
|
async function createBrowser() {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
+
}
|
|
28
32
|
}
|
|
29
33
|
try {
|
|
30
34
|
return await playwrightCore.chromium.launch({
|
|
@@ -55,9 +59,9 @@ async function screenshot(browser, options) {
|
|
|
55
59
|
width: options.width || 1200,
|
|
56
60
|
height: options.height || 630
|
|
57
61
|
});
|
|
58
|
-
const isHtml = options.path
|
|
62
|
+
const isHtml = options.html || options.path?.startsWith("html:");
|
|
59
63
|
if (isHtml) {
|
|
60
|
-
const html = options.html || options.path
|
|
64
|
+
const html = options.html || options.path?.substring(5);
|
|
61
65
|
await page.evaluate((html2) => {
|
|
62
66
|
document.open("text/html");
|
|
63
67
|
document.write(html2);
|
|
@@ -66,12 +70,12 @@ async function screenshot(browser, options) {
|
|
|
66
70
|
await page.waitForLoadState("networkidle");
|
|
67
71
|
} else {
|
|
68
72
|
await page.goto(`${options.host}${options.path}`, {
|
|
69
|
-
timeout: 1e4,
|
|
73
|
+
timeout: process.env.prerender || process.dev ? 1e4 : 3500,
|
|
70
74
|
waitUntil: "networkidle"
|
|
71
75
|
});
|
|
72
76
|
}
|
|
73
77
|
const screenshotOptions = {
|
|
74
|
-
timeout: 1e4
|
|
78
|
+
timeout: process.env.prerender || process.dev ? 1e4 : 3500
|
|
75
79
|
};
|
|
76
80
|
if (options.delay)
|
|
77
81
|
await page.waitForTimeout(options.delay);
|
|
@@ -83,7 +87,9 @@ async function screenshot(browser, options) {
|
|
|
83
87
|
}
|
|
84
88
|
if (options.selector)
|
|
85
89
|
return await page.locator(options.selector).screenshot(screenshotOptions);
|
|
86
|
-
|
|
90
|
+
const screenshot2 = await page.screenshot(screenshotOptions);
|
|
91
|
+
await page.close();
|
|
92
|
+
return screenshot2;
|
|
87
93
|
}
|
|
88
94
|
|
|
89
95
|
function setupPlaygroundRPC(nuxt, config) {
|
|
@@ -170,7 +176,7 @@ function getBodyJson(req) {
|
|
|
170
176
|
|
|
171
177
|
function decodeHtml(html) {
|
|
172
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) => {
|
|
173
|
-
return String.fromCharCode(parseInt(int));
|
|
179
|
+
return String.fromCharCode(Number.parseInt(int));
|
|
174
180
|
});
|
|
175
181
|
}
|
|
176
182
|
function decodeObjectHtmlEntities(obj) {
|
|
@@ -205,46 +211,203 @@ function extractOgImageOptions(html) {
|
|
|
205
211
|
return false;
|
|
206
212
|
}
|
|
207
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
|
+
});
|
|
336
|
+
}
|
|
337
|
+
|
|
208
338
|
const PATH = "/__nuxt_og_image__";
|
|
209
339
|
const PATH_ENTRY = `${PATH}/entry`;
|
|
210
340
|
const PATH_PLAYGROUND = `${PATH}/client`;
|
|
211
|
-
const edgeProvidersSupported = [
|
|
212
|
-
"cloudflare",
|
|
213
|
-
"vercel-edge",
|
|
214
|
-
"netlify-edge"
|
|
215
|
-
];
|
|
216
341
|
const module = defineNuxtModule({
|
|
217
342
|
meta: {
|
|
218
343
|
name: "nuxt-og-image",
|
|
219
344
|
compatibility: {
|
|
220
|
-
nuxt: "^3.
|
|
345
|
+
nuxt: "^3.6.1",
|
|
221
346
|
bridge: false
|
|
222
347
|
},
|
|
223
348
|
configKey: "ogImage"
|
|
224
349
|
},
|
|
225
350
|
defaults(nuxt) {
|
|
226
|
-
const siteUrl = process.env.NUXT_PUBLIC_SITE_URL || process.env.NUXT_SITE_URL || nuxt.options.runtimeConfig.public?.siteUrl || nuxt.options.runtimeConfig.siteUrl;
|
|
227
351
|
return {
|
|
228
|
-
|
|
229
|
-
forcePrerender: !nuxt.options.dev && nuxt.options._generate,
|
|
230
|
-
siteUrl,
|
|
352
|
+
enabled: true,
|
|
231
353
|
defaults: {
|
|
232
|
-
component: "
|
|
354
|
+
component: "OgImageTemplateFallback",
|
|
233
355
|
width: 1200,
|
|
234
|
-
height: 630
|
|
356
|
+
height: 630,
|
|
357
|
+
// default is to cache the image for 24 hours
|
|
358
|
+
cache: true,
|
|
359
|
+
cacheTtl: 24 * 60 * 60 * 1e3
|
|
235
360
|
},
|
|
236
|
-
|
|
237
|
-
|
|
361
|
+
componentDirs: ["OgImage", "OgImageTemplate"],
|
|
362
|
+
runtimeSatori: true,
|
|
363
|
+
runtimeBrowser: nuxt.options.dev,
|
|
238
364
|
fonts: [],
|
|
365
|
+
runtimeCacheStorage: true,
|
|
239
366
|
satoriOptions: {},
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
playground: process.env.NODE_ENV === "development" || nuxt.options.dev
|
|
367
|
+
playground: process.env.NODE_ENV === "development" || nuxt.options.dev,
|
|
368
|
+
debug: false
|
|
243
369
|
};
|
|
244
370
|
},
|
|
245
371
|
async setup(config, nuxt) {
|
|
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
|
+
}
|
|
246
378
|
const { resolve } = createResolver(import.meta.url);
|
|
247
|
-
|
|
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 installNuxtSiteConfig();
|
|
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
|
+
}
|
|
248
411
|
if (!config.fonts.length)
|
|
249
412
|
config.fonts = ["Inter:400", "Inter:700"];
|
|
250
413
|
const distResolve = (p) => {
|
|
@@ -254,34 +417,27 @@ const module = defineNuxtModule({
|
|
|
254
417
|
return resolve(`../dist/${p}`);
|
|
255
418
|
};
|
|
256
419
|
nuxt.options.experimental.componentIslands = true;
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
getContents: () => {
|
|
260
|
-
return `// Generated by nuxt-og-image
|
|
261
|
-
interface NuxtOgImageNitroRules {
|
|
420
|
+
extendTypes("nuxt-og-image", () => {
|
|
421
|
+
return `interface NuxtOgImageNitroRules {
|
|
262
422
|
ogImage?: false | Record<string, any>
|
|
263
423
|
}
|
|
264
424
|
declare module 'nitropack' {
|
|
265
425
|
interface NitroRouteRules extends NuxtOgImageNitroRules {}
|
|
266
426
|
interface NitroRouteConfig extends NuxtOgImageNitroRules {}
|
|
267
|
-
}
|
|
268
|
-
export {}
|
|
269
|
-
`;
|
|
270
|
-
}
|
|
271
|
-
});
|
|
272
|
-
nuxt.hooks.hook("prepare:types", ({ references }) => {
|
|
273
|
-
references.push({ path: resolve(nuxt.options.buildDir, "nuxt-og-image.d.ts") });
|
|
427
|
+
}`;
|
|
274
428
|
});
|
|
275
429
|
addServerHandler({
|
|
276
430
|
lazy: true,
|
|
277
431
|
handler: resolve("./runtime/nitro/middleware/og.png")
|
|
278
432
|
});
|
|
279
|
-
["html", "options", "svg", "vnode", "font"].forEach((type) => {
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
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
|
+
}
|
|
285
441
|
});
|
|
286
442
|
nuxt.hook("devtools:customTabs", (iframeTabs) => {
|
|
287
443
|
iframeTabs.push({
|
|
@@ -310,7 +466,17 @@ export {}
|
|
|
310
466
|
});
|
|
311
467
|
}
|
|
312
468
|
nuxt.options.optimization.treeShake.composables.client["nuxt-og-image"] = [];
|
|
313
|
-
[
|
|
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}`;
|
|
314
480
|
addImports({
|
|
315
481
|
name,
|
|
316
482
|
from: resolve("./runtime/composables/defineOgImage")
|
|
@@ -318,104 +484,198 @@ export {}
|
|
|
318
484
|
nuxt.options.optimization.treeShake.composables.client["nuxt-og-image"].push(name);
|
|
319
485
|
});
|
|
320
486
|
await addComponent({
|
|
321
|
-
name: "
|
|
322
|
-
filePath: resolve("./runtime/components/
|
|
487
|
+
name: "OgImageTemplateFallback",
|
|
488
|
+
filePath: resolve("./runtime/components/OgImageTemplate/Fallback.vue"),
|
|
323
489
|
island: true
|
|
324
490
|
});
|
|
325
|
-
[
|
|
491
|
+
[
|
|
492
|
+
// deprecated
|
|
493
|
+
"Static",
|
|
494
|
+
"Dynamic",
|
|
495
|
+
// new
|
|
496
|
+
"index",
|
|
497
|
+
"Cached",
|
|
498
|
+
"WithoutCache",
|
|
499
|
+
"Screenshot"
|
|
500
|
+
].forEach((name) => {
|
|
326
501
|
addComponent({
|
|
327
|
-
|
|
328
|
-
|
|
502
|
+
global: hasNuxtModule("@nuxt/content"),
|
|
503
|
+
name: name === "index" ? "OgImage" : `OgImage${name}`,
|
|
504
|
+
filePath: resolve(`./runtime/components/OgImage/${name}`)
|
|
329
505
|
});
|
|
330
506
|
});
|
|
507
|
+
const ogImageComponents = [];
|
|
508
|
+
nuxt.hook("components:extend", (components) => {
|
|
509
|
+
components.forEach((component) => {
|
|
510
|
+
let valid = false;
|
|
511
|
+
config.componentDirs.forEach((dir) => {
|
|
512
|
+
if (component.pascalName.startsWith(dir) || component.kebabName.startsWith(dir))
|
|
513
|
+
valid = true;
|
|
514
|
+
});
|
|
515
|
+
if (valid) {
|
|
516
|
+
component.island = true;
|
|
517
|
+
component.mode = "server";
|
|
518
|
+
ogImageComponents.push({ pascalName: component.pascalName, kebabName: component.kebabName });
|
|
519
|
+
}
|
|
520
|
+
});
|
|
521
|
+
});
|
|
522
|
+
addTemplate({
|
|
523
|
+
filename: "og-image-component-names.mjs",
|
|
524
|
+
getContents() {
|
|
525
|
+
return `export const componentNames = ${JSON.stringify(ogImageComponents)}`;
|
|
526
|
+
},
|
|
527
|
+
options: { mode: "server" }
|
|
528
|
+
});
|
|
331
529
|
const runtimeDir = resolve("./runtime");
|
|
332
530
|
nuxt.options.build.transpile.push(runtimeDir);
|
|
333
|
-
|
|
334
|
-
const
|
|
335
|
-
|
|
336
|
-
|
|
531
|
+
addServerPlugin(resolve("./runtime/nitro/plugins/prerender"));
|
|
532
|
+
const customAssetDirs = [
|
|
533
|
+
// allows us to show custom error images
|
|
534
|
+
resolve("./runtime/public-assets")
|
|
337
535
|
];
|
|
536
|
+
if (config.runtimeSatori) {
|
|
537
|
+
if (config.fonts.includes("Inter:400"))
|
|
538
|
+
customAssetDirs.push(resolve("./runtime/public-assets-optional/inter-font"));
|
|
539
|
+
if (nitroCompatibility.png === "resvg-wasm" && nitroCompatibility.wasm === "fetch")
|
|
540
|
+
customAssetDirs.push(resolve("./runtime/public-assets-optional/resvg"));
|
|
541
|
+
else if (nitroCompatibility.png === "svg2png" && nitroCompatibility.wasm === "fetch")
|
|
542
|
+
customAssetDirs.push(resolve("./runtime/public-assets-optional/svg2png"));
|
|
543
|
+
if (nitroCompatibility.satori === "yoga-wasm")
|
|
544
|
+
customAssetDirs.push(resolve("./runtime/public-assets-optional/yoga"));
|
|
545
|
+
}
|
|
338
546
|
nuxt.hooks.hook("modules:done", async () => {
|
|
339
547
|
nuxt.hooks.callHook("og-image:config", config);
|
|
340
|
-
nuxt.options.runtimeConfig["nuxt-og-image"] = {
|
|
548
|
+
nuxt.options.runtimeConfig["nuxt-og-image"] = {
|
|
549
|
+
satoriOptions: config.satoriOptions,
|
|
550
|
+
runtimeSatori: config.runtimeSatori,
|
|
551
|
+
runtimeBrowser: config.runtimeBrowser,
|
|
552
|
+
// @ts-expect-error runtime type
|
|
553
|
+
defaults: config.defaults,
|
|
554
|
+
// avoid adding credentials
|
|
555
|
+
runtimeCacheStorage: typeof config.runtimeCacheStorage === "boolean" ? "default" : config.runtimeCacheStorage.driver,
|
|
556
|
+
// convert the fonts to uniform type to fix ts issue
|
|
557
|
+
fonts: config.fonts.map((f) => {
|
|
558
|
+
if (typeof f === "string") {
|
|
559
|
+
const [name, weight] = f.split(":");
|
|
560
|
+
return {
|
|
561
|
+
name,
|
|
562
|
+
weight
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
return f;
|
|
566
|
+
}),
|
|
567
|
+
assetDirs: [
|
|
568
|
+
resolve(nuxt.options.srcDir, nuxt.options.dir.public),
|
|
569
|
+
...customAssetDirs,
|
|
570
|
+
// always add runtime dirs for prerendering to work, these are just used as scan roots
|
|
571
|
+
resolve("./runtime/public-assets-optional/inter-font"),
|
|
572
|
+
resolve("./runtime/public-assets-optional/resvg"),
|
|
573
|
+
resolve("./runtime/public-assets-optional/yoga"),
|
|
574
|
+
resolve("./runtime/public-assets-optional/svg2png")
|
|
575
|
+
]
|
|
576
|
+
};
|
|
341
577
|
});
|
|
342
|
-
const useSatoriWasm = provider === "stackblitz";
|
|
343
578
|
nuxt.hooks.hook("nitro:config", async (nitroConfig) => {
|
|
344
579
|
nitroConfig.externals = defu(nitroConfig.externals || {}, {
|
|
345
580
|
inline: [runtimeDir]
|
|
346
581
|
});
|
|
347
|
-
if (config.
|
|
582
|
+
if (config.runtimeBrowser) {
|
|
348
583
|
nitroConfig.alias = nitroConfig.alias || {};
|
|
349
584
|
nitroConfig.alias.electron = "unenv/runtime/mock/proxy-cjs";
|
|
350
585
|
nitroConfig.alias.bufferutil = "unenv/runtime/mock/proxy-cjs";
|
|
351
586
|
nitroConfig.alias["utf-8-validate"] = "unenv/runtime/mock/proxy-cjs";
|
|
352
587
|
}
|
|
353
588
|
nitroConfig.publicAssets = nitroConfig.publicAssets || [];
|
|
354
|
-
|
|
589
|
+
customAssetDirs.forEach((dir) => {
|
|
590
|
+
nitroConfig.publicAssets.push({ dir, maxAge: 31536e3 });
|
|
591
|
+
});
|
|
355
592
|
const providerPath = `${runtimeDir}/nitro/providers`;
|
|
356
|
-
if (config.
|
|
357
|
-
nitroConfig.virtual["#nuxt-og-image/browser"] =
|
|
358
|
-
|
|
359
|
-
|
|
593
|
+
if (config.runtimeBrowser) {
|
|
594
|
+
nitroConfig.virtual["#nuxt-og-image/browser"] = `
|
|
595
|
+
let browser
|
|
360
596
|
export default async function() {
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
` : `export default async function() {
|
|
364
|
-
return () => {}
|
|
597
|
+
browser = browser || await import('${providerPath}/browser/${nitroCompatibility.browser}').then((m) => m.default || m)
|
|
598
|
+
return browser
|
|
365
599
|
}
|
|
366
600
|
`;
|
|
367
601
|
}
|
|
368
|
-
if (config.
|
|
369
|
-
nitroConfig.virtual["#nuxt-og-image/satori"] = `import satori from '${providerPath}/satori/${
|
|
370
|
-
export default
|
|
602
|
+
if (config.runtimeSatori) {
|
|
603
|
+
nitroConfig.virtual["#nuxt-og-image/satori"] = `import satori from '${providerPath}/satori/${nitroCompatibility.satori}'
|
|
604
|
+
export default function() {
|
|
371
605
|
return satori
|
|
372
606
|
}`;
|
|
373
|
-
nitroConfig.virtual["#nuxt-og-image/
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
607
|
+
nitroConfig.virtual["#nuxt-og-image/png"] = `import png from '${providerPath}/png/${nitroCompatibility.png}'
|
|
608
|
+
export default function() {
|
|
609
|
+
return png
|
|
610
|
+
}
|
|
611
|
+
`;
|
|
378
612
|
}
|
|
379
613
|
nitroConfig.virtual["#nuxt-og-image/provider"] = `
|
|
380
|
-
import satori from '${relative(nuxt.options.rootDir, resolve("./runtime/nitro/renderers/satori"))}'
|
|
381
|
-
import browser from '${relative(nuxt.options.rootDir, resolve("./runtime/nitro/renderers/browser"))}'
|
|
614
|
+
${config.runtimeSatori ? `import satori from '${relative(nuxt.options.rootDir, resolve("./runtime/nitro/renderers/satori"))}'` : ""}
|
|
615
|
+
${config.runtimeBrowser ? `import browser from '${relative(nuxt.options.rootDir, resolve("./runtime/nitro/renderers/browser"))}'` : ""}
|
|
382
616
|
|
|
383
617
|
export async function useProvider(provider) {
|
|
384
618
|
if (provider === 'satori')
|
|
385
|
-
return satori
|
|
619
|
+
return ${config.runtimeSatori ? "satori" : "null"}
|
|
386
620
|
if (provider === 'browser')
|
|
387
|
-
return browser
|
|
621
|
+
return ${config.runtimeBrowser ? "browser" : "null"}
|
|
622
|
+
return null
|
|
388
623
|
}
|
|
389
624
|
`;
|
|
390
625
|
});
|
|
391
626
|
nuxt.hooks.hook("nitro:init", async (nitro) => {
|
|
392
627
|
let screenshotQueue = [];
|
|
393
628
|
nitro.hooks.hook("compiled", async (_nitro) => {
|
|
394
|
-
if (
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
629
|
+
if (!config.runtimeSatori || nuxt.options.dev)
|
|
630
|
+
return;
|
|
631
|
+
if (config.fonts.includes("Inter:400"))
|
|
632
|
+
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"));
|
|
633
|
+
if (config.fonts.includes("Inter:700"))
|
|
634
|
+
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"));
|
|
635
|
+
const configuredEntry = nitro.options.rollupConfig?.output.entryFileNames;
|
|
636
|
+
const wasmProviderPath = resolve(_nitro.options.output.serverDir, typeof configuredEntry === "string" ? configuredEntry : "index.mjs");
|
|
637
|
+
const paths = [wasmProviderPath];
|
|
638
|
+
const chunks = await globby([`${_nitro.options.output.serverDir}/chunks/**/*.mjs`], { absolute: true });
|
|
639
|
+
paths.push(...chunks);
|
|
640
|
+
for (const path of paths) {
|
|
641
|
+
if (!await pathExists(path))
|
|
642
|
+
continue;
|
|
643
|
+
let contents = await readFile(path, "utf-8");
|
|
644
|
+
let updated = false;
|
|
645
|
+
if (_nitro.options.preset.includes("vercel") && path === wasmProviderPath) {
|
|
646
|
+
contents = contents.replace(".cwd(),", '?.cwd || "/",');
|
|
647
|
+
updated = true;
|
|
401
648
|
}
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
649
|
+
if (_nitro.options.preset.includes("netlify") && path.endsWith("netlify.mjs")) {
|
|
650
|
+
const match = "// TODO: handle event.isBase64Encoded\n });";
|
|
651
|
+
contents = contents.replace(match, `${match}
|
|
652
|
+
|
|
653
|
+
const headers = normalizeOutgoingHeaders(r.headers);
|
|
654
|
+
// image buffers must be base64 encoded
|
|
655
|
+
if (Buffer.isBuffer(r.body) && headers["content-type"].startsWith("image/")) {
|
|
656
|
+
return {
|
|
657
|
+
statusCode: r.status,
|
|
658
|
+
headers,
|
|
659
|
+
body: r.body.toString("base64"),
|
|
660
|
+
isBase64Encoded: true
|
|
661
|
+
};
|
|
662
|
+
}`);
|
|
663
|
+
updated = true;
|
|
664
|
+
}
|
|
665
|
+
for (const wasm of Wasms) {
|
|
666
|
+
if (contents.includes(wasm.placeholder)) {
|
|
667
|
+
if (nitroCompatibility.wasm === "import") {
|
|
668
|
+
contents = contents.replace(wasm.placeholder, `import("./${wasm.file}${nitroCompatibility.wasmImportQuery || ""}").then(m => m.default || m)`);
|
|
669
|
+
await copy(resolve(`./runtime/public-assets-optional/${wasm.path}`), resolve(dirname(path), wasm.file));
|
|
670
|
+
} else if (nitroCompatibility.wasm === "inline") {
|
|
671
|
+
const wasmBuffer = await readFile(resolve(`./runtime/public-assets-optional/${wasm.path}`));
|
|
672
|
+
contents = contents.replace(wasm.placeholder, `Buffer.from("${wasmBuffer}", "base64")`);
|
|
673
|
+
}
|
|
674
|
+
updated = true;
|
|
417
675
|
}
|
|
418
676
|
}
|
|
677
|
+
if (updated)
|
|
678
|
+
await writeFile(path, contents, { encoding: "utf-8" });
|
|
419
679
|
}
|
|
420
680
|
});
|
|
421
681
|
const _routeRulesMatcher = toRouteMatcher(
|
|
@@ -437,7 +697,7 @@ export async function useProvider(provider) {
|
|
|
437
697
|
...extractedOptions,
|
|
438
698
|
...routeRules.ogImage || {}
|
|
439
699
|
};
|
|
440
|
-
if ((nuxt.options._generate || entry.
|
|
700
|
+
if ((nuxt.options._generate || entry.cache) && entry.provider === "browser")
|
|
441
701
|
screenshotQueue.push(entry);
|
|
442
702
|
});
|
|
443
703
|
if (nuxt.options.dev)
|
|
@@ -485,14 +745,14 @@ export async function useProvider(provider) {
|
|
|
485
745
|
});
|
|
486
746
|
}
|
|
487
747
|
if (entry.component)
|
|
488
|
-
entry.html = await
|
|
748
|
+
entry.html = await globalThis.$fetch(entry.path);
|
|
489
749
|
}
|
|
490
750
|
for (const k in screenshotQueue) {
|
|
491
751
|
const entry = screenshotQueue[k];
|
|
492
752
|
const start = Date.now();
|
|
493
753
|
let hasError = false;
|
|
494
|
-
const
|
|
495
|
-
const filename = joinURL(
|
|
754
|
+
const dirname2 = joinURL(nitro.options.output.publicDir, entry.route, "/__og_image__/");
|
|
755
|
+
const filename = joinURL(dirname2, "/og.png");
|
|
496
756
|
try {
|
|
497
757
|
const imgBuffer = await screenshot(browser, {
|
|
498
758
|
...config.defaults || {},
|
|
@@ -500,7 +760,7 @@ export async function useProvider(provider) {
|
|
|
500
760
|
host
|
|
501
761
|
});
|
|
502
762
|
try {
|
|
503
|
-
await mkdirp(
|
|
763
|
+
await mkdirp(dirname2);
|
|
504
764
|
} catch (e) {
|
|
505
765
|
}
|
|
506
766
|
await writeFile(filename, imgBuffer);
|