nuxt-og-image 6.10.4 → 7.0.1

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 (103) hide show
  1. package/README.md +10 -14
  2. package/dist/chunks/tw4.mjs +6 -6
  3. package/dist/chunks/uno.mjs +7 -7
  4. package/dist/cli.mjs +4 -4
  5. package/dist/devtools/components/og-image/RendererSelectModal.vue +1 -1
  6. package/dist/devtools/lib/og-image/fonts.ts +38 -0
  7. package/dist/devtools/lib/og-image/types.ts +7 -0
  8. package/dist/devtools/pages/og-image/index.vue +19 -14
  9. package/dist/module.d.mts +14 -10
  10. package/dist/module.d.ts +14 -10
  11. package/dist/module.json +2 -2
  12. package/dist/module.mjs +6 -6
  13. package/dist/runtime/app/client-utils.js +7 -4
  14. package/dist/runtime/app/components/Templates/Community/SaaS.satori.vue +1 -1
  15. package/dist/runtime/app/components/Templates/Community/SimpleBlog.satori.vue +1 -1
  16. package/dist/runtime/app/disabled/components.d.ts +1 -0
  17. package/dist/runtime/app/disabled/components.js +0 -0
  18. package/dist/runtime/app/disabled/composables/defineOgImage.d.ts +1 -0
  19. package/dist/runtime/app/disabled/composables/defineOgImage.js +1 -0
  20. package/dist/runtime/app/disabled/composables/defineOgImageComponent.d.ts +1 -0
  21. package/dist/runtime/app/disabled/composables/defineOgImageComponent.js +1 -0
  22. package/dist/runtime/app/disabled/composables/defineOgImageScreenshot.d.ts +1 -0
  23. package/dist/runtime/app/disabled/composables/defineOgImageScreenshot.js +1 -0
  24. package/dist/runtime/app/disabled/composables/mock.d.ts +1 -0
  25. package/dist/runtime/app/disabled/composables/mock.js +1 -0
  26. package/dist/runtime/app/disabled/index.d.ts +3 -0
  27. package/dist/runtime/app/disabled/index.js +3 -0
  28. package/dist/runtime/app/index.d.ts +4 -0
  29. package/dist/runtime/app/index.js +4 -0
  30. package/dist/runtime/app/utils/plugins.js +1 -1
  31. package/dist/runtime/app/utils.js +2 -2
  32. package/dist/runtime/server/index.d.ts +1 -0
  33. package/dist/runtime/server/index.js +1 -0
  34. package/dist/runtime/server/middleware/signing.d.ts +2 -0
  35. package/dist/runtime/server/middleware/signing.js +19 -0
  36. package/dist/runtime/server/nitro.d.ts +3 -3
  37. package/dist/runtime/server/nitro.js +4 -4
  38. package/dist/runtime/server/og-image/bindings/font-assets/dev-prerender.js +8 -49
  39. package/dist/runtime/server/og-image/bindings/font-assets/node.js +3 -2
  40. package/dist/runtime/server/og-image/bindings/satori/node.d.ts +1 -2
  41. package/dist/runtime/server/og-image/bindings/satori/wasm-fs.d.ts +1 -2
  42. package/dist/runtime/server/og-image/bindings/satori/wasm-fs.js +1 -1
  43. package/dist/runtime/server/og-image/bindings/satori/wasm.d.ts +1 -2
  44. package/dist/runtime/server/og-image/bindings/satori/wasm.js +1 -1
  45. package/dist/runtime/server/og-image/browser/screenshot.js +5 -3
  46. package/dist/runtime/server/og-image/cache/publish.d.ts +46 -0
  47. package/dist/runtime/server/og-image/cache/publish.js +91 -0
  48. package/dist/runtime/server/og-image/cache/published.d.ts +17 -0
  49. package/dist/runtime/server/og-image/cache/published.js +49 -0
  50. package/dist/runtime/server/og-image/context.js +1 -1
  51. package/dist/runtime/server/og-image/core/plugins/imageSrc.js +2 -5
  52. package/dist/runtime/server/og-image/core/transforms/emojis/index.d.ts +3 -2
  53. package/dist/runtime/server/og-image/core/vnodes.js +19 -1
  54. package/dist/runtime/server/og-image/font-source.d.ts +1 -0
  55. package/dist/runtime/server/og-image/font-source.js +1 -0
  56. package/dist/runtime/server/og-image/fonts.d.ts +1 -1
  57. package/dist/runtime/server/og-image/fonts.js +1 -1
  58. package/dist/runtime/server/og-image/satori/filters.d.ts +1 -0
  59. package/dist/runtime/server/og-image/satori/filters.js +14 -0
  60. package/dist/runtime/server/og-image/satori/instances.d.ts +1 -2
  61. package/dist/runtime/server/og-image/satori/plugins/classes.js +0 -7
  62. package/dist/runtime/server/og-image/satori/renderer.js +2 -1
  63. package/dist/runtime/server/og-image/satori/vnodes.js +1 -4
  64. package/dist/runtime/server/og-image/takumi/renderer.js +11 -47
  65. package/dist/runtime/server/og-image/utils/css.d.ts +0 -5
  66. package/dist/runtime/server/og-image/utils/css.js +0 -5
  67. package/dist/runtime/server/plugins/auto-eject-nitro3.d.ts +2 -0
  68. package/dist/runtime/server/plugins/auto-eject-nitro3.js +9 -0
  69. package/dist/runtime/server/plugins/auto-eject.js +3 -31
  70. package/dist/runtime/server/plugins/prerender.js +67 -2
  71. package/dist/runtime/server/plugins/publish.d.ts +2 -0
  72. package/dist/runtime/server/plugins/publish.js +44 -0
  73. package/dist/runtime/server/routes/debug.json.d.ts +10 -1
  74. package/dist/runtime/server/routes/debug.json.js +4 -4
  75. package/dist/runtime/server/routes/static-font.d.ts +2 -0
  76. package/dist/runtime/server/routes/static-font.js +22 -0
  77. package/dist/runtime/server/signing-secret.d.ts +8 -0
  78. package/dist/runtime/server/signing-secret.js +75 -0
  79. package/dist/runtime/server/util/auto-eject-lifecycle.d.ts +13 -0
  80. package/dist/runtime/server/util/auto-eject-lifecycle.js +31 -0
  81. package/dist/runtime/server/util/cache.d.ts +1 -0
  82. package/dist/runtime/server/util/cache.js +12 -6
  83. package/dist/runtime/server/util/cloudflare.d.ts +2 -2
  84. package/dist/runtime/server/util/eventHandlers.js +68 -3
  85. package/dist/runtime/server/util/fetchLocalAsset.js +2 -2
  86. package/dist/runtime/server/util/origin.d.ts +3 -0
  87. package/dist/runtime/server/util/origin.js +4 -0
  88. package/dist/runtime/server/util/publishWarnings.d.ts +6 -0
  89. package/dist/runtime/server/util/publishWarnings.js +6 -0
  90. package/dist/runtime/server/utils.d.ts +3 -3
  91. package/dist/runtime/server/utils.js +5 -10
  92. package/dist/runtime/shared/publish.d.ts +13 -0
  93. package/dist/runtime/shared/publish.js +17 -0
  94. package/dist/runtime/shared/urlEncoding.js +9 -4
  95. package/dist/runtime/types.d.ts +11 -16
  96. package/dist/shared/{nuxt-og-image.Bcegsloy.mjs → nuxt-og-image.DR_SxdDv.mjs} +1224 -1109
  97. package/package.json +60 -62
  98. package/skills/nuxt-og-image/SKILL.md +31 -14
  99. package/types/virtual.d.ts +8 -0
  100. package/dist/runtime/server/og-image/satori/plugins/emojis.d.ts +0 -2
  101. package/dist/runtime/server/og-image/satori/plugins/emojis.js +0 -112
  102. package/dist/runtime/server/og-image/satori/plugins/flex.d.ts +0 -2
  103. package/dist/runtime/server/og-image/satori/plugins/flex.js +0 -48
