nuxt-og-image 6.10.2 → 7.0.0
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 +10 -14
- package/dist/chunks/tw4.mjs +6 -6
- package/dist/chunks/uno.mjs +7 -7
- package/dist/cli.mjs +4 -4
- package/dist/devtools/components/og-image/RendererSelectModal.vue +1 -1
- package/dist/devtools/lib/og-image/fonts.ts +38 -0
- package/dist/devtools/lib/og-image/types.ts +7 -0
- package/dist/devtools/pages/og-image/index.vue +19 -14
- package/dist/module.d.mts +14 -10
- package/dist/module.d.ts +14 -10
- package/dist/module.json +2 -2
- package/dist/module.mjs +6 -6
- package/dist/runtime/app/client-utils.js +7 -4
- package/dist/runtime/app/components/Templates/Community/SaaS.satori.vue +1 -1
- package/dist/runtime/app/components/Templates/Community/SimpleBlog.satori.vue +1 -1
- package/dist/runtime/app/disabled/components.d.ts +1 -0
- package/dist/runtime/app/disabled/components.js +0 -0
- package/dist/runtime/app/disabled/composables/defineOgImage.d.ts +1 -0
- package/dist/runtime/app/disabled/composables/defineOgImage.js +1 -0
- package/dist/runtime/app/disabled/composables/defineOgImageComponent.d.ts +1 -0
- package/dist/runtime/app/disabled/composables/defineOgImageComponent.js +1 -0
- package/dist/runtime/app/disabled/composables/defineOgImageScreenshot.d.ts +1 -0
- package/dist/runtime/app/disabled/composables/defineOgImageScreenshot.js +1 -0
- package/dist/runtime/app/disabled/composables/mock.d.ts +1 -0
- package/dist/runtime/app/disabled/composables/mock.js +1 -0
- package/dist/runtime/app/disabled/index.d.ts +3 -0
- package/dist/runtime/app/disabled/index.js +3 -0
- package/dist/runtime/app/index.d.ts +4 -0
- package/dist/runtime/app/index.js +4 -0
- package/dist/runtime/app/utils/plugins.js +1 -1
- package/dist/runtime/app/utils.js +2 -2
- package/dist/runtime/server/index.d.ts +1 -0
- package/dist/runtime/server/index.js +1 -0
- package/dist/runtime/server/middleware/signing.d.ts +2 -0
- package/dist/runtime/server/middleware/signing.js +19 -0
- package/dist/runtime/server/nitro.d.ts +3 -3
- package/dist/runtime/server/nitro.js +4 -4
- package/dist/runtime/server/og-image/bindings/font-assets/dev-prerender.js +8 -49
- package/dist/runtime/server/og-image/bindings/font-assets/node.js +3 -2
- package/dist/runtime/server/og-image/bindings/satori/node.d.ts +1 -2
- package/dist/runtime/server/og-image/bindings/satori/wasm-fs.d.ts +1 -2
- package/dist/runtime/server/og-image/bindings/satori/wasm-fs.js +1 -1
- package/dist/runtime/server/og-image/bindings/satori/wasm.d.ts +1 -2
- package/dist/runtime/server/og-image/bindings/satori/wasm.js +1 -1
- package/dist/runtime/server/og-image/browser/screenshot.js +5 -3
- package/dist/runtime/server/og-image/cache/publish.d.ts +43 -0
- package/dist/runtime/server/og-image/cache/publish.js +91 -0
- package/dist/runtime/server/og-image/cache/published.d.ts +17 -0
- package/dist/runtime/server/og-image/cache/published.js +49 -0
- package/dist/runtime/server/og-image/context.js +1 -1
- package/dist/runtime/server/og-image/core/plugins/imageSrc.js +2 -5
- package/dist/runtime/server/og-image/core/transforms/emojis/index.d.ts +3 -2
- package/dist/runtime/server/og-image/core/vnodes.js +19 -1
- package/dist/runtime/server/og-image/font-source.d.ts +1 -0
- package/dist/runtime/server/og-image/font-source.js +1 -0
- package/dist/runtime/server/og-image/fonts.d.ts +1 -1
- package/dist/runtime/server/og-image/fonts.js +1 -1
- package/dist/runtime/server/og-image/satori/filters.d.ts +1 -0
- package/dist/runtime/server/og-image/satori/filters.js +14 -0
- package/dist/runtime/server/og-image/satori/instances.d.ts +1 -2
- package/dist/runtime/server/og-image/satori/plugins/classes.js +0 -7
- package/dist/runtime/server/og-image/satori/renderer.js +2 -1
- package/dist/runtime/server/og-image/satori/vnodes.js +1 -4
- package/dist/runtime/server/og-image/takumi/renderer.js +11 -47
- package/dist/runtime/server/og-image/utils/css.d.ts +0 -5
- package/dist/runtime/server/og-image/utils/css.js +0 -5
- package/dist/runtime/server/plugins/auto-eject-nitro3.d.ts +2 -0
- package/dist/runtime/server/plugins/auto-eject-nitro3.js +9 -0
- package/dist/runtime/server/plugins/auto-eject.js +3 -31
- package/dist/runtime/server/plugins/prerender.js +68 -2
- package/dist/runtime/server/plugins/publish.d.ts +2 -0
- package/dist/runtime/server/plugins/publish.js +44 -0
- package/dist/runtime/server/routes/debug.json.d.ts +10 -1
- package/dist/runtime/server/routes/debug.json.js +4 -4
- package/dist/runtime/server/routes/resolve.js +2 -2
- package/dist/runtime/server/routes/static-font.d.ts +2 -0
- package/dist/runtime/server/routes/static-font.js +22 -0
- package/dist/runtime/server/signing-secret.d.ts +8 -0
- package/dist/runtime/server/signing-secret.js +75 -0
- package/dist/runtime/server/util/auto-eject-lifecycle.d.ts +13 -0
- package/dist/runtime/server/util/auto-eject-lifecycle.js +31 -0
- package/dist/runtime/server/util/cache.d.ts +1 -0
- package/dist/runtime/server/util/cache.js +12 -6
- package/dist/runtime/server/util/cloudflare.d.ts +2 -2
- package/dist/runtime/server/util/eventHandlers.js +69 -3
- package/dist/runtime/server/util/fetchLocalAsset.js +2 -2
- package/dist/runtime/server/util/origin.d.ts +3 -0
- package/dist/runtime/server/util/origin.js +4 -0
- package/dist/runtime/server/util/publishWarnings.d.ts +6 -0
- package/dist/runtime/server/util/publishWarnings.js +6 -0
- package/dist/runtime/server/utils.d.ts +3 -3
- package/dist/runtime/server/utils.js +5 -10
- package/dist/runtime/shared/publish.d.ts +13 -0
- package/dist/runtime/shared/publish.js +17 -0
- package/dist/runtime/shared/urlEncoding.js +9 -4
- package/dist/runtime/types.d.ts +11 -16
- package/dist/shared/{nuxt-og-image.Bcegsloy.mjs → nuxt-og-image.DR_SxdDv.mjs} +1224 -1109
- package/package.json +60 -62
- package/skills/nuxt-og-image/SKILL.md +31 -14
- package/types/virtual.d.ts +8 -0
- package/dist/runtime/server/og-image/satori/plugins/emojis.d.ts +0 -2
- package/dist/runtime/server/og-image/satori/plugins/emojis.js +0 -112
- package/dist/runtime/server/og-image/satori/plugins/flex.d.ts +0 -2
- package/dist/runtime/server/og-image/satori/plugins/flex.js +0 -48
|
@@ -1,12 +1,17 @@
|
|
|
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";
|
|
14
|
+
import { getEventQuery } from "./query.js";
|
|
10
15
|
export async function imageEventHandler(e) {
|
|
11
16
|
const reqStart = performance.now();
|
|
12
17
|
const ctx = await resolveContext(e).catch((err) => {
|
|
@@ -29,7 +34,8 @@ export async function imageEventHandler(e) {
|
|
|
29
34
|
async function renderOgImage(e, ctx) {
|
|
30
35
|
const timings = ctx.timings;
|
|
31
36
|
const { isDevToolsContextRequest, extension, renderer } = ctx;
|
|
32
|
-
const
|
|
37
|
+
const config = useOgImageRuntimeConfig(e);
|
|
38
|
+
const { debug, baseCacheKey, security, publish } = config;
|
|
33
39
|
if (!import.meta.prerender && !import.meta.dev && security?.restrictRuntimeImagesToOrigin) {
|
|
34
40
|
const requestHost = getRequestHost(e, { xForwardedHost: true });
|
|
35
41
|
let requestHostname;
|
|
@@ -116,11 +122,43 @@ async function renderOgImage(e, ctx) {
|
|
|
116
122
|
timings.record("cache-hit", 0);
|
|
117
123
|
return buildCachedImage;
|
|
118
124
|
}
|
|
125
|
+
const purge = typeof getEventQuery(e).purge !== "undefined";
|
|
126
|
+
let publication = publish && !import.meta.dev && !import.meta.prerender ? (() => {
|
|
127
|
+
const key = getPublishKey(new URL(e.path, getSiteConfig(e).url).href, config.defaults, publish.cacheVersion);
|
|
128
|
+
return {
|
|
129
|
+
cache: getPublishedImageCache(ctx._nitro),
|
|
130
|
+
cacheKey: getPublishedImageCacheKey(publish, key, extension),
|
|
131
|
+
input: {
|
|
132
|
+
storage: useStorage(),
|
|
133
|
+
mount: publish.storage,
|
|
134
|
+
baseURL: publish.baseURL,
|
|
135
|
+
key,
|
|
136
|
+
extension,
|
|
137
|
+
maxAgeSeconds: Number(ctx.options.cacheMaxAgeSeconds),
|
|
138
|
+
timeoutMs: security.renderTimeout,
|
|
139
|
+
now: Date.now
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
})() : void 0;
|
|
143
|
+
if (publication && !purge && !publication.cache.isPublishing(publication.cacheKey, Date.now())) {
|
|
144
|
+
const result = await getPublishedImage(publication.input);
|
|
145
|
+
if (result._tag === "Published" && result.expiresAt > Date.now()) {
|
|
146
|
+
publication.cache.remember(publication.cacheKey, result, Date.now());
|
|
147
|
+
const remainingAge = Math.max(0, Math.floor((result.expiresAt - Date.now()) / 1e3));
|
|
148
|
+
setHeader(e, "Cache-Control", `public, max-age=${remainingAge}, s-maxage=${remainingAge}`);
|
|
149
|
+
return sendRedirect(e, result.url, 302);
|
|
150
|
+
}
|
|
151
|
+
publication.cache.forget(publication.cacheKey);
|
|
152
|
+
if (result._tag === "Unavailable") {
|
|
153
|
+
warnPublishUnavailable(ctx._nitro, result.reason, logger);
|
|
154
|
+
publication = void 0;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
119
157
|
const endCacheLookup = timings.start("cache-lookup");
|
|
120
158
|
const cacheApi = await useOgImageBufferCache(ctx, {
|
|
121
159
|
cacheMaxAgeSeconds: ctx.options.cacheMaxAgeSeconds,
|
|
122
160
|
baseCacheKey,
|
|
123
|
-
secret: security?.secret
|
|
161
|
+
secret: security?.secret || void 0
|
|
124
162
|
}).finally(endCacheLookup);
|
|
125
163
|
if (typeof cacheApi === "undefined") {
|
|
126
164
|
return;
|
|
@@ -128,6 +166,8 @@ async function renderOgImage(e, ctx) {
|
|
|
128
166
|
if (cacheApi instanceof H3Error) {
|
|
129
167
|
return cacheApi;
|
|
130
168
|
}
|
|
169
|
+
if (publication && purge)
|
|
170
|
+
publication.cache.forget(publication.cacheKey);
|
|
131
171
|
let image = cacheApi.cachedItem;
|
|
132
172
|
if (image) {
|
|
133
173
|
timings.record("cache-hit", 0);
|
|
@@ -166,5 +206,31 @@ async function renderOgImage(e, ctx) {
|
|
|
166
206
|
setBuildCachedImage(ctx.options, extension, image, ctx.options.cacheMaxAgeSeconds);
|
|
167
207
|
}
|
|
168
208
|
}
|
|
209
|
+
if (publication) {
|
|
210
|
+
const maxAge = Number(ctx.options.cacheMaxAgeSeconds);
|
|
211
|
+
const expiresAt = cacheApi.expiresAt || Date.now() + (Number.isFinite(maxAge) ? Math.max(0, maxAge) : 0) * 1e3;
|
|
212
|
+
const remainingAge = Math.max(0, (expiresAt - Date.now()) / 1e3);
|
|
213
|
+
const { cache, cacheKey, input } = publication;
|
|
214
|
+
const token = cache.begin(cacheKey, Date.now(), input.timeoutMs);
|
|
215
|
+
if (token) {
|
|
216
|
+
const bytes = new Uint8Array(image);
|
|
217
|
+
const app = ctx._nitro;
|
|
218
|
+
const task = publishImage({
|
|
219
|
+
...input,
|
|
220
|
+
maxAgeSeconds: remainingAge,
|
|
221
|
+
expiresAt,
|
|
222
|
+
force: true,
|
|
223
|
+
render: async () => bytes
|
|
224
|
+
}).then((result) => {
|
|
225
|
+
cache.complete(cacheKey, token, result, Date.now());
|
|
226
|
+
if (result._tag === "Unavailable")
|
|
227
|
+
warnPublishUnavailable(app, result.reason, logger);
|
|
228
|
+
}).catch((reason) => {
|
|
229
|
+
cache.complete(cacheKey, token, { _tag: "Unavailable" }, Date.now());
|
|
230
|
+
warnPublishUnavailable(app, reason, logger);
|
|
231
|
+
});
|
|
232
|
+
e.waitUntil(task);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
169
235
|
return image;
|
|
170
236
|
}
|
|
@@ -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 = `${
|
|
33
|
+
const absolute = `${getOgImageOrigin(event)}${path}`;
|
|
34
34
|
return await race($fetch(absolute, {
|
|
35
35
|
responseType: "arrayBuffer",
|
|
36
36
|
signal: deadline,
|
|
@@ -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 {
|
|
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:
|
|
8
|
-
export declare function useOgImageRuntimeConfig(e?:
|
|
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(
|
|
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(
|
|
22
|
+
const c = useRuntimeConfig();
|
|
24
23
|
const moduleCfg = c["nuxt-og-image"];
|
|
25
|
-
const
|
|
26
|
-
const
|
|
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]\//;
|
|
@@ -260,9 +262,12 @@ export function buildOgImageUrl(options, extension = "png", isStatic = false, de
|
|
|
260
262
|
const segment = encoded || "default";
|
|
261
263
|
const signed = secret && !isStatic ? `${segment},s_${signEncodedParams(segment, secret)}` : segment;
|
|
262
264
|
return {
|
|
263
|
-
url: `${prefix}/${signed}.${extension}`
|
|
265
|
+
url: `${prefix}/${signed.replace(/,/g, "%2C").replace(RE_PLUS, "%2B")}.${extension}`
|
|
264
266
|
};
|
|
265
267
|
}
|
|
268
|
+
function normalizeUrlSegment(segment) {
|
|
269
|
+
return segment.replace(RE_ENCODED_COMMA, ",").replace(RE_ENCODED_PLUS, "+");
|
|
270
|
+
}
|
|
266
271
|
export function signEncodedParams(encoded, secret) {
|
|
267
272
|
return digest(`${secret}:${encoded}`).slice(0, 16);
|
|
268
273
|
}
|
|
@@ -280,7 +285,7 @@ export function parseOgImageUrl(url) {
|
|
|
280
285
|
const path = url.replace(RE_OG_PATH_PREFIX, "");
|
|
281
286
|
const extMatch = path.match(RE_FILE_EXTENSION_WITH_CAPTURE);
|
|
282
287
|
const extension = extMatch?.[1] || "png";
|
|
283
|
-
const encoded = path.replace(RE_FILE_EXTENSION, "");
|
|
288
|
+
const encoded = normalizeUrlSegment(path.replace(RE_FILE_EXTENSION, ""));
|
|
284
289
|
const hashMatch = encoded.match(RE_HASH_SEGMENT);
|
|
285
290
|
if (hashMatch) {
|
|
286
291
|
return {
|
|
@@ -300,7 +305,7 @@ export function parseOgImageUrl(url) {
|
|
|
300
305
|
export function extractEncodedSegment(path, extension) {
|
|
301
306
|
const match = path.match(RE_OG_ROUTE_PREFIX);
|
|
302
307
|
if (match?.index != null) {
|
|
303
|
-
return path.slice(match.index + match[0].length).replace(new RegExp(`\\.${extension}$`), "");
|
|
308
|
+
return normalizeUrlSegment(path.slice(match.index + match[0].length).replace(new RegExp(`\\.${extension}$`), ""));
|
|
304
309
|
}
|
|
305
|
-
return path.split("/").pop().replace(new RegExp(`\\.${extension}$`), "");
|
|
310
|
+
return normalizeUrlSegment(path.split("/").pop().replace(new RegExp(`\\.${extension}$`), ""));
|
|
306
311
|
}
|
package/dist/runtime/types.d.ts
CHANGED
|
@@ -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
|
|
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;
|