nuxt-og-image 1.0.0-beta.10 → 1.0.0-beta.12
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 +3 -10
- package/dist/module.d.ts +1 -3
- package/dist/module.json +1 -1
- package/dist/module.mjs +7 -16
- package/dist/runtime/nitro/providers/satori/index.mjs +4 -4
- package/dist/runtime/nitro/providers/satori/utils.d.ts +1 -6
- package/dist/runtime/nitro/providers/satori/utils.mjs +20 -15
- package/dist/runtime/nitro/routes/__og_image__/font.d.ts +2 -0
- package/dist/runtime/nitro/routes/__og_image__/font.mjs +14 -0
- package/dist/runtime/nitro/routes/__og_image__/html.mjs +9 -6
- package/package.json +1 -1
- 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/README.md
CHANGED
|
@@ -34,17 +34,10 @@ Enlightened OG Image generation for Nuxt 3.
|
|
|
34
34
|
|
|
35
35
|
## Features
|
|
36
36
|
|
|
37
|
-
## 🎨 Designer - Satori & Browser
|
|
38
|
-
|
|
39
37
|
- 🎨 Design your `og:image` in the Og Image Playground with full HMR
|
|
40
|
-
-
|
|
41
|
-
-
|
|
42
|
-
|
|
43
|
-
## Screenshots - Browser
|
|
44
|
-
|
|
45
|
-
- 📸 OR just generate screenshots
|
|
46
|
-
- ⚙️ Screenshot options to hide elements, wait for animations, and more
|
|
47
|
-
|
|
38
|
+
- ▲ Blazing fast Satori provider: Tailwind classes, Google fonts, emojis
|
|
39
|
+
- 🤖 Alternative Browser provider for painless, complex templates OR just generate screenshots
|
|
40
|
+
- 📸 Feeling lazy? Just generate screenshots, hide elements, wait for animations, and more
|
|
48
41
|
|
|
49
42
|
## Install
|
|
50
43
|
|
package/dist/module.d.ts
CHANGED
|
@@ -39,9 +39,7 @@ interface ModuleOptions {
|
|
|
39
39
|
host: string;
|
|
40
40
|
defaults: OgImageOptions;
|
|
41
41
|
experimentalNitroBrowser: boolean;
|
|
42
|
-
|
|
43
|
-
publicPath: string;
|
|
44
|
-
}>;
|
|
42
|
+
fonts: `${string}:${number}`[];
|
|
45
43
|
satoriOptions: Partial<SatoriOptions>;
|
|
46
44
|
forcePrerender: boolean;
|
|
47
45
|
}
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -179,25 +179,14 @@ const module = defineNuxtModule({
|
|
|
179
179
|
width: 1200,
|
|
180
180
|
height: 630
|
|
181
181
|
},
|
|
182
|
-
|
|
183
|
-
{
|
|
184
|
-
name: "Inter",
|
|
185
|
-
weight: 400,
|
|
186
|
-
style: "normal",
|
|
187
|
-
publicPath: "/inter-latin-ext-400-normal.woff"
|
|
188
|
-
},
|
|
189
|
-
{
|
|
190
|
-
name: "Inter",
|
|
191
|
-
weight: 700,
|
|
192
|
-
style: "normal",
|
|
193
|
-
publicPath: "/inter-latin-ext-700-normal.woff"
|
|
194
|
-
}
|
|
195
|
-
],
|
|
182
|
+
fonts: [],
|
|
196
183
|
satoriOptions: {}
|
|
197
184
|
};
|
|
198
185
|
},
|
|
199
186
|
async setup(config, nuxt) {
|
|
200
187
|
const { resolve } = createResolver(import.meta.url);
|
|
188
|
+
if (!config.fonts.length)
|
|
189
|
+
config.fonts = ["Inter:400", "Inter:700"];
|
|
201
190
|
const distResolve = (p) => {
|
|
202
191
|
const cwd = resolve(".");
|
|
203
192
|
if (cwd.endsWith("/dist"))
|
|
@@ -233,6 +222,10 @@ export {}
|
|
|
233
222
|
handler: resolve(`./runtime/nitro/routes/__og_image__/${type}`)
|
|
234
223
|
});
|
|
235
224
|
});
|
|
225
|
+
addServerHandler({
|
|
226
|
+
route: "/api/og-image-font",
|
|
227
|
+
handler: resolve("./runtime/nitro/routes/__og_image__/font")
|
|
228
|
+
});
|
|
236
229
|
if (nuxt.options.dev) {
|
|
237
230
|
const playgroundDir = distResolve("./client");
|
|
238
231
|
const {
|
|
@@ -274,8 +267,6 @@ export {}
|
|
|
274
267
|
nitroConfig.externals = defu(nitroConfig.externals || {}, {
|
|
275
268
|
inline: [runtimeDir]
|
|
276
269
|
});
|
|
277
|
-
nitroConfig.publicAssets = nitroConfig.publicAssets || [];
|
|
278
|
-
nitroConfig.publicAssets.push({ dir: resolve("./runtime/public"), maxAge: 31536e3 });
|
|
279
270
|
nitroConfig.virtual["#nuxt-og-image/browser"] = `export { createBrowser } from '${runtimeDir}/nitro/browsers/${isEdge ? "lambda" : "default"}'`;
|
|
280
271
|
nitroConfig.virtual["#nuxt-og-image/provider"] = `
|
|
281
272
|
import satori from '${runtimeDir}/nitro/providers/satori'
|
|
@@ -3,12 +3,12 @@ import satori from "satori";
|
|
|
3
3
|
import { parseURL } from "ufo";
|
|
4
4
|
import { Resvg } from "@resvg/resvg-js";
|
|
5
5
|
import twemoji from "twemoji";
|
|
6
|
-
import {
|
|
6
|
+
import { loadFont, walkSatoriTree } from "./utils.mjs";
|
|
7
7
|
import imageSrc from "./plugins/imageSrc.mjs";
|
|
8
8
|
import twClasses from "./plugins/twClasses.mjs";
|
|
9
9
|
import flex from "./plugins/flex.mjs";
|
|
10
10
|
import emojis from "./plugins/emojis.mjs";
|
|
11
|
-
import {
|
|
11
|
+
import { fonts, satoriOptions } from "#nuxt-og-image/config";
|
|
12
12
|
export default {
|
|
13
13
|
name: "satori",
|
|
14
14
|
createPng: async function createPng(baseUrl, options) {
|
|
@@ -26,8 +26,8 @@ export default {
|
|
|
26
26
|
ext: ".svg"
|
|
27
27
|
});
|
|
28
28
|
satoriOptions.fonts = satoriOptions.fonts || [];
|
|
29
|
-
for (const font of
|
|
30
|
-
satoriOptions.fonts.push(await
|
|
29
|
+
for (const font of fonts)
|
|
30
|
+
satoriOptions.fonts.push(await loadFont(url, font));
|
|
31
31
|
const satoriTree = convertHtmlToSatori(emojiedFont);
|
|
32
32
|
await walkSatoriTree(url, satoriTree, [
|
|
33
33
|
emojis(url),
|
|
@@ -1,10 +1,5 @@
|
|
|
1
|
-
import type { SatoriOptions } from 'satori';
|
|
2
1
|
import type { ParsedURL } from 'ufo';
|
|
3
2
|
import type { SatoriTransformer, VNode } from '../../../../types';
|
|
4
|
-
export declare function
|
|
5
|
-
publicPath?: string;
|
|
6
|
-
}): Promise<import("satori").Font & {
|
|
7
|
-
publicPath?: string | undefined;
|
|
8
|
-
}>;
|
|
3
|
+
export declare function loadFont(url: ParsedURL, font: string): Promise<any>;
|
|
9
4
|
export declare function walkSatoriTree(url: ParsedURL, node: VNode, plugins: SatoriTransformer[]): Promise<void>;
|
|
10
5
|
export declare function defineSatoriTransformer(transformer: (url: ParsedURL) => SatoriTransformer): (url: ParsedURL) => SatoriTransformer;
|
|
@@ -1,19 +1,24 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
1
|
+
import { useStorage } from "#internal/nitro";
|
|
2
|
+
const cachedFonts = {};
|
|
3
|
+
export async function loadFont(url, font) {
|
|
4
|
+
if (cachedFonts[font])
|
|
5
|
+
return cachedFonts[font];
|
|
6
|
+
const [name, weight] = font.split(":");
|
|
7
|
+
const fontUrl = await $fetch("/api/og-image-font", {
|
|
8
|
+
query: { name, weight }
|
|
9
|
+
});
|
|
10
|
+
let data;
|
|
11
|
+
const storageKey = `nuxt-og-image:font:${font}`;
|
|
12
|
+
const hasStoredFont = await useStorage().hasItem(storageKey);
|
|
13
|
+
if (!hasStoredFont) {
|
|
14
|
+
data = await $fetch(fontUrl, {
|
|
15
|
+
responseType: "arrayBuffer"
|
|
16
|
+
});
|
|
17
|
+
await useStorage().setItem(storageKey, data);
|
|
18
|
+
} else {
|
|
19
|
+
data = await useStorage().getItem(storageKey);
|
|
15
20
|
}
|
|
16
|
-
return font;
|
|
21
|
+
return cachedFonts[font] = { name, weight, data, style: "normal" };
|
|
17
22
|
}
|
|
18
23
|
export async function walkSatoriTree(url, node, plugins) {
|
|
19
24
|
if (!node.props?.children)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { getQuery } from "h3";
|
|
2
|
+
import { defineCachedEventHandler } from "#internal/nitro";
|
|
3
|
+
export default defineCachedEventHandler(async (e) => {
|
|
4
|
+
const { name, weight } = getQuery(e);
|
|
5
|
+
const css = await await $fetch(`https://fonts.googleapis.com/css2?family=${name || "Inter"}:wght@${weight || 400}`, {
|
|
6
|
+
headers: {
|
|
7
|
+
"User-Agent": "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; de-at) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/5.0.5 Safari/533.21.1"
|
|
8
|
+
}
|
|
9
|
+
});
|
|
10
|
+
const resource = css.match(/src: url\((.+)\) format\('(opentype|truetype)'\)/);
|
|
11
|
+
if (!resource)
|
|
12
|
+
return;
|
|
13
|
+
return resource[1];
|
|
14
|
+
});
|
|
@@ -3,7 +3,7 @@ import { renderSSRHead } from "@unhead/ssr";
|
|
|
3
3
|
import { createHeadCore } from "@unhead/vue";
|
|
4
4
|
import { defineEventHandler, getQuery, sendRedirect } from "h3";
|
|
5
5
|
import { fetchOptions, renderIsland, useHostname } from "../../utils.mjs";
|
|
6
|
-
import { defaults } from "#nuxt-og-image/config";
|
|
6
|
+
import { defaults, fonts } from "#nuxt-og-image/config";
|
|
7
7
|
export default defineEventHandler(async (e) => {
|
|
8
8
|
const path = parseURL(e.path).pathname;
|
|
9
9
|
if (!path.endsWith("__og_image__/html"))
|
|
@@ -19,7 +19,7 @@ export default defineEventHandler(async (e) => {
|
|
|
19
19
|
head.push({
|
|
20
20
|
style: [
|
|
21
21
|
{
|
|
22
|
-
innerHTML:
|
|
22
|
+
innerHTML: `body { font-family: '${fonts[0].split(":")[0].replace("+", " ")}', sans-serif; }`
|
|
23
23
|
},
|
|
24
24
|
scale ? {
|
|
25
25
|
innerHTML: `body {
|
|
@@ -58,10 +58,13 @@ img.emoji {
|
|
|
58
58
|
href: "https://cdn.jsdelivr.net/npm/gardevoir",
|
|
59
59
|
rel: "stylesheet"
|
|
60
60
|
},
|
|
61
|
-
{
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
61
|
+
...fonts.map((font) => {
|
|
62
|
+
const [name, weight] = font.split(":");
|
|
63
|
+
return {
|
|
64
|
+
href: `https://fonts.googleapis.com/css2?family=${name}:wght@${weight}&display=swap`,
|
|
65
|
+
rel: "stylesheet"
|
|
66
|
+
};
|
|
67
|
+
})
|
|
65
68
|
]
|
|
66
69
|
});
|
|
67
70
|
const headChunk = await renderSSRHead(head);
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|