@@ -1,12 +1,16 @@
1
- import { appendResponseHeader, createError, getRequestHost, H3Error, setHeader } from "#nuxtseo/h3";
1
+ import { appendResponseHeader, createError, getRequestHost, H3Error, sendRedirect, setHeader } from "#nuxtseo/h3";
2
+ import { useStorage } from "#nuxtseo/nitro";
2
3
  import { getSiteConfig } from "#site-config/server/composables/getSiteConfig";
3
4
  import { logger } from "../../logger.js";
4
5
  import { getBuildCachedImage, setBuildCachedImage } from "../og-image/cache/buildCache.js";
6
+ import { getPublishedImage, getPublishKey, publishImage } from "../og-image/cache/publish.js";
7
+ import { getPublishedImageCache, getPublishedImageCacheKey } from "../og-image/cache/published.js";
5
8
  import { resolveContext } from "../og-image/context.js";
6
9
  import { fetchPathHtmlAndExtractOptions } from "../og-image/devtools.js";
7
10
  import { html } from "../og-image/templates/html.js";
8
11
  import { useOgImageRuntimeConfig } from "../utils.js";
9
12
  import { useOgImageBufferCache } from "./cache.js";
13
+ import { warnPublishUnavailable } from "./publishWarnings.js";
10
14
  import { parsePurgeRequest } from "./purge.js";
