nuxt-og-image 3.0.0-rc.1 → 3.0.0-rc.11
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 +0 -4
- package/dist/client/200.html +5 -5
- package/dist/client/404.html +5 -5
- package/dist/client/_nuxt/{IconCSS.bca1abaf.js → IconCSS.6838b383.js} +1 -1
- package/dist/client/_nuxt/builds/latest.json +1 -1
- package/dist/client/_nuxt/builds/meta/af0ef270-1d09-4960-81ba-0491787e30fd.json +1 -0
- package/dist/client/_nuxt/{entry.f2e056ce.js → entry.46886f0e.js} +47 -47
- package/dist/client/_nuxt/entry.47125dcd.css +1 -0
- package/dist/client/_nuxt/{error-404.1b7ec865.js → error-404.338d6c62.js} +1 -1
- package/dist/client/_nuxt/{error-500.1f097e6f.js → error-500.774c25a0.js} +1 -1
- package/dist/client/index.html +5 -5
- package/dist/module.d.mts +5 -0
- package/dist/module.d.ts +5 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +30 -10
- package/dist/runtime/cache.d.ts +2 -1
- package/dist/runtime/cache.mjs +33 -18
- package/dist/runtime/components/Templates/Community/NuxtSeo.vue +1 -1
- package/dist/runtime/composables/defineOgImage.mjs +8 -10
- package/dist/runtime/core/font/fetch.mjs +4 -1
- package/dist/runtime/core/html/devIframeTemplate.mjs +3 -2
- package/dist/runtime/core/html/fetchIsland.mjs +1 -1
- package/dist/runtime/core/options/extract.d.ts +1 -0
- package/dist/runtime/core/options/extract.mjs +3 -0
- package/dist/runtime/core/options/fetch.mjs +7 -1
- package/dist/runtime/core/renderers/chromium/index.mjs +2 -1
- package/dist/runtime/core/renderers/satori/index.mjs +6 -5
- package/dist/runtime/core/renderers/satori/vnodes.mjs +2 -0
- package/dist/runtime/core/utils/resolveRendererContext.mjs +14 -16
- package/dist/runtime/nitro/kit.d.ts +3 -0
- package/dist/runtime/nitro/kit.mjs +23 -0
- package/dist/runtime/nitro/plugins/prerender.d.ts +1 -1
- package/dist/runtime/nitro/plugins/prerender.mjs +5 -12
- package/dist/runtime/nitro/utils.mjs +2 -3
- package/dist/runtime/nuxt/utils.mjs +10 -3
- package/dist/runtime/server/routes/__og-image__/debug.json.d.ts +0 -4
- package/dist/runtime/server/routes/__og-image__/debug.json.mjs +0 -6
- package/dist/runtime/server/routes/__og-image__/font-[name]-[weight].[extension].mjs +31 -5
- package/dist/runtime/server/routes/__og-image__/image.mjs +8 -5
- package/dist/runtime/types.d.ts +5 -0
- package/dist/runtime/utils.pure.d.ts +2 -0
- package/dist/runtime/utils.pure.mjs +10 -1
- package/package.json +18 -17
- package/dist/client/_nuxt/builds/meta/c430c582-423d-48d2-8592-39b7bfd61658.json +0 -1
- package/dist/client/_nuxt/entry.a30f63d0.css +0 -1
|
@@ -7,10 +7,10 @@ import { useResvg, useSatori, useSharp } from "./instances.mjs";
|
|
|
7
7
|
import { theme } from "#nuxt-og-image/unocss-config.mjs";
|
|
8
8
|
export async function createSvg(event) {
|
|
9
9
|
const { options } = event;
|
|
10
|
-
const { fonts, satoriOptions } = useOgImageRuntimeConfig();
|
|
10
|
+
const { fonts, satoriOptions: _satoriOptions } = useOgImageRuntimeConfig();
|
|
11
11
|
const vnodes = await createVNodes(event);
|
|
12
12
|
await event._nitro.hooks.callHook("nuxt-og-image:satori:vnodes", vnodes, event);
|
|
13
|
-
const normalisedFonts = normaliseFontInput([...
|
|
13
|
+
const normalisedFonts = normaliseFontInput([...event.options.fonts || [], ...fonts]);
|
|
14
14
|
const localFontPromises = [];
|
|
15
15
|
const preloadedFonts = [];
|
|
16
16
|
for (const font of normalisedFonts) {
|
|
@@ -30,15 +30,16 @@ export async function createSvg(event) {
|
|
|
30
30
|
}
|
|
31
31
|
const awaitedFonts = await Promise.all(localFontPromises);
|
|
32
32
|
const satori = await useSatori();
|
|
33
|
-
|
|
33
|
+
const satoriOptions = defu(options.satori, _satoriOptions, {
|
|
34
34
|
fonts: [...preloadedFonts, ...awaitedFonts].map((_f) => {
|
|
35
|
-
return {
|
|
35
|
+
return { name: _f.name, data: _f.data, style: _f.style, weight: Number(_f.weight) };
|
|
36
36
|
}),
|
|
37
37
|
tailwindConfig: { theme },
|
|
38
38
|
embedFont: true,
|
|
39
39
|
width: options.width,
|
|
40
40
|
height: options.height
|
|
41
|
-
})
|
|
41
|
+
});
|
|
42
|
+
return satori(vnodes, satoriOptions);
|
|
42
43
|
}
|
|
43
44
|
async function createPng(event) {
|
|
44
45
|
const { resvgOptions } = useOgImageRuntimeConfig();
|
|
@@ -2,6 +2,7 @@ import { html as convertHtmlToSatori } from "satori-html";
|
|
|
2
2
|
import { fetchIsland } from "../../html/fetchIsland.mjs";
|
|
3
3
|
import { applyInlineCss } from "../../html/applyInlineCss.mjs";
|
|
4
4
|
import { applyEmojis } from "../../html/applyEmojis.mjs";
|
|
5
|
+
import { htmlDecodeQuotes } from "../../options/extract.mjs";
|
|
5
6
|
import { walkSatoriTree } from "./utils.mjs";
|
|
6
7
|
import unocss from "./plugins/unocss.mjs";
|
|
7
8
|
import emojis from "./plugins/emojis.mjs";
|
|
@@ -13,6 +14,7 @@ export async function createVNodes(ctx) {
|
|
|
13
14
|
let html = ctx.options.html;
|
|
14
15
|
if (!html) {
|
|
15
16
|
const island = await fetchIsland(ctx);
|
|
17
|
+
island.html = htmlDecodeQuotes(island.html);
|
|
16
18
|
await applyInlineCss(ctx, island);
|
|
17
19
|
await applyEmojis(ctx, island);
|
|
18
20
|
html = island.html;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { parseURL,
|
|
1
|
+
import { parseURL, withQuery, withoutTrailingSlash } from "ufo";
|
|
2
2
|
import { createError, getQuery } from "h3";
|
|
3
3
|
import { defu } from "defu";
|
|
4
|
-
import { createRouter as createRadixRouter, toRouteMatcher } from "radix3";
|
|
5
4
|
import { fetchPathHtmlAndExtractOptions } from "../options/fetch.mjs";
|
|
6
5
|
import { prerenderOptionsCache } from "../cache/prerender.mjs";
|
|
7
6
|
import { useChromiumRenderer, useSatoriRenderer } from "../renderers/satori/instances.mjs";
|
|
8
7
|
import { separateProps, useOgImageRuntimeConfig } from "../../utils.mjs";
|
|
9
8
|
import { resolvePathCacheKey } from "../../nitro/utils.mjs";
|
|
10
|
-
import {
|
|
9
|
+
import { createNitroRouteRuleMatcher } from "../../nitro/kit.mjs";
|
|
10
|
+
import { useNitroApp } from "#internal/nitro/app";
|
|
11
11
|
export async function resolveRendererContext(e) {
|
|
12
12
|
const runtimeConfig = useOgImageRuntimeConfig();
|
|
13
13
|
const path = parseURL(e.path).pathname;
|
|
@@ -15,21 +15,23 @@ export async function resolveRendererContext(e) {
|
|
|
15
15
|
if (!extension) {
|
|
16
16
|
return createError({
|
|
17
17
|
statusCode: 400,
|
|
18
|
-
statusMessage: `Missing OG Image type.`
|
|
18
|
+
statusMessage: `[Nuxt OG Image] Missing OG Image type.`
|
|
19
19
|
});
|
|
20
20
|
}
|
|
21
21
|
if (!["png", "jpeg", "jpg", "svg", "html", "json"].includes(extension)) {
|
|
22
22
|
return createError({
|
|
23
23
|
statusCode: 400,
|
|
24
|
-
statusMessage: `Unknown OG Image type ${extension}.`
|
|
24
|
+
statusMessage: `[Nuxt OG Image] Unknown OG Image type ${extension}.`
|
|
25
25
|
});
|
|
26
26
|
}
|
|
27
|
-
const basePath = withoutTrailingSlash(
|
|
28
|
-
path.replace(`/__og-image__/image`, "").replace(`/og.${extension}`, "")
|
|
29
|
-
);
|
|
30
27
|
let queryParams = { ...getQuery(e) };
|
|
31
28
|
queryParams.props = JSON.parse(queryParams.props || "{}");
|
|
32
29
|
queryParams = separateProps(queryParams);
|
|
30
|
+
let basePath = withoutTrailingSlash(
|
|
31
|
+
path.replace(`/__og-image__/image`, "").replace(`/og.${extension}`, "")
|
|
32
|
+
);
|
|
33
|
+
if (queryParams._query)
|
|
34
|
+
basePath = withQuery(basePath, JSON.parse(queryParams._query));
|
|
33
35
|
const isDebugJsonPayload = extension === "json" && runtimeConfig.debug;
|
|
34
36
|
const key = resolvePathCacheKey(e, basePath);
|
|
35
37
|
let options = queryParams.options;
|
|
@@ -44,12 +46,8 @@ export async function resolveRendererContext(e) {
|
|
|
44
46
|
}
|
|
45
47
|
}
|
|
46
48
|
delete queryParams.options;
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
);
|
|
50
|
-
const routeRules = defu({}, ..._routeRulesMatcher.matchAll(
|
|
51
|
-
withoutBase(basePath.split("?")[0], useRuntimeConfig().app.baseURL)
|
|
52
|
-
).reverse());
|
|
49
|
+
const routeRuleMatcher = createNitroRouteRuleMatcher();
|
|
50
|
+
const routeRules = routeRuleMatcher(basePath);
|
|
53
51
|
if (typeof routeRules.ogImage === "undefined" && !options) {
|
|
54
52
|
return createError({
|
|
55
53
|
statusCode: 400,
|
|
@@ -61,7 +59,7 @@ export async function resolveRendererContext(e) {
|
|
|
61
59
|
if (!options) {
|
|
62
60
|
return createError({
|
|
63
61
|
statusCode: 404,
|
|
64
|
-
statusMessage: "OG Image not found."
|
|
62
|
+
statusMessage: "[Nuxt OG Image] OG Image not found."
|
|
65
63
|
});
|
|
66
64
|
}
|
|
67
65
|
let renderer;
|
|
@@ -76,7 +74,7 @@ export async function resolveRendererContext(e) {
|
|
|
76
74
|
if (!renderer || renderer.__unenv__) {
|
|
77
75
|
throw createError({
|
|
78
76
|
statusCode: 400,
|
|
79
|
-
statusMessage: `Renderer ${options.renderer} is missing.`
|
|
77
|
+
statusMessage: `[Nuxt OG Image] Renderer ${options.renderer} is missing.`
|
|
80
78
|
});
|
|
81
79
|
}
|
|
82
80
|
const ctx = {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { createRouter as createRadixRouter, toRouteMatcher } from "radix3";
|
|
2
|
+
import { defu } from "defu";
|
|
3
|
+
import { withoutBase, withoutTrailingSlash } from "ufo";
|
|
4
|
+
import { useRuntimeConfig } from "#imports";
|
|
5
|
+
export function withoutQuery(path) {
|
|
6
|
+
return path.split("?")[0];
|
|
7
|
+
}
|
|
8
|
+
export function createNitroRouteRuleMatcher() {
|
|
9
|
+
const { nitro, app } = useRuntimeConfig();
|
|
10
|
+
const _routeRulesMatcher = toRouteMatcher(
|
|
11
|
+
createRadixRouter({
|
|
12
|
+
routes: Object.fromEntries(
|
|
13
|
+
Object.entries(nitro?.routeRules || {}).map(([path, rules]) => [withoutTrailingSlash(path), rules])
|
|
14
|
+
)
|
|
15
|
+
})
|
|
16
|
+
);
|
|
17
|
+
return (path) => {
|
|
18
|
+
return defu({}, ..._routeRulesMatcher.matchAll(
|
|
19
|
+
// radix3 does not support trailing slashes
|
|
20
|
+
withoutBase(withoutTrailingSlash(withoutQuery(path)), app.baseURL)
|
|
21
|
+
).reverse());
|
|
22
|
+
};
|
|
23
|
+
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: import("nitropack").NitroAppPlugin;
|
|
1
|
+
declare const _default: import("nitropack/dist/runtime/plugin").NitroAppPlugin;
|
|
2
2
|
export default _default;
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import { parseURL
|
|
1
|
+
import { parseURL } from "ufo";
|
|
2
2
|
import { defineNitroPlugin } from "nitropack/dist/runtime/plugin";
|
|
3
|
-
import { createRouter as createRadixRouter, toRouteMatcher } from "radix3";
|
|
4
|
-
import { defu } from "defu";
|
|
5
3
|
import { extractAndNormaliseOgImageOptions } from "../../core/options/extract.mjs";
|
|
6
4
|
import { prerenderOptionsCache } from "../../core/cache/prerender.mjs";
|
|
7
5
|
import { isInternalRoute } from "../../utils.pure.mjs";
|
|
8
6
|
import { resolvePathCacheKey } from "../utils.mjs";
|
|
9
|
-
import {
|
|
7
|
+
import { createNitroRouteRuleMatcher } from "../kit.mjs";
|
|
10
8
|
export default defineNitroPlugin(async (nitro) => {
|
|
11
9
|
if (!import.meta.prerender)
|
|
12
10
|
return;
|
|
@@ -15,14 +13,9 @@ export default defineNitroPlugin(async (nitro) => {
|
|
|
15
13
|
const path = parseURL(ctx.event.path).pathname;
|
|
16
14
|
if (isInternalRoute(path))
|
|
17
15
|
return;
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
);
|
|
22
|
-
const routeRules = defu({}, ..._routeRulesMatcher.matchAll(
|
|
23
|
-
withoutBase(path.split("?")[0], runtimeConfig.app.baseURL)
|
|
24
|
-
).reverse()).ogImage;
|
|
25
|
-
if (routeRules === false)
|
|
16
|
+
const routeRuleMatcher = createNitroRouteRuleMatcher();
|
|
17
|
+
const routeRules = routeRuleMatcher(path);
|
|
18
|
+
if (routeRules.ogImage === false)
|
|
26
19
|
return;
|
|
27
20
|
const options = extractAndNormaliseOgImageOptions([
|
|
28
21
|
head.join("\n"),
|
|
@@ -2,12 +2,11 @@ import { withoutLeadingSlash, withoutTrailingSlash } from "ufo";
|
|
|
2
2
|
import { hash } from "ohash";
|
|
3
3
|
import { normalizeKey } from "unstorage";
|
|
4
4
|
import { getQuery } from "h3";
|
|
5
|
-
import { useSiteConfig } from "#imports";
|
|
6
5
|
export function resolvePathCacheKey(e, path) {
|
|
7
|
-
const siteConfig =
|
|
6
|
+
const siteConfig = e.context.siteConfig.get();
|
|
8
7
|
const basePath = withoutTrailingSlash(withoutLeadingSlash(normalizeKey(path || e.path)));
|
|
9
8
|
return [
|
|
10
|
-
!basePath ? "index" : basePath,
|
|
9
|
+
!basePath || basePath === "/" ? "index" : basePath,
|
|
11
10
|
hash([
|
|
12
11
|
basePath,
|
|
13
12
|
siteConfig.url,
|
|
@@ -1,17 +1,24 @@
|
|
|
1
1
|
import { defu } from "defu";
|
|
2
|
-
import {
|
|
2
|
+
import { withQuery } from "ufo";
|
|
3
|
+
import { getExtension, separateProps } from "../utils.mjs";
|
|
3
4
|
import { unref, useServerHead } from "#imports";
|
|
4
5
|
import { componentNames } from "#build/nuxt-og-image/components.mjs";
|
|
5
6
|
export function createOgImageMeta(src, input, resolvedOptions, ssrContext) {
|
|
6
7
|
const _input = separateProps(defu(input, ssrContext._ogImagePayload));
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
let url = src || input.url || resolvedOptions.url;
|
|
9
|
+
if (!url)
|
|
10
|
+
return;
|
|
11
|
+
if (input._query && Object.keys(input._query).length && url)
|
|
12
|
+
url = withQuery(url, { _query: input._query });
|
|
13
|
+
let urlExtension = getExtension(url) || resolvedOptions.extension;
|
|
9
14
|
if (urlExtension === "jpg")
|
|
10
15
|
urlExtension = "jpeg";
|
|
11
16
|
const meta = [
|
|
12
17
|
{ property: "og:image", content: url },
|
|
13
18
|
{ property: "og:image:type", content: `image/${urlExtension}` },
|
|
14
19
|
{ name: "twitter:card", content: "summary_large_image" },
|
|
20
|
+
// we don't need this but avoids issue when using useSeoMeta({ twitterImage })
|
|
21
|
+
{ name: "twitter:image", content: url },
|
|
15
22
|
{ name: "twitter:image:src", content: url }
|
|
16
23
|
];
|
|
17
24
|
if (resolvedOptions.width) {
|
|
@@ -1,17 +1,11 @@
|
|
|
1
1
|
import { defineEventHandler, setHeader } from "h3";
|
|
2
2
|
import { useOgImageRuntimeConfig } from "../../../utils.mjs";
|
|
3
|
-
import { useSiteConfig } from "#imports";
|
|
4
3
|
import compatibility from "#nuxt-og-image/compatibility";
|
|
5
4
|
import { componentNames } from "#nuxt-og-image/component-names.mjs";
|
|
6
5
|
export default defineEventHandler(async (e) => {
|
|
7
6
|
setHeader(e, "Content-Type", "application/json");
|
|
8
7
|
const runtimeConfig = useOgImageRuntimeConfig();
|
|
9
|
-
const siteConfig = await useSiteConfig(e, { debug: true });
|
|
10
8
|
return {
|
|
11
|
-
siteConfigUrl: {
|
|
12
|
-
value: siteConfig.url,
|
|
13
|
-
source: siteConfig._context.url || "unknown"
|
|
14
|
-
},
|
|
15
9
|
componentNames,
|
|
16
10
|
runtimeConfig,
|
|
17
11
|
compatibility
|
|
@@ -1,10 +1,36 @@
|
|
|
1
|
-
import { createError, defineEventHandler, proxyRequest, sendRedirect } from "h3";
|
|
1
|
+
import { createError, defineEventHandler, getQuery, proxyRequest, sendRedirect, setHeader } from "h3";
|
|
2
2
|
import { parseURL } from "ufo";
|
|
3
|
+
import { getExtension, normaliseFontInput, useOgImageRuntimeConfig } from "../../../utils.mjs";
|
|
4
|
+
import { assets } from "#internal/nitro/virtual/server-assets";
|
|
3
5
|
export default defineEventHandler(async (e) => {
|
|
4
6
|
const path = parseURL(e.path).pathname;
|
|
5
|
-
const [
|
|
6
|
-
if (!
|
|
7
|
+
const [_name, _weight] = path.split("/font/")[1].split(".")[0].split("/");
|
|
8
|
+
if (!_name || !_weight)
|
|
7
9
|
return "Provide a font name and weight";
|
|
10
|
+
const name = _name[0].toUpperCase() + _name.slice(1);
|
|
11
|
+
const weight = Math.round(Number.parseInt(_weight) / 100) * 100;
|
|
12
|
+
const config = useOgImageRuntimeConfig();
|
|
13
|
+
const normalisedFonts = normaliseFontInput(config.fonts);
|
|
14
|
+
let font;
|
|
15
|
+
if (typeof getQuery(e).font === "string")
|
|
16
|
+
font = JSON.parse(getQuery(e).font);
|
|
17
|
+
if (!font) {
|
|
18
|
+
font = normalisedFonts.find((font2) => {
|
|
19
|
+
return font2.name.toLowerCase() === name.toLowerCase() && weight === Number(font2.weight);
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
if (!font) {
|
|
23
|
+
return createError({
|
|
24
|
+
statusCode: 404,
|
|
25
|
+
statusMessage: `[Nuxt OG Image] Font ${name}:${weight} not found`
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
if (import.meta.dev || import.meta.prerender) {
|
|
29
|
+
if (font.key && await assets.hasItem(font.key)) {
|
|
30
|
+
setHeader(e, "Content-Type", `font/${getExtension(font.path)}`);
|
|
31
|
+
return assets.getItemRaw(font.key);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
8
34
|
const css = await globalThis.$fetch(`https://fonts.googleapis.com/css2?family=${name}:wght@${weight}`, {
|
|
9
35
|
headers: {
|
|
10
36
|
// Make sure it returns TTF.
|
|
@@ -14,7 +40,7 @@ export default defineEventHandler(async (e) => {
|
|
|
14
40
|
if (!css) {
|
|
15
41
|
return createError({
|
|
16
42
|
statusCode: 500,
|
|
17
|
-
statusMessage: `Invalid Google Font ${name}:${weight}`
|
|
43
|
+
statusMessage: `[Nuxt OG Image] Invalid Google Font ${name}:${weight}`
|
|
18
44
|
});
|
|
19
45
|
}
|
|
20
46
|
const ttfResource = css.match(/src: url\((.+)\) format\('(opentype|truetype)'\)/);
|
|
@@ -25,6 +51,6 @@ export default defineEventHandler(async (e) => {
|
|
|
25
51
|
return sendRedirect(e, woff2Resource[1]);
|
|
26
52
|
return createError({
|
|
27
53
|
statusCode: 500,
|
|
28
|
-
statusMessage: `Malformed Google Font CSS ${css}`
|
|
54
|
+
statusMessage: `[Nuxt OG Image] Malformed Google Font CSS ${css}`
|
|
29
55
|
});
|
|
30
56
|
});
|
|
@@ -5,7 +5,6 @@ import { devIframeTemplate } from "../../../core/html/devIframeTemplate.mjs";
|
|
|
5
5
|
import { applyInlineCss } from "../../../core/html/applyInlineCss.mjs";
|
|
6
6
|
import { useOgImageBufferCache } from "../../../cache.mjs";
|
|
7
7
|
import { useOgImageRuntimeConfig } from "../../../utils.mjs";
|
|
8
|
-
import { useSiteConfig } from "#imports";
|
|
9
8
|
export default defineEventHandler(async (e) => {
|
|
10
9
|
const ctx = await resolveRendererContext(e);
|
|
11
10
|
if (ctx instanceof H3Error)
|
|
@@ -23,10 +22,12 @@ export default defineEventHandler(async (e) => {
|
|
|
23
22
|
compatibilityHints.push("Inlining CSS is only supported in Node based environments.");
|
|
24
23
|
setHeader(e, "Content-Type", "application/json");
|
|
25
24
|
return {
|
|
25
|
+
siteConfig: {
|
|
26
|
+
url: e.context.siteConfig.get().url
|
|
27
|
+
},
|
|
26
28
|
compatibilityHints,
|
|
27
29
|
cacheKey: ctx.key,
|
|
28
30
|
options: ctx.options,
|
|
29
|
-
siteConfig: useSiteConfig(e),
|
|
30
31
|
...options.renderer === "satori" ? await renderer.debug(ctx) : void 0
|
|
31
32
|
};
|
|
32
33
|
}
|
|
@@ -43,7 +44,7 @@ export default defineEventHandler(async (e) => {
|
|
|
43
44
|
if (ctx.renderer.name !== "satori") {
|
|
44
45
|
return createError({
|
|
45
46
|
statusCode: 400,
|
|
46
|
-
statusMessage: `Generating ${extension}'s with ${renderer.name} is not supported.`
|
|
47
|
+
statusMessage: `[Nuxt OG Image] Generating ${extension}'s with ${renderer.name} is not supported.`
|
|
47
48
|
});
|
|
48
49
|
}
|
|
49
50
|
setHeader(e, "Content-Type", `image/svg+xml`);
|
|
@@ -54,7 +55,7 @@ export default defineEventHandler(async (e) => {
|
|
|
54
55
|
if (!renderer.supportedFormats.includes(extension)) {
|
|
55
56
|
return createError({
|
|
56
57
|
statusCode: 400,
|
|
57
|
-
statusMessage: `Generating ${extension}'s with ${renderer.name} is not supported.`
|
|
58
|
+
statusMessage: `[Nuxt OG Image] Generating ${extension}'s with ${renderer.name} is not supported.`
|
|
58
59
|
});
|
|
59
60
|
}
|
|
60
61
|
setHeader(e, "Content-Type", `image/${extension === "jpg" ? "jpeg" : extension}`);
|
|
@@ -62,7 +63,7 @@ export default defineEventHandler(async (e) => {
|
|
|
62
63
|
default:
|
|
63
64
|
return createError({
|
|
64
65
|
statusCode: 400,
|
|
65
|
-
statusMessage: `Invalid request for og.${extension}.`
|
|
66
|
+
statusMessage: `[Nuxt OG Image] Invalid request for og.${extension}.`
|
|
66
67
|
});
|
|
67
68
|
}
|
|
68
69
|
const cacheApi = await useOgImageBufferCache(ctx, {
|
|
@@ -71,6 +72,8 @@ export default defineEventHandler(async (e) => {
|
|
|
71
72
|
});
|
|
72
73
|
if (typeof cacheApi === "undefined")
|
|
73
74
|
return;
|
|
75
|
+
if (cacheApi instanceof H3Error)
|
|
76
|
+
return cacheApi;
|
|
74
77
|
let image = cacheApi.cachedItem;
|
|
75
78
|
if (!image) {
|
|
76
79
|
image = await renderer.createImage(ctx);
|
package/dist/runtime/types.d.ts
CHANGED
|
@@ -106,9 +106,14 @@ export interface OgImageOptions<T extends keyof OgImageComponents = 'NuxtSeo'> {
|
|
|
106
106
|
sharp?: SharpOptions;
|
|
107
107
|
fonts?: InputFontConfig[];
|
|
108
108
|
cacheMaxAgeSeconds?: number;
|
|
109
|
+
/**
|
|
110
|
+
* @internal
|
|
111
|
+
*/
|
|
112
|
+
_query?: Record<string, any>;
|
|
109
113
|
}
|
|
110
114
|
export interface FontConfig {
|
|
111
115
|
name: string;
|
|
116
|
+
style?: string;
|
|
112
117
|
weight?: string | number;
|
|
113
118
|
path?: string;
|
|
114
119
|
key?: string;
|
|
@@ -4,3 +4,5 @@ export declare function separateProps(options: OgImageOptions | undefined, ignor
|
|
|
4
4
|
props: Record<string, any>;
|
|
5
5
|
};
|
|
6
6
|
export declare function normaliseFontInput(fonts: InputFontConfig[]): ResolvedFontConfig[];
|
|
7
|
+
export declare function withoutQuery(path: string): string;
|
|
8
|
+
export declare function getExtension(path: string): string;
|
|
@@ -17,6 +17,7 @@ function filterIsOgImageOption(key) {
|
|
|
17
17
|
"component",
|
|
18
18
|
"renderer",
|
|
19
19
|
"emojis",
|
|
20
|
+
"_query",
|
|
20
21
|
"satori",
|
|
21
22
|
"resvg",
|
|
22
23
|
"sharp",
|
|
@@ -48,7 +49,7 @@ export function normaliseFontInput(fonts) {
|
|
|
48
49
|
return {
|
|
49
50
|
cacheKey: f,
|
|
50
51
|
name,
|
|
51
|
-
weight: weight ||
|
|
52
|
+
weight: weight || 400,
|
|
52
53
|
style: "normal",
|
|
53
54
|
path: void 0
|
|
54
55
|
};
|
|
@@ -61,3 +62,11 @@ export function normaliseFontInput(fonts) {
|
|
|
61
62
|
};
|
|
62
63
|
});
|
|
63
64
|
}
|
|
65
|
+
export function withoutQuery(path) {
|
|
66
|
+
return path.split("?")[0];
|
|
67
|
+
}
|
|
68
|
+
export function getExtension(path) {
|
|
69
|
+
path = withoutQuery(path);
|
|
70
|
+
const lastSegment = path.split("/").pop() || path;
|
|
71
|
+
return lastSegment.split(".").pop() || lastSegment;
|
|
72
|
+
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuxt-og-image",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "3.0.0-rc.
|
|
5
|
-
"packageManager": "pnpm@8.12.
|
|
4
|
+
"version": "3.0.0-rc.11",
|
|
5
|
+
"packageManager": "pnpm@8.12.1",
|
|
6
6
|
"description": "Enlightened OG Image generation for Nuxt.",
|
|
7
7
|
"author": {
|
|
8
8
|
"website": "https://harlanzw.com",
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
"virtual.d.ts"
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@iconify-json/noto": "^1.1.
|
|
37
|
-
"@nuxt/devtools-kit": "^1.0.
|
|
36
|
+
"@iconify-json/noto": "^1.1.18",
|
|
37
|
+
"@nuxt/devtools-kit": "^1.0.6",
|
|
38
38
|
"@nuxt/kit": "^3.8.2",
|
|
39
39
|
"@resvg/resvg-js": "^2.6.0",
|
|
40
40
|
"@resvg/resvg-wasm": "^2.6.0",
|
|
@@ -42,13 +42,13 @@
|
|
|
42
42
|
"@unocss/preset-wind": "^0.58.0",
|
|
43
43
|
"@vueuse/core": "^10.7.0",
|
|
44
44
|
"chrome-launcher": "^1.1.0",
|
|
45
|
-
"css-inline": "^0.11.
|
|
45
|
+
"css-inline": "^0.11.2",
|
|
46
46
|
"defu": "^6.1.3",
|
|
47
47
|
"execa": "^8.0.1",
|
|
48
48
|
"floating-vue": "2.0.0-beta.24",
|
|
49
49
|
"image-size": "^1.0.2",
|
|
50
|
-
"nuxt-site-config": "^1.
|
|
51
|
-
"nuxt-site-config-kit": "^1.
|
|
50
|
+
"nuxt-site-config": "^2.1.0",
|
|
51
|
+
"nuxt-site-config-kit": "^2.1.0",
|
|
52
52
|
"nypm": "^0.3.3",
|
|
53
53
|
"ofetch": "^1.3.3",
|
|
54
54
|
"ohash": "^1.1.3",
|
|
@@ -64,25 +64,26 @@
|
|
|
64
64
|
"yoga-wasm-web": "^0.3.3"
|
|
65
65
|
},
|
|
66
66
|
"devDependencies": {
|
|
67
|
-
"@antfu/eslint-config": "2.4.
|
|
67
|
+
"@antfu/eslint-config": "2.4.6",
|
|
68
|
+
"@img/sharp-linux-x64": "0.33.1",
|
|
68
69
|
"@nuxt/content": "^2.9.0",
|
|
69
|
-
"@nuxt/devtools": "1.0.
|
|
70
|
+
"@nuxt/devtools": "1.0.6",
|
|
70
71
|
"@nuxt/module-builder": "^0.5.4",
|
|
71
72
|
"@nuxt/test-utils": "3.8.1",
|
|
72
|
-
"@nuxt/ui": "^2.11.
|
|
73
|
+
"@nuxt/ui": "^2.11.1",
|
|
73
74
|
"@nuxtjs/eslint-config-typescript": "^12.1.0",
|
|
74
|
-
"@nuxtjs/i18n": "8.0.0-rc.
|
|
75
|
+
"@nuxtjs/i18n": "8.0.0-rc.11",
|
|
75
76
|
"@nuxtjs/tailwindcss": "^6.10.1",
|
|
76
77
|
"@unocss/nuxt": "^0.58.0",
|
|
77
|
-
"bumpp": "^9.2.
|
|
78
|
-
"eslint": "8.
|
|
79
|
-
"jest-image-snapshot": "^6.
|
|
78
|
+
"bumpp": "^9.2.1",
|
|
79
|
+
"eslint": "8.56.0",
|
|
80
|
+
"jest-image-snapshot": "^6.4.0",
|
|
80
81
|
"nuxt": "^3.8.2",
|
|
81
82
|
"nuxt-icon": "0.6.7",
|
|
82
83
|
"playwright": "^1.40.1",
|
|
83
84
|
"sass": "^1.69.5",
|
|
84
|
-
"sharp": "^0.33.
|
|
85
|
-
"vitest": "^1.0.
|
|
85
|
+
"sharp": "^0.33.1",
|
|
86
|
+
"vitest": "^1.0.4"
|
|
86
87
|
},
|
|
87
88
|
"build": {
|
|
88
89
|
"externals": [
|
|
@@ -102,7 +103,7 @@
|
|
|
102
103
|
"dev": "nuxi dev .playground",
|
|
103
104
|
"dev:build": "nuxi build .playground",
|
|
104
105
|
"dev:prepare": "nuxt-module-build build --stub && nuxi prepare .playground",
|
|
105
|
-
"release": "bumpp
|
|
106
|
+
"release": "bumpp && pnpm -r publish --no-git-checks",
|
|
106
107
|
"test": "vitest"
|
|
107
108
|
}
|
|
108
109
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"id":"c430c582-423d-48d2-8592-39b7bfd61658","timestamp":1702109741421,"matcher":{"static":{},"wildcard":{},"dynamic":{}},"prerendered":[]}
|