nuxt-og-image 5.1.7 → 5.1.9

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.
Files changed (83) hide show
  1. package/dist/client/200.html +1 -15
  2. package/dist/client/404.html +1 -15
  3. package/dist/client/_nuxt/C0O1sPH1.js +4017 -0
  4. package/dist/client/_nuxt/C83k_r4_.js +1 -0
  5. package/dist/client/_nuxt/DAn4LZxu.js +1 -0
  6. package/dist/client/_nuxt/builds/latest.json +1 -1
  7. package/dist/client/_nuxt/builds/meta/9c728642-f464-4f02-9cbc-65fa9d60f818.json +1 -0
  8. package/dist/client/_nuxt/entry.Hpb5KO2G.css +1 -0
  9. package/dist/client/_nuxt/error-404.D1qMyH7R.css +1 -0
  10. package/dist/client/_nuxt/error-500.C-aGJHmP.css +1 -0
  11. package/dist/client/index.html +1 -15
  12. package/dist/content.cjs +7 -5
  13. package/dist/content.d.cts +18 -2
  14. package/dist/content.d.mts +18 -2
  15. package/dist/content.d.ts +18 -2
  16. package/dist/content.mjs +7 -6
  17. package/dist/module.cjs +35 -43
  18. package/dist/module.json +2 -3
  19. package/dist/module.mjs +37 -45
  20. package/dist/runtime/app/components/OgImage/OgImage.js +1 -1
  21. package/dist/runtime/app/components/OgImage/OgImageScreenshot.js +1 -1
  22. package/dist/runtime/app/components/Templates/Community/BrandedLogo.vue.d.ts +1 -4
  23. package/dist/runtime/app/components/Templates/Community/Frame.vue.d.ts +1 -3
  24. package/dist/runtime/app/components/Templates/Community/Nuxt.vue.d.ts +1 -5
  25. package/dist/runtime/app/components/Templates/Community/NuxtSeo.vue +2 -2
  26. package/dist/runtime/app/components/Templates/Community/NuxtSeo.vue.d.ts +1 -4
  27. package/dist/runtime/app/components/Templates/Community/Pergel.vue.d.ts +1 -5
  28. package/dist/runtime/app/components/Templates/Community/SimpleBlog.vue +2 -1
  29. package/dist/runtime/app/components/Templates/Community/SimpleBlog.vue.d.ts +1 -3
  30. package/dist/runtime/app/components/Templates/Community/UnJs.vue +1 -1
  31. package/dist/runtime/app/components/Templates/Community/UnJs.vue.d.ts +1 -8
  32. package/dist/runtime/app/components/Templates/Community/Wave.vue.d.ts +1 -3
  33. package/dist/runtime/app/components/Templates/Community/WithEmoji.vue.d.ts +1 -4
  34. package/dist/runtime/app/composables/defineOgImage.js +11 -23
  35. package/dist/runtime/app/composables/defineOgImageScreenshot.js +2 -1
  36. package/dist/runtime/app/plugins/__zero-runtime/og-image-canonical-urls.server.js +1 -1
  37. package/dist/runtime/app/plugins/__zero-runtime/route-rule-og-image.server.js +1 -1
  38. package/dist/runtime/app/plugins/og-image-canonical-urls.server.js +4 -2
  39. package/dist/runtime/app/plugins/route-rule-og-image.server.js +4 -2
  40. package/dist/runtime/app/utils/plugins.d.ts +3 -3
  41. package/dist/runtime/app/utils/plugins.js +15 -12
  42. package/dist/runtime/app/utils.d.ts +3 -1
  43. package/dist/runtime/app/utils.js +23 -5
  44. package/dist/runtime/server/og-image/bindings/chromium/on-demand.js +8 -3
  45. package/dist/runtime/server/og-image/chromium/screenshot.js +5 -4
  46. package/dist/runtime/server/og-image/context.js +14 -9
  47. package/dist/runtime/server/og-image/satori/font.js +4 -3
  48. package/dist/runtime/server/og-image/satori/plugins/flex.js +1 -1
  49. package/dist/runtime/server/og-image/satori/plugins/imageSrc.js +11 -6
  50. package/dist/runtime/server/og-image/satori/plugins/unocss.js +13 -7
  51. package/dist/runtime/server/og-image/satori/renderer.js +5 -2
  52. package/dist/runtime/server/og-image/satori/transforms/emojis.d.ts +2 -2
  53. package/dist/runtime/server/og-image/satori/transforms/inlineCss.d.ts +1 -1
  54. package/dist/runtime/server/og-image/satori/transforms/inlineCss.js +6 -5
  55. package/dist/runtime/server/og-image/templates/html.js +2 -1
  56. package/dist/runtime/server/plugins/__zero-runtime/nuxt-content-v2.d.ts +1 -1
  57. package/dist/runtime/server/plugins/__zero-runtime/nuxt-content-v2.js +1 -1
  58. package/dist/runtime/server/plugins/nuxt-content-v2.d.ts +1 -1
  59. package/dist/runtime/server/plugins/nuxt-content-v2.js +1 -1
  60. package/dist/runtime/server/plugins/prerender.d.ts +1 -1
  61. package/dist/runtime/server/plugins/prerender.js +3 -3
  62. package/dist/runtime/server/routes/debug.json.js +2 -2
  63. package/dist/runtime/server/util/cache.js +2 -2
  64. package/dist/runtime/server/util/eventHandlers.js +5 -4
  65. package/dist/runtime/server/util/kit.d.ts +2 -2
  66. package/dist/runtime/server/util/kit.js +1 -1
  67. package/dist/runtime/server/util/plugins.js +3 -2
  68. package/dist/runtime/server/utils.d.ts +4 -0
  69. package/dist/runtime/server/utils.js +20 -0
  70. package/dist/runtime/shared.d.ts +13 -4
  71. package/dist/runtime/shared.js +103 -17
  72. package/dist/runtime/types.d.ts +15 -1
  73. package/package.json +38 -31
  74. package/{virtual.d.ts → types/virtual.d.ts} +11 -2
  75. package/dist/client/_nuxt/BuG-6Qss.js +0 -4017
  76. package/dist/client/_nuxt/CN8iCxzm.js +0 -1
  77. package/dist/client/_nuxt/DK6ySO-b.js +0 -1
  78. package/dist/client/_nuxt/builds/meta/a8d773e2-13ae-466e-b246-42e9659ce587.json +0 -1
  79. package/dist/client/_nuxt/entry.BVkKIlAn.css +0 -1
  80. package/dist/client/_nuxt/error-404.CWHu2lpK.css +0 -1
  81. package/dist/client/_nuxt/error-500.xMt3qmEl.css +0 -1
  82. package/dist/runtime/pure.d.ts +0 -9
  83. package/dist/runtime/pure.js +0 -105