11
15
  import { getEventQuery } from "./query.js";
12
16
  export async function imageEventHandler(e) {
@@ -31,7 +35,8 @@ export async function imageEventHandler(e) {
31
35
  async function renderOgImage(e, ctx) {
32
36
  const timings = ctx.timings;
33
37
  const { isDevToolsContextRequest, extension, renderer } = ctx;
34
- const { debug, baseCacheKey, security } = useOgImageRuntimeConfig(e);
38
+ const config = useOgImageRuntimeConfig(e);
39
+ const { debug, baseCacheKey, security, publish } = config;
35
40
  if (!import.meta.prerender && !import.meta.dev && security?.restrictRuntimeImagesToOrigin) {
36
41
  const requestHost = getRequestHost(e, { xForwardedHost: true });
37
42
  let requestHostname;
@@ -67,6 +72,7 @@ async function renderOgImage(e, ctx) {
67
72
  statusMessage: "[Nuxt OG Image] Invalid purge token. Provide the signing secret as ?purge=<secret>."
68
73
  });
69
74
  }
75
+ const purge = purgeRequest._tag === "Authorized";
70
76
  if ((import.meta.dev || debug) && isDevToolsContextRequest) {
71
77
  setHeader(e, "Content-Type", "application/json");
72
78
  const [extract, rendererDebug] = await Promise.all([
@@ -125,15 +131,48 @@ async function renderOgImage(e, ctx) {
125
131
  timings.record("cache-hit", 0);
126
132
  return buildCachedImage;
127
133
  }
134
+ let publication = publish && !import.meta.dev && !import.meta.prerender ? (() => {
135
+ const key = getPublishKey(new URL(e.path, getSiteConfig(e).url).href, config.defaults, publish.cacheVersion);
136
+ return {
137
+ cache: getPublishedImageCache(ctx._nitro),
138
+ cacheKey: getPublishedImageCacheKey(publish, key, extension),
139
+ input: {
140
+ storage: useStorage(),
141
+ mount: publish.storage,
142
+ baseURL: publish.baseURL,
143
+ key,
144
+ extension,
145
+ maxAgeSeconds: Number(ctx.options.cacheMaxAgeSeconds),
146
+ timeoutMs: security.renderTimeout,
147
+ now: Date.now
148
+ }
149
+ };
150
+ })() : void 0;
151
+ if (publication && !purge && !publication.cache.isPublishing(publication.cacheKey, Date.now())) {
152
+ const result = await getPublishedImage(publication.input);
153
+ if (result._tag === "Published" && result.expiresAt > Date.now()) {
154
+ publication.cache.remember(publication.cacheKey, result, Date.now());
155
+ const remainingAge = Math.max(0, Math.floor((result.expiresAt - Date.now()) / 1e3));
156
+ setHeader(e, "Cache-Control", `public, max-age=${remainingAge}, s-maxage=${remainingAge}`);
157
+ return sendRedirect(e, result.url, 302);
158
+ }
159
+ publication.cache.forget(publication.cacheKey);
160
+ if (result._tag === "Unavailable") {
161
+ warnPublishUnavailable(ctx._nitro, result.reason, logger);
162
+ publication = void 0;
163
+ }
164
+ }
128
165
  const endCacheLookup = timings.start("cache-lookup");
129
166
  const cacheApi = await useOgImageBufferCache(ctx, {
130
167
  cacheMaxAgeSeconds: ctx.options.cacheMaxAgeSeconds,
131
168
  baseCacheKey,
132
- purge: purgeRequest._tag === "Authorized"
169
+ purge
133
170
  }).finally(endCacheLookup);
134
171
  if (typeof cacheApi === "undefined") {
135
172
  return;
136
173
  }
174
+ if (publication && purge)
175
+ publication.cache.forget(publication.cacheKey);
137
176
  let image = cacheApi.cachedItem;
138
177
  if (image) {
139
178
  timings.record("cache-hit", 0);
@@ -172,5 +211,31 @@ async function renderOgImage(e, ctx) {
172
211
  setBuildCachedImage(ctx.options, extension, image, ctx.options.cacheMaxAgeSeconds);
173
212
  }
174
213
  }
214
+ if (publication) {
215
+ const maxAge = Number(ctx.options.cacheMaxAgeSeconds);
216
+ const expiresAt = cacheApi.expiresAt || Date.now() + (Number.isFinite(maxAge) ? Math.max(0, maxAge) : 0) * 1e3;
217
+ const remainingAge = Math.max(0, (expiresAt - Date.now()) / 1e3);
218
+ const { cache, cacheKey, input } = publication;
219
+ const token = cache.begin(cacheKey, Date.now(), input.timeoutMs);
220
+ if (token) {
221
+ const bytes = new Uint8Array(image);
222
+ const app = ctx._nitro;
223
+ const task = publishImage({
224
+ ...input,
225
+ maxAgeSeconds: remainingAge,
226
+ expiresAt,
227
+ force: true,
228
+ render: async () => bytes
229
+ }).then((result) => {
230
+ cache.complete(cacheKey, token, result, Date.now());
231
+ if (result._tag === "Unavailable")
232
+ warnPublishUnavailable(app, result.reason, logger);
233
+ }).catch((reason) => {
234
+ cache.complete(cacheKey, token, { _tag: "Unavailable" }, Date.now());
235
+ warnPublishUnavailable(app, reason, logger);
236
+ });
237
+ e.waitUntil(task);
238
+ }
239
+ }
175
240
  return image;
176
241
  }
@@ -1,7 +1,7 @@
1
1
  import { $fetch } from "ofetch";
2
2
  import { fetchWithEvent } from "#nuxtseo/nitro";
3
- import { getNitroOrigin } from "#site-config/server/composables";
4
3
  import { tryCloudflareAssetsFetch } from "./cloudflareAssets.js";
4
+ import { getOgImageOrigin } from "./origin.js";
5
5
  export async function fetchLocalAsset(event, path, options) {
6
6
  const { fetchTimeout, headers, includeExternalFallback = false, onStepFailure } = options;
7
7
  const deadline = AbortSignal.timeout(fetchTimeout);
@@ -30,7 +30,7 @@ export async function fetchLocalAsset(event, path, options) {
30
30
  }));
31
31
  if (result || expired || !includeExternalFallback)
32
32
  return result;
33
- const absolute = `${getNitroOrigin(event)}${path}`;
33
+ const absolute = `${getOgImageOrigin(event)}${path}`;
34
34
  return await race($fetch(absolute, {
35
35
  responseType: "arrayBuffer",
36
36
  signal: deadline,
@@ -0,0 +1,3 @@
1
+ import type { RequestEvent } from 'nuxt/server';
2
+ /** Site Config captures the request origin before renderer and cache hooks run. */
3
+ export declare function getOgImageOrigin(event: Pick<RequestEvent, 'context'>): string;
@@ -0,0 +1,4 @@
1
+ import { getNitroOrigin } from "#site-config/server/composables";
2
+ export function getOgImageOrigin(event) {
3
+ return getNitroOrigin({ context: event.context });
4
+ }
@@ -0,0 +1,6 @@
1
+ import type { OgImageRenderEventContext } from '../../types.js';
2
+ export declare function warnPublishUnavailable(app: OgImageRenderEventContext['_nitro'] & {
3
+ _ogImagePublishWarned?: boolean;
4
+ }, reason: unknown, logger: {
5
+ warn: (message: string, reason: unknown) => void;
6
+ }): void;
@@ -0,0 +1,6 @@
1
+ export function warnPublishUnavailable(app, reason, logger) {
2
+ if (app._ogImagePublishWarned)
3
+ return;
4
+ app._ogImagePublishWarned = true;
5
+ logger.warn("[Nuxt OG Image] Publish storage is unavailable. Keeping app image URLs. Check the storage driver and credentials.", reason);
6
+ }
@@ -1,8 +1,8 @@
1
- import type { H3Event } from '#nuxtseo/h3';
1
+ import type { RequestEvent } from 'nuxt/server';
2
2
  import type { OgImageOptionsInternal, OgImageRuntimeConfig } from '../types.js';
3
3
  export interface GetOgImagePathResult {
4
4
  path: string;
5
5
  hash?: string;
6
6
  }
7
- export declare function getOgImagePath(event: H3Event, _pagePath: string, _options?: Partial<OgImageOptionsInternal>): GetOgImagePathResult;
8
- export declare function useOgImageRuntimeConfig(e?: H3Event): OgImageRuntimeConfig;
7
+ export declare function getOgImagePath(event: Pick<RequestEvent, 'context'>, _pagePath: string, _options?: Partial<OgImageOptionsInternal>): GetOgImagePathResult;
8
+ export declare function useOgImageRuntimeConfig(e?: Pick<RequestEvent, 'context'>): OgImageRuntimeConfig;
@@ -1,10 +1,9 @@
1
+ import { useRuntimeConfig } from "nuxt/server";
1
2
  import { joinURL } from "ufo";
2
- import { useRuntimeConfig } from "#nuxtseo/nitro";
3
3
  import { componentNames } from "#og-image-virtual/component-names.mjs";
4
4
  import { buildOgImageUrl } from "../shared.js";
5
- import { getCloudflareEnv } from "./util/cloudflare.js";
6
5
  export function getOgImagePath(event, _pagePath, _options) {
7
- const baseURL = useRuntimeConfig(event).app.baseURL;
6
+ const baseURL = useRuntimeConfig().app.baseURL;
8
7
  const { defaults, security } = useOgImageRuntimeConfig(event);
9
8
  const extension = _options?.extension || defaults.extension;
10
9
  const isStatic = import.meta.prerender && !(security?.secret && security?.strict);
@@ -20,15 +19,11 @@ export function getOgImagePath(event, _pagePath, _options) {
20
19
  };
21
20
  }
22
21
  export function useOgImageRuntimeConfig(e) {
23
- const c = useRuntimeConfig(e);
22
+ const c = useRuntimeConfig();
24
23
  const moduleCfg = c["nuxt-og-image"];
25
- const cloudflareEnv = getCloudflareEnv(e);
26
- const runtimeSecret = c.ogImage?.secret;
27
- const cloudflareSecret = cloudflareEnv?.NUXT_OG_IMAGE_SECRET;
28
- const overrideSecret = typeof runtimeSecret === "string" && runtimeSecret ? runtimeSecret : typeof cloudflareSecret === "string" ? cloudflareSecret : void 0;
29
- const security = overrideSecret ? { ...moduleCfg.security || {}, secret: overrideSecret } : moduleCfg.security;
24
+ const secret = e?.context._ogImageSigningSecret;
25
+ const security = secret ? { ...moduleCfg.security, secret } : moduleCfg.security;
30
26
  return {
31
- defaults: {},
32
27
  ...moduleCfg,
33
28
  security,
34
29
  app: {
@@ -0,0 +1,13 @@
1
+ interface PublishConfig {
2
+ storage: string;
3
+ baseURL: string;
4
+ }
5
+ export declare function parsePublishConfig(input: unknown): {
6
+ _tag: 'Ok';
7
+ value: PublishConfig;
8
+ } | {
9
+ _tag: 'Err';
10
+ reason: string;
11
+ };
12
+ export declare function hasPublishMount(mount: string, storage: Record<string, unknown>): boolean;
13
+ export {};
@@ -0,0 +1,17 @@
1
+ import { normalizeKey } from "unstorage";
2
+ export function parsePublishConfig(input) {
3
+ if (!input || typeof input !== "object")
4
+ return { _tag: "Err", reason: "Set publish.storage and publish.baseURL." };
5
+ const config = input;
6
+ if (typeof config.storage !== "string" || !config.storage.trim() || !normalizeKey(config.storage))
7
+ return { _tag: "Err", reason: "Set publish.storage to a Nitro storage mount name." };
8
+ if (typeof config.baseURL !== "string" || !URL.canParse(config.baseURL))
9
+ return { _tag: "Err", reason: "Set publish.baseURL to the public HTTP URL for uploaded images." };
10
+ const url = new URL(config.baseURL);
11
+ if (!["https:", "http:"].includes(url.protocol) || url.username || url.password || url.href.includes("?") || url.href.includes("#"))
12
+ return { _tag: "Err", reason: "Set publish.baseURL to an HTTP URL without credentials, query, or fragment." };
13
+ return { _tag: "Ok", value: { storage: normalizeKey(config.storage), baseURL: url.href.replace(/\/+$/, "") } };
14
+ }
15
+ export function hasPublishMount(mount, storage) {
16
+ return Object.keys(storage).some((key) => normalizeKey(key) === normalizeKey(mount));
17
+ }
@@ -9,6 +9,8 @@ const RE_UNDERSCORE = /_/g;
9
9
  const RE_DOUBLE_UNDERSCORE = /__/g;
10
10
  const RE_PERCENT20 = /%20/g;
11
11
  const RE_PLUS = /\+/g;
12
+ const RE_ENCODED_COMMA = /%2c/gi;
13
+ const RE_ENCODED_PLUS = /%2b/gi;
12
14
  const RE_SINGLE_UNDERSCORE = /(?<!_)_(?!_)/;
13
15
  const RE_OG_PATH_PREFIX = /^\/_og\/[ds]\//;
14
16
  const RE_OG_ROUTE_PREFIX = /\/_og\/[ds]\//;
@@ -263,9 +265,12 @@ export function buildOgImageUrl(options, extension = "png", isStatic = false, de
263
265
  const segment = encoded || "default";
264
266
  const signed = secret && !isStatic ? `${segment},s_${signEncodedParams(segment, secret)}` : segment;
265
267
  return {
266
- url: `${prefix}/${signed}.${extension}`
268
+ url: `${prefix}/${signed.replace(/,/g, "%2C").replace(RE_PLUS, "%2B")}.${extension}`
267
269
  };
268
270
  }
271
+ function normalizeUrlSegment(segment) {
272
+ return segment.replace(RE_ENCODED_COMMA, ",").replace(RE_ENCODED_PLUS, "+");
273
+ }
269
274
  export function signEncodedParams(encoded, secret) {
270
275
  return digest(`${secret}:${encoded}`).slice(0, 16);
271
276
  }
@@ -283,7 +288,7 @@ export function parseOgImageUrl(url) {
283
288
  const path = url.replace(RE_OG_PATH_PREFIX, "");
284
289
  const extMatch = path.match(RE_FILE_EXTENSION_WITH_CAPTURE);
285
290
  const extension = extMatch?.[1] || "png";
286
- const encoded = path.replace(RE_FILE_EXTENSION, "");
291
+ const encoded = normalizeUrlSegment(path.replace(RE_FILE_EXTENSION, ""));
287
292
  const hashMatch = encoded.match(RE_HASH_SEGMENT);
288
293
  if (hashMatch) {
289
294
  return {
@@ -303,7 +308,7 @@ export function parseOgImageUrl(url) {
303
308
  export function extractEncodedSegment(path, extension) {
304
309
  const match = path.match(RE_OG_ROUTE_PREFIX);
305
310
  if (match?.index != null) {
306
- return path.slice(match.index + match[0].length).replace(new RegExp(`\\.${extension}$`), "");
311
+ return normalizeUrlSegment(path.slice(match.index + match[0].length).replace(new RegExp(`\\.${extension}$`), ""));
307
312
  }
308
- return path.split("/").pop().replace(new RegExp(`\\.${extension}$`), "");
313
+ return normalizeUrlSegment(path.split("/").pop().replace(new RegExp(`\\.${extension}$`), ""));
309
314
  }
@@ -41,16 +41,21 @@ export interface OgImageRuntimeConfig {
41
41
  debug: boolean;
42
42
  /** Whether twitter:* meta tags are emitted alongside og:image tags */
43
43
  includeTwitter: boolean;
44
- baseCacheKey: string;
44
+ baseCacheKey: string | false;
45
45
  hasNuxtIcon: boolean;
46
46
  hasNuxtContent?: boolean;
47
47
  colorPreference: 'light' | 'dark';
48
- isNuxtContentDocumentDriven: boolean;
49
48
  zeroRuntime: boolean;
50
49
  cssFramework: 'tailwind' | 'unocss' | 'none';
51
50
  componentDirs?: string[];
52
51
  /** Directory for persistent build cache (CI caching) */
53
52
  buildCacheDir?: string;
53
+ /** Publish rendered images to a public storage mount. */
54
+ publish?: {
55
+ storage: string;
56
+ baseURL: string;
57
+ cacheVersion: string;
58
+ };
54
59
  /** Source directory for auto-eject (dev only) */
55
60
  srcDir?: string;
56
61
  /** Root directory for relative path display (dev only) */
@@ -69,7 +74,7 @@ export interface OgImageRuntimeConfig {
69
74
  imageFetchTimeout: number;
70
75
  maxQueryParamSize: number | null;
71
76
  restrictRuntimeImagesToOrigin: false | string[];
72
- secret: string;
77
+ secret: string | false;
73
78
  strict: boolean;
74
79
  };
75
80
  app: {
@@ -164,15 +169,6 @@ export interface OgImageOptions {
164
169
  src: string;
165
170
  data: ArrayBuffer | Uint8Array;
166
171
  }>;
167
- fetchedResources?: Array<{
168
- src: string;
169
- data: ArrayBuffer | Uint8Array;
170
- }>;
171
- /** @deprecated Use `images` instead. */
172
- persistentImages?: Array<{
173
- src: string;
174
- data: ArrayBuffer;
175
- }>;
176
172
  devicePixelRatio?: number;
177
173
  };
178
174
  /** @deprecated Legacy font override — no longer used at runtime */
@@ -208,6 +204,8 @@ export interface OgImageOptions {
208
204
  * Extends OgImageOptions with fields set by defineOgImage() and the module internals.
209
205
  */
210
206
  export interface OgImageOptionsInternal extends OgImageOptions {
207
+ /** Completed page content supplied during prerender publishing. */
208
+ _prerenderHtml?: string;
211
209
  /** Set by defineOgImage() — the resolved component PascalName */
212
210
  component?: string;
213
211
  /** Determined by component filename suffix (.satori.vue, .takumi.vue, .browser.vue) */
@@ -246,10 +244,7 @@ export interface RuntimeCompatibilitySchema {
246
244
  fetch?: 'node' | 'web';
247
245
  wasm?: any;
248
246
  }
249
- export interface RuntimeCompatibilityMeta {
250
- takumiVersion?: 1 | 2;
251
- }
252
- export type RuntimeCompatibilityPayload = Partial<Omit<RuntimeCompatibilitySchema, 'wasm'>> & RuntimeCompatibilityMeta;
247
+ export type RuntimeCompatibilityPayload = Partial<Omit<RuntimeCompatibilitySchema, 'wasm'>>;
253
248
  export type CompatibilityFlags = Partial<Omit<RuntimeCompatibilitySchema, 'wasm'>>;
254
249
  export interface CompatibilityFlagEnvOverrides {
255
250
  dev?: CompatibilityFlags;