nuxt-og-image 0.5.5 → 1.0.0-beta.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 +147 -29
- package/dist/client/200.html +7 -0
- package/dist/client/404.html +7 -0
- package/dist/client/_nuxt/Icon.4a9650c6.js +1 -0
- package/dist/client/_nuxt/Icon.e17ad835.css +1 -0
- package/dist/client/_nuxt/entry.0827acf4.css +1 -0
- package/dist/client/_nuxt/entry.ce848650.js +4 -0
- package/dist/client/_nuxt/error-404.556d8899.js +1 -0
- package/dist/client/_nuxt/error-404.68aa58b4.css +1 -0
- package/dist/client/_nuxt/error-500.70731718.js +1 -0
- package/dist/client/_nuxt/error-500.dc5710d1.css +1 -0
- package/dist/client/_nuxt/error-component.418ebd67.js +3 -0
- package/dist/client/index.html +7 -0
- package/dist/client/nuxt.svg +3 -0
- package/dist/module.d.ts +17 -12
- package/dist/module.json +1 -1
- package/dist/module.mjs +212 -103
- package/dist/runtime/browserUtil.mjs +3 -1
- package/dist/runtime/components/OgImageDynamic.d.ts +5 -0
- package/dist/runtime/components/OgImageDynamic.mjs +9 -0
- package/dist/runtime/components/OgImageScreenshot.d.ts +5 -9
- package/dist/runtime/components/OgImageScreenshot.mjs +2 -2
- package/dist/runtime/components/OgImageStatic.d.ts +5 -0
- package/dist/runtime/components/{OgImage.mjs → OgImageStatic.mjs} +3 -3
- package/dist/runtime/components/OgImageTemplate.island.vue +8 -83
- package/dist/runtime/composables/defineOgImage.d.ts +4 -9
- package/dist/runtime/composables/defineOgImage.mjs +35 -11
- package/dist/runtime/{browsers → nitro/browsers}/default.d.ts +0 -0
- package/dist/runtime/{browsers → nitro/browsers}/default.mjs +0 -0
- package/dist/runtime/{browsers → nitro/browsers}/lambda.d.ts +0 -0
- package/dist/runtime/{browsers → nitro/browsers}/lambda.mjs +0 -0
- package/dist/runtime/nitro/providers/browser.d.ts +3 -0
- package/dist/runtime/nitro/providers/browser.mjs +16 -0
- package/dist/runtime/nitro/providers/satori.d.ts +3 -0
- package/dist/runtime/nitro/providers/satori.mjs +48 -0
- package/dist/runtime/nitro/routes/__og_image__/html.d.ts +2 -0
- package/dist/runtime/nitro/routes/__og_image__/html.mjs +43 -0
- package/dist/runtime/nitro/routes/__og_image__/index.d.ts +2 -0
- package/dist/runtime/nitro/routes/__og_image__/index.mjs +26 -0
- package/dist/runtime/nitro/routes/__og_image__/og.png.d.ts +2 -0
- package/dist/runtime/nitro/routes/__og_image__/og.png.mjs +23 -0
- package/dist/runtime/nitro/{html.d.ts → routes/__og_image__/payload.d.ts} +2 -1
- package/dist/runtime/nitro/routes/__og_image__/payload.mjs +53 -0
- package/dist/runtime/nitro/routes/__og_image__/svg.d.ts +2 -0
- package/dist/runtime/nitro/routes/__og_image__/svg.mjs +16 -0
- package/dist/runtime/nitro/utils.d.ts +8 -0
- package/dist/runtime/nitro/utils.mjs +18 -0
- package/dist/runtime/public/inter-latin-ext-400-normal.woff +0 -0
- package/dist/runtime/public/inter-latin-ext-700-normal.woff +0 -0
- package/package.json +18 -7
- package/dist/runtime/components/OgImage.d.ts +0 -10
- package/dist/runtime/nitro/html.mjs +0 -55
- package/dist/runtime/nitro/image.d.ts +0 -3
- package/dist/runtime/nitro/image.mjs +0 -18
package/dist/module.mjs
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { mkdir, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { existsSync } from 'fs';
|
|
3
|
+
import { useNuxt, addTemplate, defineNuxtModule, createResolver, addServerHandler, addImports, addComponent } from '@nuxt/kit';
|
|
3
4
|
import { execa } from 'execa';
|
|
4
|
-
import { hash } from 'ohash';
|
|
5
5
|
import chalk from 'chalk';
|
|
6
6
|
import defu from 'defu';
|
|
7
7
|
import { toRouteMatcher, createRouter } from 'radix3';
|
|
8
|
-
import {
|
|
9
|
-
import
|
|
10
|
-
import {
|
|
8
|
+
import { joinURL } from 'ufo';
|
|
9
|
+
import { resolve, relative } from 'pathe';
|
|
10
|
+
import { tinyws } from 'tinyws';
|
|
11
|
+
import sirv from 'sirv';
|
|
12
|
+
import { createBirpcGroup } from 'birpc';
|
|
13
|
+
import { stringify, parse } from 'flatted';
|
|
11
14
|
|
|
12
15
|
async function createBrowser() {
|
|
13
16
|
try {
|
|
@@ -41,6 +44,8 @@ async function screenshot(browser, url, options) {
|
|
|
41
44
|
timeout: 1e4,
|
|
42
45
|
waitUntil: "networkidle"
|
|
43
46
|
});
|
|
47
|
+
if (options.delay)
|
|
48
|
+
await page.waitForTimeout(options.delay);
|
|
44
49
|
if (options.mask) {
|
|
45
50
|
await page.evaluate((mask) => {
|
|
46
51
|
for (const el of document.querySelectorAll(mask))
|
|
@@ -48,23 +53,118 @@ async function screenshot(browser, url, options) {
|
|
|
48
53
|
}, options.mask);
|
|
49
54
|
}
|
|
50
55
|
if (options.selector)
|
|
51
|
-
await page.locator(options.selector).screenshot();
|
|
56
|
+
return await page.locator(options.selector).screenshot();
|
|
52
57
|
return await page.screenshot();
|
|
53
58
|
}
|
|
54
59
|
|
|
55
|
-
const HtmlRendererRoute = "__og_image";
|
|
56
60
|
const PayloadScriptId = "nuxt-og-image-payload";
|
|
57
|
-
const MetaOgImageContentPlaceholder = "__NUXT_OG_IMAGE_PLACEHOLDER__";
|
|
58
|
-
const LinkPrerenderId = "nuxt-og-image-screenshot-path";
|
|
59
|
-
const DefaultRuntimeImageSuffix = "og-image.png";
|
|
60
61
|
const Constants = {
|
|
61
|
-
|
|
62
|
-
PayloadScriptId,
|
|
63
|
-
MetaOgImageContentPlaceholder,
|
|
64
|
-
LinkPrerenderId,
|
|
65
|
-
DefaultRuntimeImageSuffix
|
|
62
|
+
PayloadScriptId
|
|
66
63
|
};
|
|
67
64
|
|
|
65
|
+
function exposeConfig(alias, filename, config) {
|
|
66
|
+
const exports = Object.entries(config).map(([k, v]) => `export const ${k} = '${v}'`).join("\n");
|
|
67
|
+
useNuxt().options.alias[alias] = addTemplate({
|
|
68
|
+
filename,
|
|
69
|
+
getContents: () => exports
|
|
70
|
+
}).dst;
|
|
71
|
+
useNuxt().hooks.hook("nitro:config", (nitroConfig) => {
|
|
72
|
+
nitroConfig.virtual[alias] = exports;
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function setupPlaygroundRPC(nuxt, config) {
|
|
77
|
+
const serverFunctions = {
|
|
78
|
+
getConfig() {
|
|
79
|
+
return config;
|
|
80
|
+
},
|
|
81
|
+
async openInEditor(input) {
|
|
82
|
+
if (input.startsWith("./"))
|
|
83
|
+
input = resolve(process.cwd(), input);
|
|
84
|
+
const match = input.match(/^(.*?)([:\d]*)$/);
|
|
85
|
+
let suffix = "";
|
|
86
|
+
if (match) {
|
|
87
|
+
input = match[1];
|
|
88
|
+
suffix = match[2];
|
|
89
|
+
}
|
|
90
|
+
const file = [
|
|
91
|
+
input,
|
|
92
|
+
`${input}.js`,
|
|
93
|
+
`${input}.mjs`,
|
|
94
|
+
`${input}.ts`
|
|
95
|
+
].find((i) => existsSync(i));
|
|
96
|
+
if (file) {
|
|
97
|
+
await import('launch-editor').then((r) => (r.default || r)(file + suffix));
|
|
98
|
+
} else {
|
|
99
|
+
console.error("File not found:", input);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
const clients = /* @__PURE__ */ new Set();
|
|
104
|
+
const birpc = createBirpcGroup(serverFunctions, []);
|
|
105
|
+
nuxt.hook("builder:watch", (e, path) => {
|
|
106
|
+
if (e === "change")
|
|
107
|
+
birpc.boardcast.refresh.asEvent(path);
|
|
108
|
+
});
|
|
109
|
+
const middleware = async (req, res) => {
|
|
110
|
+
if (req.ws) {
|
|
111
|
+
const ws = await req.ws();
|
|
112
|
+
clients.add(ws);
|
|
113
|
+
const channel = {
|
|
114
|
+
post: (d) => ws.send(d),
|
|
115
|
+
on: (fn) => ws.on("message", fn),
|
|
116
|
+
serialize: stringify,
|
|
117
|
+
deserialize: parse
|
|
118
|
+
};
|
|
119
|
+
birpc.updateChannels((c) => {
|
|
120
|
+
c.push(channel);
|
|
121
|
+
});
|
|
122
|
+
ws.on("close", () => {
|
|
123
|
+
clients.delete(ws);
|
|
124
|
+
birpc.updateChannels((c) => {
|
|
125
|
+
const index = c.indexOf(channel);
|
|
126
|
+
if (index >= 0)
|
|
127
|
+
c.splice(index, 1);
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
} else if (req.method === "POST") {
|
|
131
|
+
const body = await getBodyJson(req);
|
|
132
|
+
if (body.method === "setPayload") ; else {
|
|
133
|
+
res.statusCode = 400;
|
|
134
|
+
}
|
|
135
|
+
res.end();
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
return {
|
|
139
|
+
middleware,
|
|
140
|
+
birpc
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
function getBodyJson(req) {
|
|
144
|
+
return new Promise((resolve2, reject) => {
|
|
145
|
+
let body = "";
|
|
146
|
+
req.on("data", (chunk) => body += chunk);
|
|
147
|
+
req.on("error", reject);
|
|
148
|
+
req.on("end", () => {
|
|
149
|
+
try {
|
|
150
|
+
resolve2(JSON.parse(body) || {});
|
|
151
|
+
} catch (e) {
|
|
152
|
+
reject(e);
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function extractOgPayload(html) {
|
|
159
|
+
const payload = html.match(new RegExp(`<script id="${PayloadScriptId}" type="application/json">(.+?)<\/script>`))?.[1];
|
|
160
|
+
if (payload) {
|
|
161
|
+
return JSON.parse(payload);
|
|
162
|
+
}
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
const PATH = "/__nuxt_og_image__";
|
|
166
|
+
const PATH_ENTRY = `${PATH}/entry`;
|
|
167
|
+
const PATH_PLAYGROUND = `${PATH}/client`;
|
|
68
168
|
const module = defineNuxtModule({
|
|
69
169
|
meta: {
|
|
70
170
|
name: "nuxt-og-image",
|
|
@@ -76,57 +176,74 @@ const module = defineNuxtModule({
|
|
|
76
176
|
},
|
|
77
177
|
defaults(nuxt) {
|
|
78
178
|
return {
|
|
179
|
+
experimentalNitroBrowser: false,
|
|
180
|
+
forcePrerender: !nuxt.options.dev && nuxt.options._generate,
|
|
79
181
|
host: nuxt.options.runtimeConfig.public?.siteUrl,
|
|
80
182
|
width: 1200,
|
|
81
|
-
height: 630
|
|
82
|
-
defaultIslandComponent: "OgImageTemplate",
|
|
83
|
-
outputDir: "_og-images",
|
|
84
|
-
serverSideRender: nuxt.options.dev || (process.env.NITRO_PRESET || "").includes("edge")
|
|
183
|
+
height: 630
|
|
85
184
|
};
|
|
86
185
|
},
|
|
87
186
|
async setup(config, nuxt) {
|
|
88
187
|
const { resolve } = createResolver(import.meta.url);
|
|
188
|
+
const distResolve = (p) => {
|
|
189
|
+
const cwd = resolve(".");
|
|
190
|
+
if (cwd.endsWith("/dist"))
|
|
191
|
+
return resolve(p);
|
|
192
|
+
return resolve(`../dist/${p}`);
|
|
193
|
+
};
|
|
89
194
|
nuxt.options.experimental.componentIslands = true;
|
|
90
195
|
const isEdge = (process.env.NITRO_PRESET || "").includes("edge");
|
|
91
196
|
addTemplate({
|
|
92
197
|
filename: "nuxt-og-image.d.ts",
|
|
93
198
|
getContents: () => {
|
|
94
199
|
return `// Generated by nuxt-og-image
|
|
200
|
+
interface NuxtOgImageNitroRules {
|
|
201
|
+
ogImage?: false | Record<string, any>
|
|
202
|
+
}
|
|
95
203
|
declare module 'nitropack' {
|
|
96
|
-
interface NitroRouteRules {
|
|
97
|
-
|
|
98
|
-
}
|
|
204
|
+
interface NitroRouteRules extends NuxtOgImageNitroRules {}
|
|
205
|
+
interface NitroRouteConfig extends NuxtOgImageNitroRules {}
|
|
99
206
|
}
|
|
207
|
+
export {}
|
|
100
208
|
`;
|
|
101
209
|
}
|
|
102
210
|
});
|
|
103
211
|
nuxt.hooks.hook("prepare:types", ({ references }) => {
|
|
104
212
|
references.push({ path: resolve(nuxt.options.buildDir, "nuxt-og-image.d.ts") });
|
|
105
213
|
});
|
|
106
|
-
|
|
214
|
+
["html", "payload", "svg", "og.png"].forEach((type) => {
|
|
107
215
|
addServerHandler({
|
|
108
|
-
handler: resolve(
|
|
216
|
+
handler: resolve(`./runtime/nitro/routes/__og_image__/${type}`)
|
|
109
217
|
});
|
|
110
|
-
if (config.serverSideRender) {
|
|
111
|
-
addServerHandler({
|
|
112
|
-
handler: resolve("./runtime/nitro/image")
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
addImports({
|
|
117
|
-
name: "defineOgImage",
|
|
118
|
-
from: resolve("./runtime/composables/defineOgImage")
|
|
119
218
|
});
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
219
|
+
if (nuxt.options.dev) {
|
|
220
|
+
const playgroundDir = distResolve("./client");
|
|
221
|
+
const {
|
|
222
|
+
middleware: rpcMiddleware
|
|
223
|
+
} = setupPlaygroundRPC(nuxt, config);
|
|
224
|
+
nuxt.hook("vite:serverCreated", (server) => {
|
|
225
|
+
server.middlewares.use(PATH_ENTRY, tinyws());
|
|
226
|
+
server.middlewares.use(PATH_ENTRY, rpcMiddleware);
|
|
227
|
+
if (existsSync(playgroundDir))
|
|
228
|
+
server.middlewares.use(PATH_PLAYGROUND, sirv(playgroundDir, { single: true, dev: true }));
|
|
229
|
+
});
|
|
230
|
+
addServerHandler({
|
|
231
|
+
handler: resolve("./runtime/nitro/routes/__og_image__/index")
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
["defineOgImageDynamic", "defineOgImageStatic", "defineOgImageScreenshot"].forEach((name) => {
|
|
235
|
+
addImports({
|
|
236
|
+
name,
|
|
237
|
+
from: resolve("./runtime/composables/defineOgImage")
|
|
238
|
+
});
|
|
123
239
|
});
|
|
124
240
|
await addComponent({
|
|
125
241
|
name: "OgImageTemplate",
|
|
126
242
|
filePath: resolve("./runtime/components/OgImageTemplate.island.vue"),
|
|
243
|
+
global: true,
|
|
127
244
|
island: true
|
|
128
245
|
});
|
|
129
|
-
["
|
|
246
|
+
["OgImageStatic", "OgImageDynamic", "OgImageScreenshot"].forEach((name) => {
|
|
130
247
|
addComponent({
|
|
131
248
|
name,
|
|
132
249
|
filePath: resolve(`./runtime/components/${name}`),
|
|
@@ -135,67 +252,65 @@ declare module 'nitropack' {
|
|
|
135
252
|
});
|
|
136
253
|
const runtimeDir = resolve("./runtime");
|
|
137
254
|
nuxt.options.build.transpile.push(runtimeDir);
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
filename: "nuxt-og-image-constants.mjs",
|
|
141
|
-
getContents: () => constScript
|
|
142
|
-
}).dst;
|
|
255
|
+
exposeConfig("#nuxt-og-image/constants", "nuxt-og-image-constants.mjs", Constants);
|
|
256
|
+
exposeConfig("#nuxt-og-image/config", "nuxt-og-image-config.mjs", config);
|
|
143
257
|
nuxt.hooks.hook("nitro:config", (nitroConfig) => {
|
|
144
258
|
nitroConfig.externals = defu(nitroConfig.externals || {}, {
|
|
145
259
|
inline: [runtimeDir]
|
|
146
260
|
});
|
|
147
|
-
nitroConfig.
|
|
148
|
-
nitroConfig.
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
261
|
+
nitroConfig.publicAssets = nitroConfig.publicAssets || [];
|
|
262
|
+
nitroConfig.publicAssets.push({ dir: resolve("./runtime/public"), maxAge: 31536e3 });
|
|
263
|
+
nitroConfig.virtual["#nuxt-og-image/browser"] = `export { createBrowser } from '${runtimeDir}/nitro/browsers/${isEdge ? "lambda" : "default"}'`;
|
|
264
|
+
nitroConfig.virtual["#nuxt-og-image/provider"] = `
|
|
265
|
+
import satori from '${runtimeDir}/nitro/providers/satori'
|
|
266
|
+
import browser from '${runtimeDir}/nitro/providers/browser'
|
|
267
|
+
|
|
268
|
+
export function useProvider(provider) {
|
|
269
|
+
if (provider === 'satori')
|
|
270
|
+
return satori
|
|
271
|
+
if (provider === 'browser')
|
|
272
|
+
return browser
|
|
273
|
+
}
|
|
274
|
+
`;
|
|
275
|
+
if (config.experimentalNitroBrowser) {
|
|
276
|
+
nitroConfig.virtual["#nuxt-og-image/providers/browser"] = `export * from '${runtimeDir}/nitro/providers/browser'`;
|
|
277
|
+
if (isEdge) {
|
|
278
|
+
["puppeteer", "bufferutil", "utf-8-validate"].forEach((name) => {
|
|
279
|
+
nitroConfig.alias[name] = "unenv/runtime/mock/proxy";
|
|
280
|
+
});
|
|
281
|
+
}
|
|
153
282
|
}
|
|
154
283
|
});
|
|
155
284
|
nuxt.hooks.hook("nitro:init", async (nitro) => {
|
|
156
|
-
let
|
|
157
|
-
let cleanupEntries = [];
|
|
285
|
+
let screenshotQueue = [];
|
|
158
286
|
const _routeRulesMatcher = toRouteMatcher(
|
|
159
287
|
createRouter({ routes: nitro.options.routeRules })
|
|
160
288
|
);
|
|
161
|
-
const outputPath = join(nitro.options.output.publicDir, config.outputDir);
|
|
162
289
|
nitro.hooks.hook("prerender:generate", async (ctx) => {
|
|
163
|
-
if (ctx.route.includes(".") || ctx.route.endsWith(
|
|
290
|
+
if (ctx.route.includes(".") || ctx.route.endsWith("__og_image__/html"))
|
|
164
291
|
return;
|
|
165
|
-
|
|
292
|
+
const html = ctx.contents;
|
|
166
293
|
if (!html)
|
|
167
294
|
return;
|
|
168
|
-
|
|
169
|
-
|
|
295
|
+
const extractedPayload = extractOgPayload(html);
|
|
296
|
+
ctx.contents = html.replace(new RegExp(`<script id="${PayloadScriptId}" type="application/json">(.*?)<\/script>`), "");
|
|
170
297
|
const routeRules = defu({}, ..._routeRulesMatcher.matchAll(ctx.route).reverse());
|
|
171
|
-
if (routeRules.ogImage === false)
|
|
298
|
+
if (!extractedPayload || routeRules.ogImage === false)
|
|
172
299
|
return;
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
absoluteUrl,
|
|
179
|
-
outputPath: joinURL(nitro.options.output.publicDir, config.outputDir, fileName),
|
|
180
|
-
linkingHtml: joinURL(nitro.options.output.publicDir, ctx.fileName),
|
|
181
|
-
route: ctx.route,
|
|
182
|
-
hasPayload: screenshotPath,
|
|
183
|
-
routeRules: routeRules.ogImage || "",
|
|
184
|
-
screenshotPath: screenshotPath || ctx.route
|
|
300
|
+
const payload = {
|
|
301
|
+
path: ctx.route,
|
|
302
|
+
...extractedPayload,
|
|
303
|
+
...routeRules.ogImage || {},
|
|
304
|
+
ctx
|
|
185
305
|
};
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
ctx.contents = html;
|
|
306
|
+
if ((nuxt.options._generate || payload.prerender) && payload.provider === "browser")
|
|
307
|
+
screenshotQueue.push(payload);
|
|
189
308
|
});
|
|
190
309
|
if (nuxt.options.dev)
|
|
191
310
|
return;
|
|
192
|
-
const
|
|
193
|
-
if (
|
|
311
|
+
const captureScreenshots = async () => {
|
|
312
|
+
if (screenshotQueue.length === 0)
|
|
194
313
|
return;
|
|
195
|
-
try {
|
|
196
|
-
await mkdir(outputPath, { recursive: true });
|
|
197
|
-
} catch (e) {
|
|
198
|
-
}
|
|
199
314
|
const previewProcess = execa("npx", ["serve", nitro.options.output.publicDir]);
|
|
200
315
|
let browser = null;
|
|
201
316
|
try {
|
|
@@ -209,25 +324,34 @@ declare module 'nitropack' {
|
|
|
209
324
|
})).trim();
|
|
210
325
|
browser = await createBrowser();
|
|
211
326
|
if (browser) {
|
|
212
|
-
nitro.logger.info(`
|
|
213
|
-
for (const k in
|
|
214
|
-
const entry =
|
|
327
|
+
nitro.logger.info(`Pre-rendering ${screenshotQueue.length} og:image screenshots...`);
|
|
328
|
+
for (const k in screenshotQueue) {
|
|
329
|
+
const entry = screenshotQueue[k];
|
|
215
330
|
const start = Date.now();
|
|
216
331
|
let hasError = false;
|
|
332
|
+
const dirname = joinURL(nitro.options.output.publicDir, `${entry.ctx.fileName.replace("index.html", "")}__og_image__/`);
|
|
333
|
+
const filename = joinURL(dirname, "/og.png");
|
|
217
334
|
try {
|
|
218
|
-
const imgBuffer = await screenshot(browser, `${host}${entry.
|
|
219
|
-
|
|
335
|
+
const imgBuffer = await screenshot(browser, `${host}${entry.path}`, {
|
|
336
|
+
...config,
|
|
337
|
+
...entry
|
|
338
|
+
});
|
|
339
|
+
try {
|
|
340
|
+
await mkdir(dirname, { recursive: true });
|
|
341
|
+
} catch (e) {
|
|
342
|
+
}
|
|
343
|
+
await writeFile(filename, imgBuffer);
|
|
220
344
|
} catch (e) {
|
|
221
345
|
hasError = true;
|
|
222
346
|
console.error(e);
|
|
223
347
|
}
|
|
224
348
|
const generateTimeMS = Date.now() - start;
|
|
225
349
|
nitro.logger.log(chalk[hasError ? "red" : "gray"](
|
|
226
|
-
` ${Number(k) ===
|
|
350
|
+
` ${Number(k) === screenshotQueue.length - 1 ? "\u2514\u2500" : "\u251C\u2500"} ${relative(nitro.options.output.publicDir, filename)} (${generateTimeMS}ms) ${Math.round((Number(k) + 1) / screenshotQueue.length * 100)}%`
|
|
227
351
|
));
|
|
228
352
|
}
|
|
229
353
|
} else {
|
|
230
|
-
nitro.logger.log(chalk.red("Failed to create browser to create og:images."));
|
|
354
|
+
nitro.logger.log(chalk.red("Failed to create a browser to create og:images."));
|
|
231
355
|
}
|
|
232
356
|
} catch (e) {
|
|
233
357
|
console.error(e);
|
|
@@ -235,28 +359,13 @@ declare module 'nitropack' {
|
|
|
235
359
|
await browser?.close();
|
|
236
360
|
previewProcess.kill();
|
|
237
361
|
}
|
|
238
|
-
|
|
239
|
-
entries = [];
|
|
362
|
+
screenshotQueue = [];
|
|
240
363
|
};
|
|
241
364
|
nitro.hooks.hook("rollup:before", async () => {
|
|
242
|
-
await
|
|
365
|
+
await captureScreenshots();
|
|
243
366
|
});
|
|
244
367
|
nitro.hooks.hook("close", async () => {
|
|
245
|
-
await
|
|
246
|
-
for (const entry of cleanupEntries) {
|
|
247
|
-
try {
|
|
248
|
-
const html = await readFile(entry.linkingHtml, "utf-8");
|
|
249
|
-
const newHtml = html.replace("__OG_IMAGE_SCREENSHOT_ALT", `Web page screenshot of ${entry.route}.`).replace(new RegExp(`<link id="${LinkPrerenderId}" rel="prerender" href="(.*?)">`), "").replace(new RegExp(`<script id="${PayloadScriptId}" type="application/json">(.*?)<\/script>`), "").replace("\n\n", "\n");
|
|
250
|
-
if (html !== newHtml) {
|
|
251
|
-
await writeFile(entry.linkingHtml, newHtml, { encoding: "utf-8" });
|
|
252
|
-
}
|
|
253
|
-
} catch (e) {
|
|
254
|
-
console.error(e);
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
const ogImageFolders = await fg([`**/${HtmlRendererRoute}`], { cwd: nitro.options.output.publicDir, onlyDirectories: true });
|
|
258
|
-
for (const ogImageFolder of ogImageFolders)
|
|
259
|
-
await rm(join(nitro.options.output.publicDir, ogImageFolder), { recursive: true, force: true });
|
|
368
|
+
await captureScreenshots();
|
|
260
369
|
});
|
|
261
370
|
});
|
|
262
371
|
}
|
|
@@ -10,6 +10,8 @@ export async function screenshot(browser, url, options) {
|
|
|
10
10
|
timeout: 1e4,
|
|
11
11
|
waitUntil: "networkidle"
|
|
12
12
|
});
|
|
13
|
+
if (options.delay)
|
|
14
|
+
await page.waitForTimeout(options.delay);
|
|
13
15
|
if (options.mask) {
|
|
14
16
|
await page.evaluate((mask) => {
|
|
15
17
|
for (const el of document.querySelectorAll(mask))
|
|
@@ -17,6 +19,6 @@ export async function screenshot(browser, url, options) {
|
|
|
17
19
|
}, options.mask);
|
|
18
20
|
}
|
|
19
21
|
if (options.selector)
|
|
20
|
-
await page.locator(options.selector).screenshot();
|
|
22
|
+
return await page.locator(options.selector).screenshot();
|
|
21
23
|
return await page.screenshot();
|
|
22
24
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { OgImagePayload } from '../../types';
|
|
2
|
+
declare const _default: import("vue").DefineComponent<OgImagePayload, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<OgImagePayload>>, {
|
|
3
|
+
[x: string]: any;
|
|
4
|
+
}>;
|
|
5
|
+
export default _default;
|
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
}
|
|
6
|
-
title?: string | undefined;
|
|
7
|
-
description?: string | undefined;
|
|
8
|
-
component?: string | undefined;
|
|
9
|
-
}>, {}>;
|
|
1
|
+
import type { OgImageScreenshotPayload } from '../../types';
|
|
2
|
+
declare const _default: import("vue").DefineComponent<OgImageScreenshotPayload, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<OgImageScreenshotPayload>>, {
|
|
3
|
+
[x: string]: any;
|
|
4
|
+
[x: number]: any;
|
|
5
|
+
}>;
|
|
10
6
|
export default _default;
|
|
@@ -2,8 +2,8 @@ import { defineComponent } from "vue";
|
|
|
2
2
|
import { defineOgImageScreenshot } from "#imports";
|
|
3
3
|
export default defineComponent({
|
|
4
4
|
name: "OgImageScreenshot",
|
|
5
|
-
setup() {
|
|
6
|
-
defineOgImageScreenshot();
|
|
5
|
+
setup(_, { attrs }) {
|
|
6
|
+
defineOgImageScreenshot(attrs);
|
|
7
7
|
return () => null;
|
|
8
8
|
}
|
|
9
9
|
});
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { OgImagePayload } from '../../types';
|
|
2
|
+
declare const _default: import("vue").DefineComponent<OgImagePayload, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<OgImagePayload>>, {
|
|
3
|
+
[x: string]: any;
|
|
4
|
+
}>;
|
|
5
|
+
export default _default;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { defineComponent } from "vue";
|
|
2
|
-
import {
|
|
2
|
+
import { defineOgImageStatic } from "#imports";
|
|
3
3
|
export default defineComponent({
|
|
4
|
-
name: "
|
|
4
|
+
name: "OgImageStatic",
|
|
5
5
|
setup(_, { attrs }) {
|
|
6
|
-
|
|
6
|
+
defineOgImageStatic(attrs);
|
|
7
7
|
return () => null;
|
|
8
8
|
}
|
|
9
9
|
});
|
|
@@ -7,89 +7,14 @@ const props = defineProps({
|
|
|
7
7
|
</script>
|
|
8
8
|
|
|
9
9
|
<template>
|
|
10
|
-
<div
|
|
11
|
-
<div
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
<p
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
<strong>Payload</strong>
|
|
19
|
-
<code>
|
|
20
|
-
<pre>{{ props }}</pre>
|
|
21
|
-
</code>
|
|
10
|
+
<div :style="{ padding: '0 60px', width: '100%', height: '100%', backgroundColor: '#0c0c0c', backgroundImage: 'linear-gradient(to bottom, #dbf4ff, #fff1f1)', display: 'flex', alignItems: 'center' }">
|
|
11
|
+
<div :style="{ padding: '0 30px', display: 'flex', flexDirection: 'column' }">
|
|
12
|
+
<p :style="{ fontSize: '60px', fontWeight: 'bold', marginBottom: '20px' }">
|
|
13
|
+
{{ title }}
|
|
14
|
+
</p>
|
|
15
|
+
<p :style="{ fontSize: '26px' }">
|
|
16
|
+
{{ description }}
|
|
17
|
+
</p>
|
|
22
18
|
</div>
|
|
23
19
|
</div>
|
|
24
20
|
</template>
|
|
25
|
-
|
|
26
|
-
<style scoped>
|
|
27
|
-
.wrap {
|
|
28
|
-
width: 100%;
|
|
29
|
-
height: 100%;
|
|
30
|
-
display: flex;
|
|
31
|
-
align-items: center;
|
|
32
|
-
flex-direction: column;
|
|
33
|
-
color: white;
|
|
34
|
-
font-weight: bold;
|
|
35
|
-
font-family: sans-serif;
|
|
36
|
-
background-color: #0c0c0c;
|
|
37
|
-
position: relative;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
.bg1 {
|
|
41
|
-
top: 0;
|
|
42
|
-
left: 0;
|
|
43
|
-
display: block;
|
|
44
|
-
position: absolute;
|
|
45
|
-
width: 100%;
|
|
46
|
-
height: 100%;
|
|
47
|
-
padding: 0 !important;
|
|
48
|
-
margin: 0 !important;
|
|
49
|
-
background-color: #0c0c0c;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
.bg2 {
|
|
53
|
-
top: 0;
|
|
54
|
-
left: 0;
|
|
55
|
-
z-index: 1;
|
|
56
|
-
display: block;
|
|
57
|
-
position: absolute;
|
|
58
|
-
width: 100%;
|
|
59
|
-
height: 100%;
|
|
60
|
-
padding: 0 !important;
|
|
61
|
-
margin: 0 !important;
|
|
62
|
-
background: radial-gradient(at 100% 100%, #0f766e, rgba(12, 12, 12, 0.1) 60%);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
a {
|
|
66
|
-
color: inherit;
|
|
67
|
-
padding-bottom: 3px;
|
|
68
|
-
text-decoration: none;
|
|
69
|
-
border-bottom: 3px solid #ff8235;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
.wrap > div {
|
|
73
|
-
z-index: 2;
|
|
74
|
-
padding: 2rem;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
code pre {
|
|
78
|
-
background: #333;
|
|
79
|
-
color: white;
|
|
80
|
-
padding: 1rem;
|
|
81
|
-
border-radius: 0.5rem;
|
|
82
|
-
font-weight: lighter;
|
|
83
|
-
font-size: 1.1rem;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
p {
|
|
87
|
-
font-size: 1.5em;
|
|
88
|
-
font-weight: normal;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
h1 {
|
|
92
|
-
font-size: 4rem;
|
|
93
|
-
margin: 0;
|
|
94
|
-
}
|
|
95
|
-
</style>
|
|
@@ -1,10 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
component?: string;
|
|
6
|
-
alt?: string;
|
|
7
|
-
[key: string]: any;
|
|
8
|
-
}
|
|
9
|
-
export declare function defineOgImageScreenshot(): void;
|
|
1
|
+
import type { OgImagePayload, OgImageScreenshotPayload } from '../../types';
|
|
2
|
+
export declare function defineOgImageScreenshot(options?: OgImageScreenshotPayload): void;
|
|
3
|
+
export declare function defineOgImageDynamic(options?: OgImageScreenshotPayload): void;
|
|
4
|
+
export declare function defineOgImageStatic(options?: OgImageScreenshotPayload): void;
|
|
10
5
|
export declare function defineOgImage(options?: OgImagePayload): void;
|