@@ -11,11 +11,12 @@ import { useNitroApp } from "nitropack/runtime";
11
11
  import { hash } from "ohash";
12
12
  import { parseURL, withoutLeadingSlash, withoutTrailingSlash, withQuery } from "ufo";
13
13
  import { normalizeKey } from "unstorage";
14
- import { separateProps, useOgImageRuntimeConfig } from "../../shared.js";
14
+ import { separateProps } from "../../shared.js";
15
15
  import { decodeObjectHtmlEntities } from "../util/encoding.js";
16
16
  import { createNitroRouteRuleMatcher } from "../util/kit.js";
17
17
  import { logger } from "../util/logger.js";
18
18
  import { normaliseOptions } from "../util/options.js";
19
+ import { useOgImageRuntimeConfig } from "../utils.js";
19
20
  import { useChromiumRenderer, useSatoriRenderer } from "./instances.js";
20
21
  export function resolvePathCacheKey(e, path) {
21
22
  const siteConfig = useSiteConfig(e, {
@@ -145,7 +146,7 @@ export async function resolveContext(e) {
145
146
  const PAYLOAD_REGEX = /<script.+id="nuxt-og-image-options"[^>]*>(.+?)<\/script>/;
146
147
  function getPayloadFromHtml(html) {
147
148
  const match = String(html).match(PAYLOAD_REGEX);
148
- return match ? match[1] : null;
149
+ return match ? String(match[1]) : null;
149
150
  }
150
151
  export function extractAndNormaliseOgImageOptions(html) {
151
152
  const _payload = getPayloadFromHtml(html);
@@ -248,16 +249,17 @@ async function fetchPathHtmlAndExtractOptions(e, path, key) {
248
249
  }
249
250
  if (!_payload) {
250
251
  const payload2 = extractAndNormaliseOgImageOptions(html);
251
- if (payload2?.socialPreview?.og?.image) {
252
+ if (payload2 && typeof payload2 === "object" && payload2.socialPreview?.og?.image) {
253
+ const image = payload2.socialPreview.og.image;
252
254
  const p = {
253
255
  custom: true,
254
- url: payload2.socialPreview.og.image
256
+ url: typeof image === "string" ? image : image
255
257
  };
256
- if (payload2.socialPreview.og.image["image:width"]) {
257
- p.width = payload2.socialPreview.og.image["image:width"];
258
+ if (typeof image === "object" && image["image:width"]) {
259
+ p.width = image["image:width"];
258
260
  }
259
- if (payload2.socialPreview.og.image["image:height"]) {
260
- p.height = payload2.socialPreview.og.image["image:height"];
261
+ if (typeof image === "object" && image["image:height"]) {
262
+ p.height = image["image:height"];
261
263
  }
262
264
  return p;
263
265
  }
@@ -274,5 +276,8 @@ async function fetchPathHtmlAndExtractOptions(e, path, key) {
274
276
  value: payload
275
277
  });
276
278
  }
277
- return payload;
279
+ return typeof payload === "object" ? payload : createError({
280
+ statusCode: 500,
281
+ statusMessage: "[Nuxt OG Image] Invalid payload type."
282
+ });
278
283
  }
@@ -1,4 +1,5 @@
1
- import { useNitroOrigin, useStorage } from "#imports";
1
+ import { useNitroOrigin } from "#site-config/server/composables";
2
+ import { useStorage } from "nitropack/runtime";
2
3
  import { prefixStorage } from "unstorage";
3
4
  export const assets = prefixStorage(useStorage(), "/assets");
4
5
  export async function loadFont({ e, publicStoragePath }, font) {
@@ -11,7 +12,7 @@ export async function loadFont({ e, publicStoragePath }, font) {
11
12
  const decoder = new TextDecoder();
12
13
  fontData = decoder.decode(fontData);
13
14
  }
14
- font.data = Buffer.from(fontData, "base64");
15
+ font.data = Buffer.from(String(fontData), "base64");
15
16
  return font;
16
17
  }
17
18
  let data;
@@ -19,7 +20,7 @@ export async function loadFont({ e, publicStoragePath }, font) {
19
20
  if (import.meta.dev || import.meta.prerender) {
20
21
  const key = `${publicStoragePath}${font.path.replace("./", ":").replace("/", ":")}`;
21
22
  if (await useStorage().hasItem(key))
22
- data = await useStorage().getItemRaw(key);
23
+ data = await useStorage().getItemRaw(key) || void 0;
23
24
  } else {
24
25
  data = await e.$fetch(font.path, {
25
26
  baseURL: useNitroOrigin(e),
@@ -43,7 +43,7 @@ export default defineSatoriTransformer({
43
43
  }
44
44
  if (node.type === "div") {
45
45
  node.props.style.display = "flex";
46
- if (!node.props?.class?.includes("flex-") && node.props.children.some((child) => BLOCK_ELEMENTS.includes(child.type))) {
46
+ if (!node.props?.class?.includes("flex-") && Array.isArray(node.props.children) && node.props.children.some((child) => BLOCK_ELEMENTS.includes(child.type))) {
47
47
  node.props.style.flexDirection = "column";
48
48
  return;
49
49
  }
@@ -1,7 +1,8 @@
1
- import { useNitroOrigin, useStorage } from "#imports";
1
+ import { useNitroOrigin } from "#site-config/server/composables/useNitroOrigin";
2
2
  import sizeOf from "image-size";
3
+ import { useStorage } from "nitropack/runtime";
3
4
  import { withBase, withoutLeadingSlash } from "ufo";
4
- import { toBase64Image } from "../../../../pure.js";
5
+ import { toBase64Image } from "../../../../shared.js";
5
6
  import { decodeHtml } from "../../../util/encoding.js";
6
7
  import { logger } from "../../../util/logger.js";
7
8
  import { defineSatoriTransformer } from "../utils.js";
@@ -41,8 +42,10 @@ export default defineSatoriTransformer([
41
42
  });
42
43
  }
43
44
  }
44
- if (imageBuffer)
45
- node.props.src = toBase64Image(imageBuffer);
45
+ if (imageBuffer) {
46
+ const buffer = imageBuffer instanceof ArrayBuffer ? imageBuffer : imageBuffer.buffer;
47
+ node.props.src = toBase64Image(buffer);
48
+ }
46
49
  } else if (!src.startsWith("data:")) {
47
50
  src = decodeHtml(src);
48
51
  node.props.src = src;
@@ -71,7 +74,8 @@ export default defineSatoriTransformer([
71
74
  }
72
75
  if (typeof node.props.src === "string" && node.props.src.startsWith("/")) {
73
76
  if (imageBuffer) {
74
- node.props.src = toBase64Image(imageBuffer);
77
+ const buffer = imageBuffer instanceof ArrayBuffer ? imageBuffer : imageBuffer.buffer;
78
+ node.props.src = toBase64Image(buffer);
75
79
  } else {
76
80
  node.props.src = `${withBase(src, `${useNitroOrigin(e)}`)}?${Date.now()}`;
77
81
  }
@@ -90,7 +94,8 @@ export default defineSatoriTransformer([
90
94
  const srcWithoutBase = src.replace(runtimeConfig.app.baseURL, "/");
91
95
  const imageBuffer = await resolveLocalFilePathImage(publicStoragePath, srcWithoutBase);
92
96
  if (imageBuffer) {
93
- const base64 = toBase64Image(Buffer.from(imageBuffer));
97
+ const buffer = imageBuffer instanceof ArrayBuffer ? imageBuffer : imageBuffer.buffer;
98
+ const base64 = toBase64Image(buffer);
94
99
  node.props.style.backgroundImage = `url(${base64})`;
95
100
  }
96
101
  } else {
@@ -1,4 +1,8 @@
1
1
  import { defineSatoriTransformer } from "../utils.js";
2
+ function safeSplit(s) {
3
+ const [key, value] = s.split(":");
4
+ return [String(key || "").trim(), String(value || "").trim()];
5
+ }
2
6
  export default defineSatoriTransformer({
3
7
  filter: (node) => !!node.props?.class,
4
8
  transform: async (node, ctx) => {
@@ -8,7 +12,7 @@ export default defineSatoriTransformer({
8
12
  for (const token of classes.split(" ").filter((c) => c.trim())) {
9
13
  const parsedToken = await ctx.unocss.parseToken(token);
10
14
  if (parsedToken) {
11
- const inlineStyles = parsedToken[0][2].split(";").filter((s) => !!s?.trim());
15
+ const inlineStyles = String(parsedToken?.[0]?.[2]).split(";").filter((s) => !!s?.trim());
12
16
  const vars = {
13
17
  "--color-gray-50": "249 250 251",
14
18
  "--color-gray-100": "243 244 246",
@@ -23,20 +27,22 @@ export default defineSatoriTransformer({
23
27
  "--color-gray-950": "3 7 18"
24
28
  };
25
29
  inlineStyles.filter((s) => s.startsWith("--")).forEach((s) => {
26
- const [key, value] = s.split(":");
30
+ const [key, value] = safeSplit(s);
27
31
  vars[key] = value;
28
32
  });
29
33
  inlineStyles.filter((s) => !s.startsWith("--")).forEach((s) => {
30
- const [key, value] = s.split(":");
34
+ const [key, value] = safeSplit(s);
31
35
  const camelCasedKey = key.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
32
36
  if (!styles[camelCasedKey])
33
37
  styles[camelCasedKey] = value.replace(/var\((.*?)\)/g, (_, k) => vars[k.trim()]);
34
38
  if (styles[camelCasedKey] && styles[camelCasedKey].includes("/")) {
35
39
  const [rgb, opacity] = styles[camelCasedKey].split("/");
36
- if (opacity.trim() === "1)")
37
- styles[camelCasedKey] = rgb.replace(/(\d+) (\d+) (\d+).*/, (_, r, g, b) => `${r}, ${g}, ${b})`);
38
- else
39
- styles[camelCasedKey] = `${rgb.replace("rgb", "rgba").replaceAll(" ", ", ")}${opacity.trim()}`;
40
+ if (rgb && opacity) {
41
+ if (opacity.trim() === "1)")
42
+ styles[camelCasedKey] = rgb.replace(/(\d+) (\d+) (\d+).*/, (_, r, g, b) => `${r}, ${g}, ${b})`);
43
+ else
44
+ styles[camelCasedKey] = `${rgb.replace("rgb", "rgba").replaceAll(" ", ", ")}${opacity.trim()}`;
45
+ }
40
46
  }
41
47
  });
42
48
  replacedClasses.add(token);
@@ -3,7 +3,8 @@ import { theme } from "#og-image-virtual/unocss-config.mjs";
3
3
  import compatibility from "#og-image/compatibility";
4
4
  import { defu } from "defu";
5
5
  import { sendError } from "h3";
6
- import { normaliseFontInput, useOgImageRuntimeConfig } from "../../../shared.js";
6
+ import { normaliseFontInput } from "../../../shared.js";
7
+ import { useOgImageRuntimeConfig } from "../../utils.js";
7
8
  import { loadFont } from "./font.js";
8
9
  import { useResvg, useSatori, useSharp } from "./instances.js";
9
10
  import { createVNodes } from "./vnodes.js";
@@ -16,7 +17,7 @@ async function resolveFonts(event) {
16
17
  if (fontCache) {
17
18
  for (const font of normalisedFonts) {
18
19
  if (await fontCache.hasItem(font.cacheKey)) {
19
- font.data = await fontCache.getItemRaw(font.cacheKey);
20
+ font.data = await fontCache.getItemRaw(font.cacheKey) || void 0;
20
21
  preloadedFonts.push(font);
21
22
  } else {
22
23
  if (!fontPromises[font.cacheKey]) {
@@ -58,6 +59,8 @@ export async function createSvg(event) {
58
59
  async function createPng(event) {
59
60
  const { resvgOptions } = useOgImageRuntimeConfig();
60
61
  const svg = await createSvg(event);
62
+ if (!svg)
63
+ throw new Error("Failed to create SVG");
61
64
  const Resvg = await useResvg();
62
65
  const resvg = new Resvg(svg, defu(
63
66
  event.options.resvg,
@@ -1,3 +1,3 @@
1
- import type { NuxtIslandResponse } from 'nuxt/dist/core/runtime/nitro/renderer';
1
+ import type { NuxtIslandResponse } from 'nuxt/app';
2
2
  import type { OgImageRenderEventContext } from '../../../../types.js';
3
- export declare function applyEmojis(ctx: OgImageRenderEventContext, island: NuxtIslandResponse): Promise<any>;
3
+ export declare function applyEmojis(ctx: OgImageRenderEventContext, island: NuxtIslandResponse): Promise<string | boolean>;
@@ -1,3 +1,3 @@
1
- import type { NuxtIslandResponse } from 'nuxt/dist/core/runtime/nitro/renderer';
1
+ import type { NuxtIslandResponse } from 'nuxt/app';
2
2
  import type { OgImageRenderEventContext } from '../../../../types.js';
3
3
  export declare function applyInlineCss(ctx: OgImageRenderEventContext, island: NuxtIslandResponse): Promise<boolean>;
@@ -1,4 +1,4 @@
1
- import { useNitroOrigin } from "#imports";
1
+ import { useNitroOrigin } from "#site-config/server/composables/useNitroOrigin";
2
2
  import { createConsola } from "consola";
3
3
  import { useCssInline } from "../instances.js";
4
4
  export async function applyInlineCss(ctx, island) {
@@ -11,7 +11,7 @@ export async function applyInlineCss(ctx, island) {
11
11
  }
12
12
  let linksToCss = [];
13
13
  if (import.meta.dev) {
14
- linksToCss = componentInlineStyles.length ? (await Promise.all(
14
+ const cssResults = componentInlineStyles.length ? await Promise.all(
15
15
  componentInlineStyles.map((l) => {
16
16
  const url = l.href.endsWith("lang.css") ? `${l.href}&hmr=false` : l.href;
17
17
  return e.$fetch(url, {
@@ -19,14 +19,15 @@ export async function applyInlineCss(ctx, island) {
19
19
  baseURL: useNitroOrigin(e)
20
20
  }).then((res) => {
21
21
  if (res.includes("__vite__css"))
22
- return res.match(/__vite__css = "([^"]+)"/)?.[1];
22
+ return res.match(/__vite__css = "([^"]+)"/)?.[1] || "";
23
23
  return res.trim().split("\n").filter((l2) => !l2.startsWith("//")).join("\n").trim();
24
24
  }).catch(() => {
25
25
  return "";
26
26
  });
27
27
  })
28
- )).join("\n") : "";
29
- css = [linksToCss, css].join("\n");
28
+ ) : [];
29
+ linksToCss = cssResults;
30
+ css = [linksToCss.join("\n"), css].join("\n");
30
31
  }
31
32
  if (!css.trim().length)
32
33
  return false;
@@ -2,8 +2,9 @@ import { theme } from "#og-image-virtual/unocss-config.mjs";
2
2
  import { createHeadCore } from "@unhead/vue";
3
3
  import { renderSSRHead } from "@unhead/vue/server";
4
4
  import { createError } from "h3";
5
- import { normaliseFontInput, useOgImageRuntimeConfig } from "../../../shared.js";
5
+ import { normaliseFontInput } from "../../../shared.js";
6
6
  import { fetchIsland } from "../../util/kit.js";
7
+ import { useOgImageRuntimeConfig } from "../../utils.js";
7
8
  import { applyEmojis } from "../satori/transforms/emojis.js";
8
9
  export async function html(ctx) {
9
10
  const { options } = ctx;
@@ -1,2 +1,2 @@
1
- declare const _default: any;
1
+ declare const _default: import("nitropack").NitroAppPlugin;
2
2
  export default _default;
@@ -1,4 +1,4 @@
1
- import { defineNitroPlugin } from "#imports";
1
+ import { defineNitroPlugin } from "nitropack/runtime";
2
2
  import { nuxtContentPlugin } from "../../util/plugins.js";
3
3
  export default defineNitroPlugin((nitroApp) => {
4
4
  if (import.meta.dev || import.meta.prerender) {
@@ -1,2 +1,2 @@
1
- declare const _default: any;
1
+ declare const _default: import("nitropack").NitroAppPlugin;
2
2
  export default _default;
@@ -1,4 +1,4 @@
1
- import { defineNitroPlugin } from "#imports";
1
+ import { defineNitroPlugin } from "nitropack/runtime";
2
2
  import { nuxtContentPlugin } from "../util/plugins.js";
3
3
  export default defineNitroPlugin((nitroApp) => {
4
4
  nuxtContentPlugin(nitroApp);
@@ -1,2 +1,2 @@
1
- declare const _default: any;
1
+ declare const _default: import("nitropack").NitroAppPlugin;
2
2
  export default _default;
@@ -1,8 +1,8 @@
1
- import { defineNitroPlugin } from "#imports";
2
1
  import { prerenderOptionsCache } from "#og-image-cache";
3
2
  import { createSitePathResolver } from "#site-config/server/composables/utils";
3
+ import { defineNitroPlugin } from "nitropack/runtime";
4
4
  import { parseURL } from "ufo";
5
- import { isInternalRoute } from "../../pure.js";
5
+ import { isInternalRoute } from "../../shared.js";
6
6
  import { extractAndNormaliseOgImageOptions, resolvePathCacheKey } from "../og-image/context.js";
7
7
  import { createNitroRouteRuleMatcher } from "../util/kit.js";
8
8
  export default defineNitroPlugin(async (nitro) => {
@@ -31,7 +31,7 @@ export default defineNitroPlugin(async (nitro) => {
31
31
  await prerenderOptionsCache.setItem(key, options);
32
32
  const index = html.bodyAppend.findIndex((script) => script.includes('id="nuxt-og-image-options"'));
33
33
  if (index !== -1) {
34
- html.bodyAppend[index] = html.bodyAppend[index].replace(/<script id="nuxt-og-image-options" type="application\/json">[\s\S]*?<\/script>/, "");
34
+ html.bodyAppend[index] = String(html.bodyAppend[index]).replace(/<script id="nuxt-og-image-options" type="application\/json">[\s\S]*?<\/script>/, "");
35
35
  html.bodyAppend[index] = html.bodyAppend[index].replace(/<script id="nuxt-og-image-overrides" type="application\/json">[\s\S]*?<\/script>/, "");
36
36
  }
37
37
  });
@@ -1,8 +1,8 @@
1
- import { useSiteConfig } from "#imports";
2
1
  import { componentNames } from "#og-image-virtual/component-names.mjs";
3
2
  import compatibility from "#og-image/compatibility";
3
+ import { useSiteConfig } from "#site-config/server/composables/useSiteConfig";
4
4
  import { defineEventHandler, setHeader } from "h3";
5
- import { useOgImageRuntimeConfig } from "../../shared.js";
5
+ import { useOgImageRuntimeConfig } from "../utils.js";
6
6
  export default defineEventHandler(async (e) => {
7
7
  setHeader(e, "Content-Type", "application/json");
8
8
  const runtimeConfig = useOgImageRuntimeConfig();
@@ -1,11 +1,11 @@
1
- import { useStorage } from "#imports";
2
1
  import { createError, getQuery, handleCacheHeaders, setHeader, setHeaders } from "h3";
2
+ import { useStorage } from "nitropack/runtime";
3
3
  import { hash } from "ohash";
4
4
  import { withTrailingSlash } from "ufo";
5
5
  import { prefixStorage } from "unstorage";
6
6
  export async function useOgImageBufferCache(ctx, options) {
7
7
  const maxAge = Number(options.cacheMaxAgeSeconds);
8
- let enabled = !import.meta.dev && import.meta.env.MODE !== "test" && maxAge > 0;
8
+ let enabled = !import.meta.dev && import.meta.env?.MODE !== "test" && maxAge > 0;
9
9
  const cache = prefixStorage(useStorage(), withTrailingSlash(options.baseCacheKey || "/"));
10
10
  const key = ctx.key;
11
11
  let cachedItem = false;
@@ -1,15 +1,16 @@
1
1
  import { createError, getQuery, H3Error, proxyRequest, sendRedirect, setHeader, setResponseHeader } from "h3";
2
2
  import { parseURL } from "ufo";
3
- import { normaliseFontInput, useOgImageRuntimeConfig } from "../../shared.js";
3
+ import { normaliseFontInput } from "../../shared.js";
4
4
  import { resolveContext } from "../og-image/context.js";
5
5
  import { assets } from "../og-image/satori/font.js";
6
6
  import { html } from "../og-image/templates/html.js";
7
+ import { useOgImageRuntimeConfig } from "../utils.js";
7
8
  import { useOgImageBufferCache } from "./cache.js";
8
9
  export async function fontEventHandler(e) {
9
10
  const path = parseURL(e.path).pathname;
10
11
  const { fonts } = useOgImageRuntimeConfig();
11
12
  const key = path.split("/font/")[1];
12
- if (key.includes(":")) {
13
+ if (key && key.includes(":")) {
13
14
  const font2 = fonts.find((f) => f.key === key);
14
15
  if (font2?.key && await assets.hasItem(font2.key)) {
15
16
  let fontData = await assets.getItem(font2.key);
@@ -27,10 +28,10 @@ export async function fontEventHandler(e) {
27
28
  return Buffer.from(fontData, "base64");
28
29
  }
29
30
  }
30
- const [_name, _weight] = key.split(".")[0].split("/");
31
+ const [_name, _weight] = String(key?.split(".")[0]).split("/");
31
32
  if (!_name || !_weight)
32
33
  return "Provide a font name and weight";
33
- const name = _name[0].toUpperCase() + _name.slice(1);
34
+ const name = String(_name[0]).toUpperCase() + _name.slice(1);
34
35
  const weight = Math.round(Number.parseInt(_weight) / 100) * 100;
35
36
  const config = useOgImageRuntimeConfig();
36
37
  const normalisedFonts = normaliseFontInput(config.fonts);
@@ -1,6 +1,6 @@
1
1
  import type { H3Event } from 'h3';
2
2
  import type { NitroRouteRules } from 'nitropack';
3
- import type { NuxtIslandResponse } from 'nuxt/dist/core/runtime/nitro/renderer';
3
+ import type { NuxtIslandResponse } from 'nuxt/app';
4
4
  export declare function fetchIsland(e: H3Event, component: string, props: Record<string, any>): Promise<NuxtIslandResponse>;
5
- export declare function withoutQuery(path: string): string;
5
+ export declare function withoutQuery(path: string): string | undefined;
6
6
  export declare function createNitroRouteRuleMatcher(): ((path: string) => NitroRouteRules);
@@ -1,5 +1,5 @@
1
- import { useRuntimeConfig } from "#imports";
2
1
  import { defu } from "defu";
2
+ import { useRuntimeConfig } from "nitropack/runtime";
3
3
  import { hash } from "ohash";
4
4
  import { createRouter as createRadixRouter, toRouteMatcher } from "radix3";
5
5
  import { withoutBase, withoutTrailingSlash } from "ufo";
@@ -1,7 +1,8 @@
1
1
  import { defu } from "defu";
2
2
  import { stringify } from "devalue";
3
3
  import { withQuery } from "ufo";
4
- import { generateMeta, getOgImagePath, useOgImageRuntimeConfig } from "../../shared.js";
4
+ import { generateMeta } from "../../shared.js";
5
+ import { getOgImagePath, useOgImageRuntimeConfig } from "../utils.js";
5
6
  import { normaliseOptions } from "./options.js";
6
7
  export function nuxtContentPlugin(nitroApp) {
7
8
  const { isNuxtContentDocumentDriven, strictNuxtContentPaths, defaults } = useOgImageRuntimeConfig();
@@ -32,7 +33,7 @@ export function nuxtContentPlugin(nitroApp) {
32
33
  ...content.ogImage
33
34
  };
34
35
  Object.entries(ogImageConfig).forEach(([key, val]) => {
35
- payload[key.replace(/-([a-z])/g, (g) => g[1].toUpperCase())] = val;
36
+ payload[key.replace(/-([a-z])/g, (g) => String(g[1]).toUpperCase())] = val;
36
37
  });
37
38
  content.head = defu({
38
39
  script: [
@@ -0,0 +1,4 @@
1
+ import type { OgImageOptions, OgImageRuntimeConfig } from '#og-image/types';
2
+ import type { H3Event } from 'h3';
3
+ export declare function getOgImagePath(pagePath: string, _options?: Partial<OgImageOptions>): string;
4
+ export declare function useOgImageRuntimeConfig(e?: H3Event): OgImageRuntimeConfig;
@@ -0,0 +1,20 @@
1
+ import { useRuntimeConfig } from "nitropack/runtime";
2
+ import { joinURL, withQuery } from "ufo";
3
+ export function getOgImagePath(pagePath, _options) {
4
+ const baseURL = useRuntimeConfig().app.baseURL;
5
+ const extension = _options?.extension || useOgImageRuntimeConfig().defaults.extension;
6
+ const path = joinURL("/", baseURL, `__og-image__/${import.meta.prerender ? "static" : "image"}`, pagePath, `og.${extension}`);
7
+ if (Object.keys(_options?._query || {}).length) {
8
+ return withQuery(path, _options._query);
9
+ }
10
+ return path;
11
+ }
12
+ export function useOgImageRuntimeConfig(e) {
13
+ const c = useRuntimeConfig(e);
14
+ return {
15
+ ...c["nuxt-og-image"],
16
+ app: {
17
+ baseURL: c.app.baseURL
18
+ }
19
+ };
20
+ }
@@ -1,6 +1,15 @@
1
1
  import type { ResolvableMeta } from '@unhead/vue';
2
- import type { OgImageOptions, OgImagePrebuilt, OgImageRuntimeConfig } from './types.js';
3
- export * from './pure.js';
2
+ import type { InputFontConfig, OgImageOptions, OgImagePrebuilt, ResolvedFontConfig } from './types.js';
4
3
  export declare function generateMeta(url: OgImagePrebuilt['url'] | string, resolvedOptions: OgImageOptions | OgImagePrebuilt): ResolvableMeta[];
5
- export declare function getOgImagePath(pagePath: string, _options?: Partial<OgImageOptions>): string;
6
- export declare function useOgImageRuntimeConfig(): OgImageRuntimeConfig;
4
+ export declare function toBase64Image(data: string | ArrayBuffer): string;
5
+ export declare function isInternalRoute(path: string): boolean;
6
+ export declare function separateProps(options: OgImageOptions | undefined, ignoreKeys?: string[]): {
7
+ props: Record<string, any>;
8
+ };
9
+ export declare function normaliseFontInput(fonts: InputFontConfig[]): ResolvedFontConfig[];
10
+ export declare function withoutQuery(path: string): string | undefined;
11
+ export declare function getExtension(path: string): string;
12
+ /**
13
+ * @deprecated Please use `#og-image/app/utils` instead.
14
+ */
15
+ export declare function useOgImageRuntimeConfig(): {};
@@ -1,8 +1,5 @@
1
- import { useRuntimeConfig } from "#imports";
2
- import { joinURL, withQuery } from "ufo";
1
+ import { defu } from "defu";
3
2
  import { toValue } from "vue";
4
- import { getExtension } from "./pure.js";
5
- export * from "./pure.js";
6
3
  export function generateMeta(url, resolvedOptions) {
7
4
  const meta = [
8
5
  { property: "og:image", content: url },
@@ -26,21 +23,110 @@ export function generateMeta(url, resolvedOptions) {
26
23
  }
27
24
  return meta;
28
25
  }
29
- export function getOgImagePath(pagePath, _options) {
30
- const baseURL = useRuntimeConfig().app.baseURL;
31
- const extension = _options?.extension || useOgImageRuntimeConfig().defaults.extension;
32
- const path = joinURL("/", baseURL, `__og-image__/${import.meta.prerender ? "static" : "image"}`, pagePath, `og.${extension}`);
33
- if (Object.keys(_options?._query || {}).length) {
34
- return withQuery(path, _options._query);
26
+ function detectBase64MimeType(data) {
27
+ const signatures = {
28
+ "R0lGODdh": "image/gif",
29
+ "R0lGODlh": "image/gif",
30
+ "iVBORw0KGgo": "image/png",
31
+ "/9j/": "image/jpeg",
32
+ "UklGR": "image/webp",
33
+ "AAABAA": "image/x-icon"
34
+ };
35
+ for (const s in signatures) {
36
+ if (data.startsWith(s)) {
37
+ return signatures[s];
38
+ }
35
39
  }
36
- return path;
40
+ return "image/svg+xml";
37
41
  }
38
- export function useOgImageRuntimeConfig() {
39
- const c = useRuntimeConfig();
42
+ export function toBase64Image(data) {
43
+ const base64 = typeof data === "string" ? data : Buffer.from(data).toString("base64");
44
+ const type = detectBase64MimeType(base64);
45
+ return `data:${type};base64,${base64}`;
46
+ }
47
+ export function isInternalRoute(path) {
48
+ return path.startsWith("/_") || path.startsWith("@");
49
+ }
50
+ function filterIsOgImageOption(key) {
51
+ const keys = [
52
+ "url",
53
+ "extension",
54
+ "width",
55
+ "height",
56
+ "fonts",
57
+ "alt",
58
+ "props",
59
+ "renderer",
60
+ "html",
61
+ "component",
62
+ "renderer",
63
+ "emojis",
64
+ "_query",
65
+ "satori",
66
+ "resvg",
67
+ "sharp",
68
+ "screenshot",
69
+ "cacheMaxAgeSeconds"
70
+ ];
71
+ return keys.includes(key);
72
+ }
73
+ export function separateProps(options, ignoreKeys = []) {
74
+ options = options || {};
75
+ const _props = defu(options.props, Object.fromEntries(
76
+ Object.entries({ ...options }).filter(([k]) => !filterIsOgImageOption(k) && !ignoreKeys.includes(k))
77
+ ));
78
+ const props = {};
79
+ Object.entries(_props).forEach(([key, val]) => {
80
+ props[key.replace(/-([a-z])/g, (g) => String(g[1]).toUpperCase())] = val;
81
+ });
40
82
  return {
41
- ...c["nuxt-og-image"],
42
- app: {
43
- baseURL: c.app.baseURL
44
- }
83
+ ...Object.fromEntries(
84
+ Object.entries({ ...options }).filter(([k]) => filterIsOgImageOption(k) || ignoreKeys.includes(k))
85
+ ),
86
+ props
45
87
  };
46
88
  }
89
+ export function normaliseFontInput(fonts) {
90
+ return fonts.map((f) => {
91
+ if (typeof f === "string") {
92
+ const vals = f.split(":");
93
+ const includesStyle = vals.length === 3;
94
+ let name, weight, style;
95
+ if (includesStyle) {
96
+ name = vals[0];
97
+ style = vals[1];
98
+ weight = vals[2];
99
+ } else {
100
+ name = vals[0];
101
+ weight = vals[1];
102
+ }
103
+ return {
104
+ cacheKey: f,
105
+ name,
106
+ weight: weight || 400,
107
+ style: style || "normal",
108
+ path: void 0
109
+ };
110
+ }
111
+ return {
112
+ cacheKey: f.key || `${f.name}:${f.style}:${f.weight}`,
113
+ style: "normal",
114
+ weight: 400,
115
+ ...f
116
+ };
117
+ });
118
+ }
119
+ export function withoutQuery(path) {
120
+ return path.split("?")[0];
121
+ }
122
+ export function getExtension(path) {
123
+ path = withoutQuery(path);
124
+ const lastSegment = path.split("/").pop() || path;
125
+ const extension = lastSegment.split(".").pop() || lastSegment;
126
+ if (extension === "jpg")
127
+ return "jpeg";
128
+ return extension;
129
+ }
130
+ export function useOgImageRuntimeConfig() {
131
+ return {};
132
+ }
@@ -119,6 +119,11 @@ export interface OgImageOptions<T extends keyof OgImageComponents = 'NuxtSeo'> {
119
119
  sharp?: SharpOptions & JpegOptions;
120
120
  fonts?: InputFontConfig[];
121
121
  cacheMaxAgeSeconds?: number;
122
+ /**
123
+ * Social preview metadata
124
+ * @internal
125
+ */
126
+ socialPreview?: SocialPreviewMetaData;
122
127
  /**
123
128
  * @internal
124
129
  */
@@ -169,5 +174,14 @@ export interface SatoriTransformer {
169
174
  }
170
175
  export interface SocialPreviewMetaData {
171
176
  twitter?: Record<string, string>;
172
- og?: Record<string, string>;
177
+ og?: Record<string, string> & {
178
+ image?: string | {
179
+ 'image:width'?: string | number;
180
+ 'image:height'?: string | number;
181
+ [key: string]: any;
182
+ };
183
+ };
184
+ }
185
+ export interface RouteRulesOgImage extends Partial<OgImageOptions> {
186
+ [key: string]: any;
173
187
  }