nuxt-og-image 1.0.0-beta.1 → 1.0.0-beta.10
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 +1 -0
- package/dist/client/200.html +2 -2
- package/dist/client/404.html +2 -2
- package/dist/client/_nuxt/{Icon.4a9650c6.js → Icon.a3c98859.js} +1 -1
- package/dist/client/_nuxt/entry.2a315a2c.js +4 -0
- package/dist/client/_nuxt/{entry.0827acf4.css → entry.dc5450bf.css} +1 -1
- package/dist/client/_nuxt/{error-404.556d8899.js → error-404.0c49154a.js} +1 -1
- package/dist/client/_nuxt/{error-500.70731718.js → error-500.f3eec0bb.js} +1 -1
- package/dist/client/_nuxt/{error-component.418ebd67.js → error-component.7c753c74.js} +2 -2
- package/dist/client/index.html +2 -2
- package/dist/module.d.ts +8 -8
- package/dist/module.json +1 -1
- package/dist/module.mjs +45 -29
- package/dist/runtime/components/{OgImageTemplate.island.vue → OgImageBasic.island.vue} +2 -2
- package/dist/runtime/components/OgImageDynamic.d.ts +2 -2
- package/dist/runtime/components/OgImageScreenshot.d.ts +2 -2
- package/dist/runtime/components/OgImageStatic.d.ts +2 -2
- package/dist/runtime/composables/defineOgImage.d.ts +5 -5
- package/dist/runtime/composables/defineOgImage.mjs +11 -6
- package/dist/runtime/nitro/providers/browser.mjs +7 -8
- package/dist/runtime/nitro/providers/{satori.d.ts → satori/index.d.ts} +1 -1
- package/dist/runtime/nitro/providers/satori/index.mjs +48 -0
- package/dist/runtime/nitro/providers/satori/plugins/emojis.d.ts +2 -0
- package/dist/runtime/nitro/providers/satori/plugins/emojis.mjs +13 -0
- package/dist/runtime/nitro/providers/satori/plugins/flex.d.ts +2 -0
- package/dist/runtime/nitro/providers/satori/plugins/flex.mjs +11 -0
- package/dist/runtime/nitro/providers/satori/plugins/imageSrc.d.ts +2 -0
- package/dist/runtime/nitro/providers/satori/plugins/imageSrc.mjs +24 -0
- package/dist/runtime/nitro/providers/satori/plugins/twClasses.d.ts +2 -0
- package/dist/runtime/nitro/providers/satori/plugins/twClasses.mjs +9 -0
- package/dist/runtime/nitro/providers/satori/utils.d.ts +10 -0
- package/dist/runtime/nitro/providers/satori/utils.mjs +33 -0
- package/dist/runtime/nitro/routes/__og_image__/html.mjs +42 -12
- package/dist/runtime/nitro/routes/__og_image__/index.mjs +4 -4
- package/dist/runtime/nitro/routes/__og_image__/og.png.mjs +8 -12
- package/dist/runtime/nitro/routes/__og_image__/options.d.ts +5 -0
- package/dist/runtime/nitro/routes/__og_image__/{payload.mjs → options.mjs} +21 -28
- package/dist/runtime/nitro/routes/__og_image__/svg.mjs +5 -5
- package/dist/runtime/nitro/routes/__og_image__/vnode.d.ts +2 -0
- package/dist/runtime/nitro/routes/__og_image__/vnode.mjs +16 -0
- package/dist/runtime/nitro/utils.d.ts +3 -3
- package/dist/runtime/nitro/utils.mjs +4 -4
- package/package.json +3 -2
- package/dist/client/_nuxt/entry.ce848650.js +0 -4
- package/dist/runtime/nitro/providers/satori.mjs +0 -48
- package/dist/runtime/nitro/routes/__og_image__/payload.d.ts +0 -5
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { fileURLToPath } from "node:url";
|
|
2
|
+
import { promises as fsp } from "node:fs";
|
|
3
|
+
import { dirname, resolve } from "pathe";
|
|
4
|
+
import { withBase } from "ufo";
|
|
5
|
+
import { getAsset } from "#internal/nitro/virtual/public-assets";
|
|
6
|
+
export async function parseFont(url, font) {
|
|
7
|
+
if (typeof font.publicPath === "string") {
|
|
8
|
+
const file = getAsset(font.publicPath);
|
|
9
|
+
if (file) {
|
|
10
|
+
const serverDir = dirname(fileURLToPath(import.meta.url));
|
|
11
|
+
font.data = await fsp.readFile(resolve(serverDir, file.path));
|
|
12
|
+
}
|
|
13
|
+
if (!font.data)
|
|
14
|
+
font.data = await (await $fetch(withBase(font.publicPath, `${url.protocol}//${url.host}`))).arrayBuffer();
|
|
15
|
+
}
|
|
16
|
+
return font;
|
|
17
|
+
}
|
|
18
|
+
export async function walkSatoriTree(url, node, plugins) {
|
|
19
|
+
if (!node.props?.children)
|
|
20
|
+
return;
|
|
21
|
+
for (const child of node.props.children || []) {
|
|
22
|
+
if (child) {
|
|
23
|
+
for (const plugin of plugins) {
|
|
24
|
+
if (plugin.filter(child))
|
|
25
|
+
await plugin.transform(child, url);
|
|
26
|
+
}
|
|
27
|
+
await walkSatoriTree(url, child, plugins);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export function defineSatoriTransformer(transformer) {
|
|
32
|
+
return transformer;
|
|
33
|
+
}
|
|
@@ -1,26 +1,56 @@
|
|
|
1
|
-
import { parseURL, withoutTrailingSlash } from "ufo";
|
|
1
|
+
import { parseURL, withBase, withoutTrailingSlash } from "ufo";
|
|
2
2
|
import { renderSSRHead } from "@unhead/ssr";
|
|
3
3
|
import { createHeadCore } from "@unhead/vue";
|
|
4
|
-
import { defineEventHandler, sendRedirect } from "h3";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
4
|
+
import { defineEventHandler, getQuery, sendRedirect } from "h3";
|
|
5
|
+
import { fetchOptions, renderIsland, useHostname } from "../../utils.mjs";
|
|
6
|
+
import { defaults } 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"))
|
|
10
10
|
return;
|
|
11
11
|
const basePath = withoutTrailingSlash(path.replace("__og_image__/html", ""));
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const island = await renderIsland(component, payload);
|
|
12
|
+
const scale = getQuery(e).scale;
|
|
13
|
+
const options = await fetchOptions(basePath);
|
|
14
|
+
if (options.provider === "browser")
|
|
15
|
+
return sendRedirect(e, withBase(basePath, useHostname(e)));
|
|
16
|
+
const island = await renderIsland(options);
|
|
18
17
|
const head = createHeadCore();
|
|
19
18
|
head.push(island.head);
|
|
20
19
|
head.push({
|
|
21
20
|
style: [
|
|
22
21
|
{
|
|
23
|
-
innerHTML: "body { font-family: 'Inter', sans-serif;
|
|
22
|
+
innerHTML: "body { font-family: 'Inter', sans-serif; }"
|
|
23
|
+
},
|
|
24
|
+
scale ? {
|
|
25
|
+
innerHTML: `body {
|
|
26
|
+
transform: scale(${scale});
|
|
27
|
+
transform-origin: top left;
|
|
28
|
+
max-height: 100vh;
|
|
29
|
+
}
|
|
30
|
+
img.emoji {
|
|
31
|
+
height: 1em;
|
|
32
|
+
width: 1em;
|
|
33
|
+
margin: 0 .05em 0 .1em;
|
|
34
|
+
vertical-align: -0.1em;
|
|
35
|
+
}
|
|
36
|
+
`
|
|
37
|
+
} : {}
|
|
38
|
+
],
|
|
39
|
+
meta: [
|
|
40
|
+
{
|
|
41
|
+
charset: "utf-8"
|
|
42
|
+
}
|
|
43
|
+
],
|
|
44
|
+
script: [
|
|
45
|
+
{
|
|
46
|
+
src: "https://cdn.tailwindcss.com"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
innerHTML: `tailwind.config = {
|
|
50
|
+
corePlugins: {
|
|
51
|
+
preflight: false,
|
|
52
|
+
}
|
|
53
|
+
}`
|
|
24
54
|
}
|
|
25
55
|
],
|
|
26
56
|
link: [
|
|
@@ -38,6 +68,6 @@ export default defineEventHandler(async (e) => {
|
|
|
38
68
|
return `<!DOCTYPE html>
|
|
39
69
|
<html ${headChunk.htmlAttrs}>
|
|
40
70
|
<head>${headChunk.headTags}</head>
|
|
41
|
-
<body ${headChunk.bodyAttrs}>${headChunk.bodyTagsOpen}<div style="width: ${width}px; height: ${height}px; display: flex; margin: 0 auto;">${island.html}</div>${headChunk.bodyTags}</body>
|
|
71
|
+
<body ${headChunk.bodyAttrs}>${headChunk.bodyTagsOpen}<div style="width: ${defaults.width}px; height: ${defaults.height}px; display: flex; margin: 0 auto;">${island.html}</div>${headChunk.bodyTags}</body>
|
|
42
72
|
</html>`;
|
|
43
73
|
});
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { defineEventHandler } from "h3";
|
|
2
2
|
import { parseURL, withoutTrailingSlash } from "ufo";
|
|
3
|
-
import {
|
|
3
|
+
import { fetchOptions, useHostname } from "../../utils.mjs";
|
|
4
4
|
export default defineEventHandler(async (e) => {
|
|
5
5
|
const path = parseURL(e.path).pathname;
|
|
6
6
|
if (!path.endsWith("/__og_image__"))
|
|
7
7
|
return;
|
|
8
8
|
const basePath = withoutTrailingSlash(path.replace("__og_image__", ""));
|
|
9
|
-
const
|
|
10
|
-
if (!
|
|
9
|
+
const options = await fetchOptions(basePath);
|
|
10
|
+
if (!options)
|
|
11
11
|
return `The route ${basePath} has not been set up for og:image generation.`;
|
|
12
12
|
return `
|
|
13
13
|
<style>
|
|
@@ -21,6 +21,6 @@ export default defineEventHandler(async (e) => {
|
|
|
21
21
|
height: 100%;
|
|
22
22
|
}
|
|
23
23
|
</style>
|
|
24
|
-
<title>
|
|
24
|
+
<title>OG Image Playground</title>
|
|
25
25
|
<iframe src="${useHostname(e)}/__nuxt_og_image__/client/?&path=${withoutTrailingSlash(path.replace("__og_image__", ""))}"></iframe>`;
|
|
26
26
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineEventHandler, setHeader } from "h3";
|
|
2
|
-
import { parseURL, withBase, withoutTrailingSlash } from "ufo";
|
|
3
|
-
import {
|
|
2
|
+
import { joinURL, parseURL, withBase, withoutTrailingSlash } from "ufo";
|
|
3
|
+
import { fetchOptions, useHostname } from "../../utils.mjs";
|
|
4
4
|
import { useProvider } from "#nuxt-og-image/provider";
|
|
5
5
|
export default defineEventHandler(async (e) => {
|
|
6
6
|
const path = parseURL(e.path).pathname;
|
|
@@ -9,15 +9,11 @@ export default defineEventHandler(async (e) => {
|
|
|
9
9
|
const basePath = withoutTrailingSlash(
|
|
10
10
|
path.replace("__og_image__/og.png", "")
|
|
11
11
|
);
|
|
12
|
-
const
|
|
12
|
+
const options = await fetchOptions(basePath);
|
|
13
13
|
setHeader(e, "Content-Type", "image/png");
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
setHeader(e, "Expires", "0");
|
|
20
|
-
}
|
|
21
|
-
const provider = await useProvider(providerName);
|
|
22
|
-
return provider.createPng(withBase(`${basePath}/__og_image__/html`, useHostname(e)));
|
|
14
|
+
setHeader(e, "Cache-Control", "no-cache, no-store, must-revalidate");
|
|
15
|
+
setHeader(e, "Pragma", "no-cache");
|
|
16
|
+
setHeader(e, "Expires", "0");
|
|
17
|
+
const provider = await useProvider(options.provider);
|
|
18
|
+
return provider.createPng(withBase(joinURL(basePath, "/__og_image__/html"), useHostname(e)), options);
|
|
23
19
|
});
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { OgImageOptions } from '../../../../types';
|
|
2
|
+
export declare function extractOgImageOptions(html: string): any;
|
|
3
|
+
export declare const inferOgImageOptions: (html: string) => OgImageOptions;
|
|
4
|
+
declare const _default: import("h3").EventHandler<false | OgImageOptions | undefined>;
|
|
5
|
+
export default _default;
|
|
@@ -1,31 +1,32 @@
|
|
|
1
1
|
import { parseURL, withoutTrailingSlash } from "ufo";
|
|
2
2
|
import { defineEventHandler, getQuery } from "h3";
|
|
3
|
-
import { PayloadScriptId } from "#nuxt-og-image/constants";
|
|
4
3
|
import { getRouteRules } from "#internal/nitro";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
};
|
|
12
|
-
export const inferOgPayload = (html) => {
|
|
13
|
-
const payload = {};
|
|
4
|
+
import { defaults } from "#nuxt-og-image/config";
|
|
5
|
+
export function extractOgImageOptions(html) {
|
|
6
|
+
const options = html.match(/<script id="nuxt-og-image-options" type="application\/json">(.+?)<\/script>/)?.[1];
|
|
7
|
+
return options ? JSON.parse(options) : false;
|
|
8
|
+
}
|
|
9
|
+
export const inferOgImageOptions = (html) => {
|
|
10
|
+
const options = {};
|
|
14
11
|
const title = html.match(/<meta property="og:title" content="(.*?)">/)?.[1];
|
|
15
12
|
if (title)
|
|
16
|
-
|
|
13
|
+
options.title = title;
|
|
14
|
+
else
|
|
15
|
+
options.title = html.match(/<title>(.*?)<\/title>/)?.[1];
|
|
17
16
|
const description = html.match(/<meta property="og:description" content="(.*?)">/)?.[1];
|
|
18
17
|
if (description)
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
options.description = description;
|
|
19
|
+
else
|
|
20
|
+
options.description = html.match(/<meta name="description" content="(.*?)">/)?.[1];
|
|
21
|
+
return options;
|
|
21
22
|
};
|
|
22
23
|
export default defineEventHandler(async (e) => {
|
|
23
24
|
const path = parseURL(e.path).pathname;
|
|
24
|
-
if (!path.endsWith("__og_image__/
|
|
25
|
+
if (!path.endsWith("__og_image__/options"))
|
|
25
26
|
return;
|
|
26
|
-
const basePath = withoutTrailingSlash(path.replace("__og_image__/
|
|
27
|
+
const basePath = withoutTrailingSlash(path.replace("__og_image__/options", ""));
|
|
27
28
|
const html = await $fetch(basePath);
|
|
28
|
-
const extractedPayload =
|
|
29
|
+
const extractedPayload = extractOgImageOptions(html);
|
|
29
30
|
if (!extractedPayload)
|
|
30
31
|
return false;
|
|
31
32
|
e.node.req.url = basePath;
|
|
@@ -34,20 +35,12 @@ export default defineEventHandler(async (e) => {
|
|
|
34
35
|
e.node.req.url = e.path;
|
|
35
36
|
if (routeRules === false)
|
|
36
37
|
return false;
|
|
37
|
-
|
|
38
|
+
return {
|
|
38
39
|
path: basePath,
|
|
39
|
-
...
|
|
40
|
-
...
|
|
40
|
+
...defaults,
|
|
41
|
+
...inferOgImageOptions(html),
|
|
41
42
|
...routeRules || {},
|
|
43
|
+
...extractedPayload,
|
|
42
44
|
...getQuery(e)
|
|
43
45
|
};
|
|
44
|
-
if (payload.provider === "satori") {
|
|
45
|
-
payload = {
|
|
46
|
-
title: "Hello World",
|
|
47
|
-
description: "Example description",
|
|
48
|
-
image: "https://example.com/image.png",
|
|
49
|
-
...payload
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
return payload;
|
|
53
46
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineEventHandler, setHeader } from "h3";
|
|
2
|
-
import { parseURL, withBase, withoutTrailingSlash } from "ufo";
|
|
3
|
-
import {
|
|
2
|
+
import { joinURL, parseURL, withBase, withoutTrailingSlash } from "ufo";
|
|
3
|
+
import { fetchOptions, useHostname } from "../../utils.mjs";
|
|
4
4
|
import { useProvider } from "#nuxt-og-image/provider";
|
|
5
5
|
export default defineEventHandler(async (e) => {
|
|
6
6
|
const path = parseURL(e.path).pathname;
|
|
@@ -9,8 +9,8 @@ export default defineEventHandler(async (e) => {
|
|
|
9
9
|
const basePath = withoutTrailingSlash(
|
|
10
10
|
path.replace("__og_image__/svg", "")
|
|
11
11
|
);
|
|
12
|
-
const
|
|
12
|
+
const options = await fetchOptions(basePath);
|
|
13
13
|
setHeader(e, "Content-Type", "image/svg+xml");
|
|
14
|
-
const provider = await useProvider(
|
|
15
|
-
return provider.createSvg(withBase(
|
|
14
|
+
const provider = await useProvider(options.provider);
|
|
15
|
+
return provider.createSvg(withBase(joinURL(basePath, "/__og_image__/html"), useHostname(e)), options);
|
|
16
16
|
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { defineEventHandler, setHeader } from "h3";
|
|
2
|
+
import { joinURL, parseURL, withBase, withoutTrailingSlash } from "ufo";
|
|
3
|
+
import { fetchOptions, useHostname } from "../../utils.mjs";
|
|
4
|
+
import { useProvider } from "#nuxt-og-image/provider";
|
|
5
|
+
export default defineEventHandler(async (e) => {
|
|
6
|
+
const path = parseURL(e.path).pathname;
|
|
7
|
+
if (!path.endsWith("__og_image__/vnode"))
|
|
8
|
+
return;
|
|
9
|
+
const basePath = withoutTrailingSlash(
|
|
10
|
+
path.replace("__og_image__/vnode", "")
|
|
11
|
+
);
|
|
12
|
+
const options = await fetchOptions(basePath);
|
|
13
|
+
setHeader(e, "Content-Type", "application/json");
|
|
14
|
+
const provider = await useProvider(options.provider);
|
|
15
|
+
return provider.createVNode(withBase(joinURL(basePath, "/__og_image__/html"), useHostname(e)), options);
|
|
16
|
+
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { H3Event } from 'h3';
|
|
2
|
-
import type {
|
|
3
|
-
export declare function
|
|
4
|
-
export declare function renderIsland(
|
|
2
|
+
import type { OgImageOptions } from '../../types';
|
|
3
|
+
export declare function fetchOptions(path: string): Promise<OgImageOptions>;
|
|
4
|
+
export declare function renderIsland(payload: OgImageOptions): Promise<{
|
|
5
5
|
html: string;
|
|
6
6
|
head: any;
|
|
7
7
|
}>;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { joinURL, withQuery } from "ufo";
|
|
2
2
|
import { getRequestHeader } from "h3";
|
|
3
|
-
export function
|
|
4
|
-
return $fetch(joinURL(path, "__og_image__/
|
|
3
|
+
export function fetchOptions(path) {
|
|
4
|
+
return $fetch(joinURL(path, "__og_image__/options"));
|
|
5
5
|
}
|
|
6
|
-
export function renderIsland(
|
|
7
|
-
return $fetch(withQuery(`/__nuxt_island/${
|
|
6
|
+
export function renderIsland(payload) {
|
|
7
|
+
return $fetch(withQuery(`/__nuxt_island/${payload.component}`, {
|
|
8
8
|
props: JSON.stringify(payload)
|
|
9
9
|
}));
|
|
10
10
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuxt-og-image",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.0.0-beta.
|
|
4
|
+
"version": "1.0.0-beta.10",
|
|
5
5
|
"packageManager": "pnpm@7.8.0",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"funding": "https://github.com/sponsors/harlan-zw",
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
"satori-html": "^0.3.2",
|
|
45
45
|
"sirv": "^2.0.2",
|
|
46
46
|
"tinyws": "^0.1.0",
|
|
47
|
+
"twemoji": "^14.0.2",
|
|
47
48
|
"ufo": "^1.0.1"
|
|
48
49
|
},
|
|
49
50
|
"devDependencies": {
|
|
@@ -63,7 +64,7 @@
|
|
|
63
64
|
"build": "pnpm dev:prepare && pnpm build:module && pnpm build:client",
|
|
64
65
|
"build:client": "nuxi generate client",
|
|
65
66
|
"build:module": "nuxt-build-module",
|
|
66
|
-
"lint": "eslint \"**/*.{ts,vue,json,yml}\"",
|
|
67
|
+
"lint": "eslint \"**/*.{ts,vue,json,yml}\" --fix",
|
|
67
68
|
"dev": "nuxi dev .playground",
|
|
68
69
|
"dev:build": "nuxi build .playground",
|
|
69
70
|
"dev:prepare": "nuxt-module-build --stub && nuxi prepare .playground",
|