nuxt-og-image 6.7.4 → 6.7.5

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 (37) hide show
  1. package/dist/chunks/tw4.cjs +1 -1
  2. package/dist/chunks/tw4.mjs +1 -1
  3. package/dist/chunks/uno.cjs +1 -1
  4. package/dist/chunks/uno.mjs +1 -1
  5. package/dist/cli.cjs +8 -2
  6. package/dist/cli.mjs +8 -2
  7. package/dist/devtools/lib/og-image/rpc.ts +4 -1
  8. package/dist/module.cjs +1 -1
  9. package/dist/module.json +2 -2
  10. package/dist/module.mjs +1 -1
  11. package/dist/runtime/app/plugins/og-image-canonical-urls.server.d.ts +2 -1
  12. package/dist/runtime/app/plugins/og-image-canonical-urls.server.js +3 -1
  13. package/dist/runtime/app/plugins/route-rule-og-image.server.d.ts +2 -1
  14. package/dist/runtime/app/plugins/route-rule-og-image.server.js +3 -1
  15. package/dist/runtime/logger.js +2 -6
  16. package/dist/runtime/pure.d.ts +0 -1
  17. package/dist/runtime/pure.js +0 -5
  18. package/dist/runtime/server/og-image/bindings/browser/cloudflare.d.ts +0 -1
  19. package/dist/runtime/server/og-image/bindings/browser/cloudflare.js +2 -9
  20. package/dist/runtime/server/og-image/bindings/font-assets/dev-prerender.js +25 -11
  21. package/dist/runtime/server/og-image/bindings/font-assets/external-url.js +3 -1
  22. package/dist/runtime/server/og-image/bindings/font-assets/node.js +3 -1
  23. package/dist/runtime/server/og-image/fonts.js +3 -1
  24. package/dist/runtime/server/util/cloudflare.d.ts +3 -0
  25. package/dist/runtime/server/util/cloudflare.js +17 -0
  26. package/dist/runtime/server/util/cloudflareAssets.js +8 -5
  27. package/dist/runtime/server/util/encoding.d.ts +0 -1
  28. package/dist/runtime/server/util/encoding.js +0 -7
  29. package/dist/runtime/server/util/kit.d.ts +0 -1
  30. package/dist/runtime/server/util/kit.js +0 -1
  31. package/dist/runtime/server/util/logger.js +2 -6
  32. package/dist/runtime/server/util/timings.d.ts +0 -3
  33. package/dist/runtime/server/util/timings.js +0 -3
  34. package/dist/runtime/server/utils.js +6 -3
  35. package/dist/shared/{nuxt-og-image.BRBtdkUp.cjs → nuxt-og-image.Cctpuv4O.cjs} +57 -47
  36. package/dist/shared/{nuxt-og-image.Bv8VSGTj.mjs → nuxt-og-image.D3mV8OQ9.mjs} +56 -46
  37. package/package.json +33 -35
@@ -4,7 +4,7 @@ const promises = require('node:fs/promises');
4
4
  const node_url = require('node:url');
5
5
  const exsolve = require('exsolve');
6
6
  const pathe = require('pathe');
7
- const module$1 = require('../shared/nuxt-og-image.BRBtdkUp.cjs');
7
+ const module$1 = require('../shared/nuxt-og-image.Cctpuv4O.cjs');
8
8
  require('node:crypto');
9
9
  require('node:fs');
10
10
  require('@nuxt/kit');
@@ -2,7 +2,7 @@ import { readFile } from 'node:fs/promises';
2
2
  import { pathToFileURL } from 'node:url';
3
3
  import { resolveModulePath } from 'exsolve';
4
4
  import { dirname, join } from 'pathe';
5
- import { e as extractVariantBaseClasses, r as resolveVariantPrefixes, h as resolveExtractedVars, i as resolveVarsDeep, s as simplifyCss, p as postProcessStyles, l as loadLightningCss, a as extractCssVars, c as extractUniversalVars, d as extractPerClassVars, g as extractVarsFromCss, f as extractClassStyles } from '../shared/nuxt-og-image.Bv8VSGTj.mjs';
5
+ import { e as extractVariantBaseClasses, r as resolveVariantPrefixes, h as resolveExtractedVars, i as resolveVarsDeep, s as simplifyCss, p as postProcessStyles, l as loadLightningCss, a as extractCssVars, c as extractUniversalVars, d as extractPerClassVars, g as extractVarsFromCss, f as extractClassStyles } from '../shared/nuxt-og-image.D3mV8OQ9.mjs';
6
6
  import 'node:crypto';
7
7
  import 'node:fs';
8
8
  import '@nuxt/kit';
@@ -3,7 +3,7 @@
3
3
  const promises = require('node:fs/promises');
4
4
  const defu = require('defu');
5
5
  const logger_js = require('../../dist/runtime/logger.js');
6
- const module$1 = require('../shared/nuxt-og-image.BRBtdkUp.cjs');
6
+ const module$1 = require('../shared/nuxt-og-image.Cctpuv4O.cjs');
7
7
  require('node:crypto');
8
8
  require('node:fs');
9
9
  require('node:url');
@@ -1,7 +1,7 @@
1
1
  import { readFile } from 'node:fs/promises';
2
2
  import { defu } from 'defu';
3
3
  import { logger } from '../../dist/runtime/logger.js';
4
- import { e as extractVariantBaseClasses, s as simplifyCss, a as extractCssVars, b as extractPropertyInitialValues, c as extractUniversalVars, d as extractPerClassVars, f as extractClassStyles, p as postProcessStyles, r as resolveVariantPrefixes, g as extractVarsFromCss, h as resolveExtractedVars } from '../shared/nuxt-og-image.Bv8VSGTj.mjs';
4
+ import { e as extractVariantBaseClasses, s as simplifyCss, a as extractCssVars, b as extractPropertyInitialValues, c as extractUniversalVars, d as extractPerClassVars, f as extractClassStyles, p as postProcessStyles, r as resolveVariantPrefixes, g as extractVarsFromCss, h as resolveExtractedVars } from '../shared/nuxt-og-image.D3mV8OQ9.mjs';
5
5
  import 'node:crypto';
6
6
  import 'node:fs';
7
7
  import 'node:url';
package/dist/cli.cjs CHANGED
@@ -364,7 +364,10 @@ async function checkNuxtConfig(rootDir) {
364
364
  const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
365
365
  hasNuxtFontsInPkg = !!(pkg.dependencies?.["@nuxt/fonts"] || pkg.devDependencies?.["@nuxt/fonts"]);
366
366
  }
367
- const config = await kit.loadNuxtConfig({ cwd: rootDir }).catch(() => null);
367
+ const config = await kit.loadNuxtConfig({ cwd: rootDir }).catch((error) => {
368
+ p__namespace.log.warn(`Could not inspect Nuxt config: ${error.message}`);
369
+ return null;
370
+ });
368
371
  if (!config)
369
372
  return { hasDeprecatedFonts: false, hasNuxtFonts: hasNuxtFontsInPkg, hasDefaultsComponent: false, defaultComponentName: null, nitroPreset: null, deprecatedConfigKeys: [] };
370
373
  const ogImageConfig = config.ogImage;
@@ -545,7 +548,10 @@ function migrateV6Components(componentsToRename, defaultRenderer, dryRun) {
545
548
  }
546
549
  }
547
550
  async function detectDeploymentTarget(rootDir) {
548
- const config = await kit.loadNuxtConfig({ cwd: rootDir }).catch(() => null);
551
+ const config = await kit.loadNuxtConfig({ cwd: rootDir }).catch((error) => {
552
+ p__namespace.log.warn(`Could not detect deployment target: ${error.message}`);
553
+ return null;
554
+ });
549
555
  return config?.nitro?.preset || null;
550
556
  }
551
557
  async function installRendererDeps(renderers, isEdge) {
package/dist/cli.mjs CHANGED
@@ -347,7 +347,10 @@ async function checkNuxtConfig(rootDir) {
347
347
  const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
348
348
  hasNuxtFontsInPkg = !!(pkg.dependencies?.["@nuxt/fonts"] || pkg.devDependencies?.["@nuxt/fonts"]);
349
349
  }
350
- const config = await loadNuxtConfig({ cwd: rootDir }).catch(() => null);
350
+ const config = await loadNuxtConfig({ cwd: rootDir }).catch((error) => {
351
+ p.log.warn(`Could not inspect Nuxt config: ${error.message}`);
352
+ return null;
353
+ });
351
354
  if (!config)
352
355
  return { hasDeprecatedFonts: false, hasNuxtFonts: hasNuxtFontsInPkg, hasDefaultsComponent: false, defaultComponentName: null, nitroPreset: null, deprecatedConfigKeys: [] };
353
356
  const ogImageConfig = config.ogImage;
@@ -528,7 +531,10 @@ function migrateV6Components(componentsToRename, defaultRenderer, dryRun) {
528
531
  }
529
532
  }
530
533
  async function detectDeploymentTarget(rootDir) {
531
- const config = await loadNuxtConfig({ cwd: rootDir }).catch(() => null);
534
+ const config = await loadNuxtConfig({ cwd: rootDir }).catch((error) => {
535
+ p.log.warn(`Could not detect deployment target: ${error.message}`);
536
+ return null;
537
+ });
532
538
  return config?.nitro?.preset || null;
533
539
  }
534
540
  async function installRendererDeps(renderers, isEdge) {
@@ -17,7 +17,10 @@ export const isFallbackMode = computed(() => connectionState.value === 'fallback
17
17
  // Fallback fetch for localhost:3000
18
18
  async function tryFallbackConnection() {
19
19
  const fallbackUrl = 'http://localhost:3000'
20
- const res = await fetch(`${fallbackUrl}/_og/debug.json`).catch(() => null)
20
+ const res = await fetch(`${fallbackUrl}/_og/debug.json`).catch(() => {
21
+ // An unreachable fallback host means the devtools connection has failed.
22
+ return null
23
+ })
21
24
  if (res?.ok) {
22
25
  appFetch.value = ((url: string, opts?: any) => fetch(`${fallbackUrl}${url}`, opts).then(r => r.json())) as any
23
26
  base.value = '/'
package/dist/module.cjs CHANGED
@@ -11,7 +11,7 @@ require('nuxt-site-config/kit');
11
11
  require('pathe');
12
12
  require('pkg-types');
13
13
  require('std-env');
14
- const module$1 = require('./shared/nuxt-og-image.BRBtdkUp.cjs');
14
+ const module$1 = require('./shared/nuxt-og-image.Cctpuv4O.cjs');
15
15
  require('nuxtseo-shared/kit');
16
16
  require('../dist/runtime/logger.js');
17
17
  require('oxc-walker');
package/dist/module.json CHANGED
@@ -4,9 +4,9 @@
4
4
  "nuxt": ">=3.16.0"
5
5
  },
6
6
  "configKey": "ogImage",
7
- "version": "6.7.4",
7
+ "version": "6.7.5",
8
8
  "builder": {
9
- "@nuxt/module-builder": "1.0.2",
9
+ "@nuxt/module-builder": "1.0.3",
10
10
  "unbuild": "3.6.1"
11
11
  }
12
12
  }
package/dist/module.mjs CHANGED
@@ -9,7 +9,7 @@ import 'nuxt-site-config/kit';
9
9
  import 'pathe';
10
10
  import 'pkg-types';
11
11
  import 'std-env';
12
- export { m as default } from './shared/nuxt-og-image.Bv8VSGTj.mjs';
12
+ export { m as default } from './shared/nuxt-og-image.D3mV8OQ9.mjs';
13
13
  import 'nuxtseo-shared/kit';
14
14
  import '../dist/runtime/logger.js';
15
15
  import 'oxc-walker';
@@ -1 +1,2 @@
1
- export { ogImageCanonicalUrls as default } from '../utils/plugins.js';
1
+ declare const _default: import("nuxt/app").Plugin<Record<string, unknown>> & import("nuxt/app").ObjectPlugin<Record<string, unknown>>;
2
+ export default _default;
@@ -1 +1,3 @@
1
- export { ogImageCanonicalUrls as default } from "../utils/plugins.js";
1
+ import { defineNuxtPlugin } from "#app";
2
+ import { ogImageCanonicalUrls } from "../utils/plugins.js";
3
+ export default defineNuxtPlugin((nuxtApp) => ogImageCanonicalUrls(nuxtApp));
@@ -1 +1,2 @@
1
- export { routeRuleOgImage as default } from '../utils/plugins.js';
1
+ declare const _default: import("nuxt/app").Plugin<Record<string, unknown>> & import("nuxt/app").ObjectPlugin<Record<string, unknown>>;
2
+ export default _default;
@@ -1 +1,3 @@
1
- export { routeRuleOgImage as default } from "../utils/plugins.js";
1
+ import { defineNuxtPlugin } from "#app";
2
+ import { routeRuleOgImage } from "../utils/plugins.js";
3
+ export default defineNuxtPlugin((nuxtApp) => routeRuleOgImage(nuxtApp));
@@ -1,8 +1,4 @@
1
- import { createConsola } from "consola";
2
1
  import { colorize } from "consola/utils";
3
- export const logger = createConsola({
4
- defaults: {
5
- tag: "@nuxtjs/og-image"
6
- }
7
- });
2
+ import { createModuleLogger } from "nuxtseo-shared/utils";
3
+ export const logger = createModuleLogger("@nuxtjs/og-image");
8
4
  export const gray = (s) => colorize("gray", s);
@@ -3,4 +3,3 @@ export declare function extractSocialPreviewTags(html: string): [Record<string,
3
3
  export declare function detectBase64MimeType(data: string): string;
4
4
  export declare function toBase64Image(data: string | ArrayBuffer): string;
5
5
  export declare function withoutQuery(path: string): string | undefined;
6
- export declare function getExtension(path: string): string;
@@ -65,8 +65,3 @@ export function toBase64Image(data) {
65
65
  export function withoutQuery(path) {
66
66
  return path.split("?")[0];
67
67
  }
68
- export function getExtension(path) {
69
- path = withoutQuery(path);
70
- const lastSegment = path.split("/").pop() || path;
71
- return lastSegment.split(".").pop() || lastSegment;
72
- }
@@ -6,5 +6,4 @@ interface Browser {
6
6
  on: (event: string, handler: () => void) => void;
7
7
  }
8
8
  export declare function createBrowser(event?: H3Event): Promise<Browser>;
9
- export declare function disposeBrowser(): Promise<void>;
10
9
  export {};
@@ -1,3 +1,4 @@
1
+ import { getCloudflareEnv } from "../../../util/cloudflare.js";
1
2
  import { withTimeout } from "../../../util/withTimeout.js";
2
3
  import { useOgImageRuntimeConfig } from "../../../utils.js";
3
4
  let puppeteer;
@@ -20,7 +21,7 @@ export async function createBrowser(event) {
20
21
  "[Nuxt OG Image] Browser binding name not configured. Set `ogImage.browser.binding` in nuxt.config."
21
22
  );
22
23
  }
23
- const binding = event?.context?.cloudflare?.env?.[bindingName];
24
+ const binding = getCloudflareEnv(event)?.[bindingName];
24
25
  if (!binding) {
25
26
  throw new Error(
26
27
  `[Nuxt OG Image] Cloudflare browser binding "${bindingName}" not found. Ensure it's configured in wrangler.toml and the request has cloudflare context.`
@@ -45,11 +46,3 @@ export async function createBrowser(event) {
45
46
  browserPromise = null;
46
47
  return browser;
47
48
  }
48
- export async function disposeBrowser() {
49
- if (browser) {
50
- await browser.close().catch((err) => {
51
- void err;
52
- });
53
- browser = null;
54
- }
55
- }
@@ -10,11 +10,23 @@ import { fetchWithRedirectValidation } from "../../../util/ssrf.js";
10
10
  import { useOgImageRuntimeConfig } from "../../../utils.js";
11
11
  import { fetchSpecialFontUrl, isDataFontUrl, isExternalFontUrl } from "./external-url.js";
12
12
  let fontUrlMapping;
13
+ async function readOptionalFile(path) {
14
+ return readFile(path).catch((error) => {
15
+ if (error.code === "ENOENT")
16
+ return null;
17
+ throw error;
18
+ });
19
+ }
20
+ async function fetchOptionalFont(url, timeout) {
21
+ return fetch(url, { signal: AbortSignal.timeout(timeout) }).catch(() => {
22
+ return null;
23
+ });
24
+ }
13
25
  async function loadFontUrlMapping() {
14
26
  if (fontUrlMapping)
15
27
  return fontUrlMapping;
16
- const content = await readFile(join(buildDir, "cache", "og-image", "font-urls.json"), "utf-8").catch(() => null);
17
- fontUrlMapping = content ? JSON.parse(content) : {};
28
+ const content = await readOptionalFile(join(buildDir, "cache", "og-image", "font-urls.json"));
29
+ fontUrlMapping = content ? JSON.parse(content.toString("utf-8")) : {};
18
30
  return fontUrlMapping;
19
31
  }
20
32
  export async function resolve(event, font) {
@@ -22,7 +34,7 @@ export async function resolve(event, font) {
22
34
  const runtimeConfig = useOgImageRuntimeConfig();
23
35
  const timeout = getFetchTimeout(runtimeConfig);
24
36
  if (font.absolutePath) {
25
- const data = await readFile(font.absolutePath).catch(() => null);
37
+ const data = await readOptionalFile(font.absolutePath);
26
38
  if (data?.length)
27
39
  return data;
28
40
  }
@@ -31,31 +43,31 @@ export async function resolve(event, font) {
31
43
  if (import.meta.prerender) {
32
44
  if (path.startsWith("/_og-static-fonts/")) {
33
45
  const filename2 = path.slice("/_og-static-fonts/".length);
34
- const cached = await readFile(join(buildDir, "cache", "og-image", "fonts-ttf", filename2)).catch(() => null) || await readFile(join(rootDir, ".output", "public", "_og-static-fonts", filename2)).catch(() => null);
46
+ const cached = await readOptionalFile(join(buildDir, "cache", "og-image", "fonts-ttf", filename2)) || await readOptionalFile(join(rootDir, ".output", "public", "_og-static-fonts", filename2));
35
47
  if (cached?.length)
36
48
  return cached;
37
49
  }
38
50
  if (path.startsWith("/_fonts/")) {
39
51
  const filename2 = path.slice("/_fonts/".length);
40
- const cached = await readFile(join(rootDir, ".output", "public", "_fonts", filename2)).catch(() => null);
52
+ const cached = await readOptionalFile(join(rootDir, ".output", "public", "_fonts", filename2));
41
53
  if (cached?.length)
42
54
  return cached;
43
55
  const mapping = await loadFontUrlMapping();
44
56
  if (mapping[filename2]) {
45
- const res = await fetch(mapping[filename2], { signal: AbortSignal.timeout(timeout) }).catch(() => null);
57
+ const res = await fetchOptionalFont(mapping[filename2], timeout);
46
58
  if (res?.ok)
47
59
  return Buffer.from(await res.arrayBuffer());
48
60
  }
49
61
  throw new Error(`Font ${filename2} not found in mapping or cache`);
50
62
  }
51
63
  const filename = path.slice(1);
52
- const data = await readFile(join(rootDir, "public", filename)).catch(() => null) || await readFile(join(rootDir, ".output", "public", filename)).catch(() => null);
64
+ const data = await readOptionalFile(join(rootDir, "public", filename)) || await readOptionalFile(join(rootDir, ".output", "public", filename));
53
65
  if (data?.length)
54
66
  return data;
55
67
  }
56
68
  if (path.startsWith("/_og-static-fonts/")) {
57
69
  const filename = path.slice("/_og-static-fonts/".length);
58
- const cached = await readFile(join(buildDir, "cache", "og-image", "fonts-ttf", filename)).catch(() => null);
70
+ const cached = await readOptionalFile(join(buildDir, "cache", "og-image", "fonts-ttf", filename));
59
71
  if (cached?.length)
60
72
  return cached;
61
73
  }
@@ -63,14 +75,14 @@ export async function resolve(event, font) {
63
75
  const filename = path.slice("/_fonts/".length);
64
76
  const mapping = await loadFontUrlMapping();
65
77
  if (mapping[filename]) {
66
- const res = await fetch(mapping[filename], { signal: AbortSignal.timeout(timeout) }).catch(() => null);
78
+ const res = await fetchOptionalFont(mapping[filename], timeout);
67
79
  if (res?.ok)
68
80
  return Buffer.from(await res.arrayBuffer());
69
81
  }
70
82
  }
71
83
  if (import.meta.dev) {
72
84
  const filename = path.slice(1);
73
- const data = await readFile(join(rootDir, "public", filename)).catch(() => null);
85
+ const data = await readOptionalFile(join(rootDir, "public", filename));
74
86
  if (data?.length)
75
87
  return data;
76
88
  }
@@ -79,7 +91,9 @@ export async function resolve(event, font) {
79
91
  const reqUrl = getRequestURL(event);
80
92
  const origin = `${reqUrl.protocol}//${reqUrl.host}`;
81
93
  const target = new URL(withBase(path, app.baseURL), origin);
82
- const ab = await fetchWithRedirectValidation(target.href, { timeout, trustedHost: target.host }).catch(() => null);
94
+ const ab = await fetchWithRedirectValidation(target.href, { timeout, trustedHost: target.host }).catch(() => {
95
+ return null;
96
+ });
83
97
  if (ab) {
84
98
  return Buffer.from(ab);
85
99
  }
@@ -32,7 +32,9 @@ export function resolveSameOriginFontUrl(path, siteUrl) {
32
32
  }
33
33
  export async function fetchSpecialFontUrl(path, siteUrl, timeout) {
34
34
  if (isDataFontUrl(path)) {
35
- const res = await fetch(path.trimStart(), { signal: AbortSignal.timeout(timeout) }).catch(() => null);
35
+ const res = await fetch(path.trimStart(), { signal: AbortSignal.timeout(timeout) }).catch(() => {
36
+ return null;
37
+ });
36
38
  if (res?.ok)
37
39
  return Buffer.from(await res.arrayBuffer());
38
40
  throw new Error("[Nuxt OG Image] Invalid data: font URL.");
@@ -15,7 +15,9 @@ export async function resolve(event, font) {
15
15
  if (path && (isDataFontUrl(path) || isExternalFontUrl(path)))
16
16
  return fetchSpecialFontUrl(path, getSiteConfig(event).url, timeout);
17
17
  const target = new URL(fullPath, origin);
18
- const ab = await fetchWithRedirectValidation(target.href, { timeout, trustedHost: target.host }).catch(() => null);
18
+ const ab = await fetchWithRedirectValidation(target.href, { timeout, trustedHost: target.host }).catch(() => {
19
+ return null;
20
+ });
19
21
  if (ab) {
20
22
  return Buffer.from(ab);
21
23
  }
@@ -198,7 +198,9 @@ export async function loadDefinedFonts(event, fontDefs) {
198
198
  const weight = normalizeFontWeight(def.weight);
199
199
  const style = def.style === "italic" ? "italic" : "normal";
200
200
  const fontConfig = { family: name, weight, style, src: path, localPath: path };
201
- const data = await resolve(event.e, fontConfig).catch(() => null);
201
+ const data = await resolve(event.e, fontConfig).catch(() => {
202
+ return null;
203
+ });
202
204
  if (data) {
203
205
  results.push({
204
206
  ...fontConfig,
@@ -0,0 +1,3 @@
1
+ import type { H3Event } from 'h3';
2
+ export type CloudflareEnv = Record<string, unknown>;
3
+ export declare function getCloudflareEnv(event?: H3Event): CloudflareEnv | undefined;
@@ -0,0 +1,17 @@
1
+ function toRecord(value) {
2
+ return typeof value === "object" && value !== null ? value : void 0;
3
+ }
4
+ export function getCloudflareEnv(event) {
5
+ const runtime = event && "runtime" in event ? toRecord(event.runtime) : void 0;
6
+ const runtimeCloudflare = toRecord(runtime?.cloudflare);
7
+ const runtimeEnv = toRecord(runtimeCloudflare?.env);
8
+ if (runtimeEnv)
9
+ return runtimeEnv;
10
+ const contextCloudflare = toRecord(event?.context.cloudflare);
11
+ const contextEnv = toRecord(contextCloudflare?.env);
12
+ if (contextEnv)
13
+ return contextEnv;
14
+ const platform = toRecord(event?.context._platform);
15
+ const platformCloudflare = toRecord(platform?.cloudflare);
16
+ return toRecord(platformCloudflare?.env);
17
+ }
@@ -1,15 +1,18 @@
1
- import { getRequestHost } from "h3";
1
+ import { getRequestURL } from "h3";
2
+ import { getCloudflareEnv } from "./cloudflare.js";
2
3
  export function getCloudflareAssets(event) {
3
- const assets = event.context.cloudflare?.env?.ASSETS || event.context.ASSETS;
4
- return assets && typeof assets.fetch === "function" ? assets : void 0;
4
+ const assets = getCloudflareEnv(event)?.ASSETS || event.context.ASSETS;
5
+ return typeof assets === "object" && assets !== null && "fetch" in assets && typeof assets.fetch === "function" ? assets : void 0;
5
6
  }
6
7
  export async function tryCloudflareAssetsFetch(event, path, signal) {
7
8
  const assets = getCloudflareAssets(event);
8
9
  if (!assets)
9
10
  return;
10
- const origin = event.context.cloudflare?.request?.url || `https://${getRequestHost(event) || "localhost"}`;
11
+ const origin = getRequestURL(event).origin;
11
12
  const url = new URL(path, origin).href;
12
- const res = await assets.fetch(url, signal ? { signal } : void 0).catch(() => null);
13
+ const res = await assets.fetch(url, signal ? { signal } : void 0).catch(() => {
14
+ return null;
15
+ });
13
16
  if (!res || !res.ok)
14
17
  return;
15
18
  return res.arrayBuffer();
@@ -1,3 +1,2 @@
1
1
  export declare function htmlDecodeQuotes(html: string): string;
2
2
  export declare function decodeHtml(html: string): string;
3
- export declare function decodeObjectHtmlEntities(obj: Record<string, string | any>): Record<string, any>;
@@ -20,10 +20,3 @@ export function decodeHtml(html) {
20
20
  return String.fromCharCode(Number.parseInt(int));
21
21
  }).replace(RE_AMP, "&");
22
22
  }
23
- export function decodeObjectHtmlEntities(obj) {
24
- Object.entries(obj).forEach(([key, value]) => {
25
- if (typeof value === "string")
26
- obj[key] = decodeHtml(value);
27
- });
28
- return obj;
29
- }
@@ -1,6 +1,5 @@
1
1
  import type { H3Event } from 'h3';
2
2
  import type { NitroRouteRules } from 'nitropack';
3
3
  import type { NuxtIslandResponse } from 'nuxt/app';
4
- export { withoutQuery } from 'nuxtseo-shared/utils';
5
4
  export declare function fetchIsland(e: H3Event, component: string, props: Record<string, any>, timeout?: number): Promise<NuxtIslandResponse>;
6
5
  export declare function createNitroRouteRuleMatcher(): ((path: string) => NitroRouteRules);
@@ -3,7 +3,6 @@ import { useRuntimeConfig } from "nitropack/runtime";
3
3
  import { createRouter as createRadixRouter, toRouteMatcher } from "radix3";
4
4
  import { withoutBase, withoutTrailingSlash } from "ufo";
5
5
  import { getIslandHash } from "#og-image/island-hash";
6
- export { withoutQuery } from "nuxtseo-shared/utils";
7
6
  export function fetchIsland(e, component, props, timeout) {
8
7
  const hashId = getIslandHash({ name: component, props });
9
8
  const signal = timeout ? AbortSignal.timeout(timeout) : void 0;
@@ -1,6 +1,2 @@
1
- import { createConsola } from "consola";
2
- export const logger = createConsola({
3
- defaults: {
4
- tag: "Nuxt OG Image"
5
- }
6
- });
1
+ import { createModuleLogger } from "nuxtseo-shared/utils";
2
+ export const logger = createModuleLogger("Nuxt OG Image");
@@ -12,6 +12,3 @@ export interface Timings {
12
12
  }
13
13
  export declare function createTimings(): Timings;
14
14
  export declare const TIMING_CTX_KEY = "_ogImageTimings";
15
- export declare function getTimingsFromEvent(e: {
16
- context: Record<string, any>;
17
- }): Timings | undefined;
@@ -70,6 +70,3 @@ export function createTimings() {
70
70
  return { start, record, measure, entries, header };
71
71
  }
72
72
  export const TIMING_CTX_KEY = "_ogImageTimings";
73
- export function getTimingsFromEvent(e) {
74
- return e.context[TIMING_CTX_KEY];
75
- }
@@ -2,6 +2,7 @@ import { useRuntimeConfig } from "nitropack/runtime";
2
2
  import { joinURL } from "ufo";
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";
5
6
  export function getOgImagePath(_pagePath, _options) {
6
7
  const baseURL = useRuntimeConfig().app.baseURL;
7
8
  const { defaults, security } = useOgImageRuntimeConfig();
@@ -20,9 +21,11 @@ export function getOgImagePath(_pagePath, _options) {
20
21
  }
21
22
  export function useOgImageRuntimeConfig(e) {
22
23
  const c = useRuntimeConfig(e);
23
- const moduleCfg = c["nuxt-og-image"] || {};
24
- const cloudflareEnv = e?.context.cloudflare?.env || e?.context?._platform?.cloudflare?.env;
25
- const overrideSecret = c.ogImage?.secret || cloudflareEnv?.NUXT_OG_IMAGE_SECRET;
24
+ 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;
26
29
  const security = overrideSecret ? { ...moduleCfg.security || {}, secret: overrideSecret } : moduleCfg.security;
27
30
  return {
28
31
  defaults: {},
@@ -62,7 +62,9 @@ function checkLocalChrome() {
62
62
  return hasChromeLocally;
63
63
  }
64
64
  async function hasResolvableDependency(dep) {
65
- return await kit.resolvePath(dep, { fallbackToOriginal: true }).catch(() => null).then((r) => r && r !== dep);
65
+ return await kit.resolvePath(dep, { fallbackToOriginal: true }).catch(() => {
66
+ return null;
67
+ }).then((r) => r && r !== dep);
66
68
  }
67
69
  const VALID_RENDERER_SUFFIXES = ["satori", "browser", "takumi"];
68
70
  const RE_RENDERER_SUFFIX_CI = /\.?(satori|browser|takumi)$/i;
@@ -913,7 +915,6 @@ const RE_QUOTES = /^['"]|['"]$/g;
913
915
  const RE_WIDTH_VALUE = /width:([^;}]+)/;
914
916
  const RE_CALC_VAR_MULTIPLY = /calc\(var\((--[\w-]+)\)\s*\*\s*([\d.]+)\)/;
915
917
  const RE_NUMERIC_WITH_UNIT = /([\d.]+)(rem|px|em|%)/;
916
- const RE_EXTREME_VALUE = /^(-?[\d.]+e\+?\d+)(px|rem|em|%)$/;
917
918
  const RE_CSS_KEYWORD = /^(?:initial|inherit|unset|revert|revert-layer)$/;
918
919
  const RE_UNRESOLVED_VAR = /var\((--[\w-]+)/g;
919
920
  const RE_INVALID_CALC = /calc\(\s*[*/]/;
@@ -1523,18 +1524,6 @@ function convertLogicalProperties(styles) {
1523
1524
  }
1524
1525
  }
1525
1526
  }
1526
- function clampExtremeValues(styles) {
1527
- for (const [prop, value] of Object.entries(styles)) {
1528
- if (!value.includes("e+") && !value.includes("e38"))
1529
- continue;
1530
- const match = value.match(RE_EXTREME_VALUE);
1531
- if (match?.[1] && match?.[2]) {
1532
- const num = Number.parseFloat(match[1]);
1533
- if (Math.abs(num) > 9999)
1534
- styles[prop] = `9999${match[2]}`;
1535
- }
1536
- }
1537
- }
1538
1527
  function stripGradientColorSpace(value) {
1539
1528
  return value.replace(css_js.GRADIENT_COLOR_SPACE_RE, "");
1540
1529
  }
@@ -1582,7 +1571,6 @@ async function postProcessStyles(rawStyles, vars, resolveVar, context) {
1582
1571
  }
1583
1572
  convertIndividualTransforms(styles);
1584
1573
  convertLogicalProperties(styles);
1585
- clampExtremeValues(styles);
1586
1574
  return Object.keys(styles).length ? styles : null;
1587
1575
  }
1588
1576
  function walkTemplateAst(nodes, visitor) {
@@ -1985,7 +1973,9 @@ async function parseFontsFromTemplate(nuxt, options) {
1985
1973
  async function downloadFontFile(url, destPath) {
1986
1974
  if (fs.existsSync(destPath))
1987
1975
  return true;
1988
- const res = await fetch(url).catch(() => null);
1976
+ const res = await fetch(url).catch(() => {
1977
+ return null;
1978
+ });
1989
1979
  if (!res?.ok)
1990
1980
  return false;
1991
1981
  await promises.writeFile(destPath, Buffer.from(await res.arrayBuffer()));
@@ -2626,7 +2616,7 @@ const TreeShakeComposablesPlugin = unplugin.createUnplugin(() => {
2626
2616
  },
2627
2617
  transform(code, id) {
2628
2618
  const s = new MagicString__default(code);
2629
- if (id.endsWith("components.islands.mjs")) ; else {
2619
+ if (!id.endsWith("components.islands.mjs")) {
2630
2620
  const strippedCode = stripLiteral.stripLiteral(code);
2631
2621
  if (!COMPOSABLE_RE.test(code)) {
2632
2622
  return;
@@ -3223,7 +3213,9 @@ const iconCache = /* @__PURE__ */ new Map();
3223
3213
  async function loadIconSet(prefix) {
3224
3214
  if (iconCache.has(prefix))
3225
3215
  return iconCache.get(prefix);
3226
- const icons = await import(`@iconify-json/${prefix}/icons.json`, { with: { type: 'json' } }).then((m) => m.default).catch(() => null);
3216
+ const icons = await import(`@iconify-json/${prefix}/icons.json`, { with: { type: 'json' } }).then((m) => m.default).catch(() => {
3217
+ return null;
3218
+ });
3227
3219
  iconCache.set(prefix, icons);
3228
3220
  if (iconCache.size > 20)
3229
3221
  iconCache.delete(iconCache.keys().next().value);
@@ -3407,7 +3399,9 @@ const AssetTransformPlugin = unplugin.createUnplugin((options) => {
3407
3399
  let hasChanges = false;
3408
3400
  if (options.emojiSet && emojiUtils_js.RE_MATCH_EMOJIS.test(template)) {
3409
3401
  if (!emojiIcons) {
3410
- emojiIcons = options.emojiIcons ?? await import(`@iconify-json/${options.emojiSet}/icons.json`, { with: { type: 'json' } }).then((m) => m.default).catch(() => null);
3402
+ emojiIcons = options.emojiIcons ?? await import(`@iconify-json/${options.emojiSet}/icons.json`, { with: { type: 'json' } }).then((m) => m.default).catch(() => {
3403
+ return null;
3404
+ });
3411
3405
  }
3412
3406
  emojiUtils_js.RE_MATCH_EMOJIS.lastIndex = 0;
3413
3407
  const allEmojis = /* @__PURE__ */ new Set();
@@ -3697,7 +3691,9 @@ const AssetTransformPlugin = unplugin.createUnplugin((options) => {
3697
3691
  } else {
3698
3692
  continue;
3699
3693
  }
3700
- const fileBuffer = await promises.readFile(resolvedPath).catch(() => null);
3694
+ const fileBuffer = await promises.readFile(resolvedPath).catch(() => {
3695
+ return null;
3696
+ });
3701
3697
  if (!fileBuffer)
3702
3698
  continue;
3703
3699
  const mimeType = getMimeType(ext);
@@ -4081,7 +4077,6 @@ ${importStatements}
4081
4077
  const warnings = [];
4082
4078
  const counts = {
4083
4079
  config: /* @__PURE__ */ new Map(),
4084
- composable: /* @__PURE__ */ new Map(),
4085
4080
  component: /* @__PURE__ */ new Map()
4086
4081
  };
4087
4082
  let hasEmitted = false;
@@ -4103,13 +4098,6 @@ const REMOVED_CONFIG = {
4103
4098
  "defaults.renderer": "Removed (renderer determined by component filename suffix)",
4104
4099
  "defaults.component": "Removed (rename component to OgImage/Default.{renderer}.vue)"
4105
4100
  };
4106
- const DEPRECATED_COMPOSABLES$1 = {
4107
- defineOgImageComponent: "defineOgImage()",
4108
- defineOgImageStatic: "defineOgImage()",
4109
- defineOgImageDynamic: "defineOgImage()",
4110
- defineOgImageCached: "defineOgImage()",
4111
- defineOgImageWithoutCache: "defineOgImage()"
4112
- };
4113
4101
  function addWarning(warning) {
4114
4102
  const countMap = counts[warning.type];
4115
4103
  const current = countMap.get(warning.code) || 0;
@@ -4139,13 +4127,13 @@ function addComponentWarning(componentPath) {
4139
4127
  });
4140
4128
  }
4141
4129
  function hasWarnings() {
4142
- return warnings.length > 0 || counts.config.size > 0 || counts.composable.size > 0 || counts.component.size > 0;
4130
+ return warnings.length > 0 || counts.config.size > 0 || counts.component.size > 0;
4143
4131
  }
4144
4132
  function emitWarnings() {
4145
4133
  if (hasEmitted || !hasWarnings())
4146
4134
  return;
4147
4135
  hasEmitted = true;
4148
- const totalIssues = [...counts.config.values()].reduce((a, b) => a + b, 0) + [...counts.composable.values()].reduce((a, b) => a + b, 0) + [...counts.component.values()].reduce((a, b) => a + b, 0);
4136
+ const totalIssues = [...counts.config.values()].reduce((a, b) => a + b, 0) + [...counts.component.values()].reduce((a, b) => a + b, 0);
4149
4137
  const body = [
4150
4138
  formatWarnings(),
4151
4139
  "",
@@ -4182,17 +4170,6 @@ function formatWarnings() {
4182
4170
  }
4183
4171
  lines.push("");
4184
4172
  }
4185
- if (counts.composable.size > 0) {
4186
- lines.push("Deprecated composables:");
4187
- for (const [name, count] of counts.composable) {
4188
- const replacement = DEPRECATED_COMPOSABLES$1[name];
4189
- const suffix = count > 1 ? ` (\xD7${count})` : "";
4190
- lines.push(` \u2022 ${name}()${suffix}`);
4191
- if (replacement)
4192
- lines.push(` \u2192 Use: ${replacement}`);
4193
- }
4194
- lines.push("");
4195
- }
4196
4173
  if (counts.component.size > 0) {
4197
4174
  const componentCount = [...counts.component.values()].reduce((a, b) => a + b, 0);
4198
4175
  lines.push(`Components missing renderer suffix: ${componentCount}`);
@@ -4669,6 +4646,12 @@ declare module '#og-image-cache' {
4669
4646
  import type { OgImageOptions, OgImageRenderEventContext, VNode } from '${typesPath}'
4670
4647
 
4671
4648
  declare module 'nitropack' {
4649
+ interface NitroRuntimeConfig {
4650
+ 'nuxt-og-image': OgImageRuntimeConfig
4651
+ ogImage?: {
4652
+ secret?: string
4653
+ }
4654
+ }
4672
4655
  interface NitroRouteRules {
4673
4656
  ogImage?: false | OgImageOptions & Record<string, any>
4674
4657
  }
@@ -4682,6 +4665,12 @@ declare module 'nitropack' {
4682
4665
  }
4683
4666
 
4684
4667
  declare module 'nitropack/types' {
4668
+ interface NitroRuntimeConfig {
4669
+ 'nuxt-og-image': OgImageRuntimeConfig
4670
+ ogImage?: {
4671
+ secret?: string
4672
+ }
4673
+ }
4685
4674
  interface NitroRouteRules {
4686
4675
  ogImage?: false | OgImageOptions & Record<string, any>
4687
4676
  }
@@ -4694,6 +4683,15 @@ declare module 'nitropack/types' {
4694
4683
  }
4695
4684
  }
4696
4685
 
4686
+ declare module 'h3' {
4687
+ interface H3EventContext {
4688
+ _nitro?: {
4689
+ routeRules?: import('nitropack').NitroRouteRules
4690
+ }
4691
+ _ogImagePrerenderPaths?: Map<string, string>
4692
+ }
4693
+ }
4694
+
4697
4695
  export {}
4698
4696
  `;
4699
4697
  }
@@ -4705,14 +4703,16 @@ const RE_PASCAL_TO_KEBAB = /([a-z])([A-Z])/g;
4705
4703
  const RE_TILDE_PREFIX = /^~\//;
4706
4704
  const IS_MODULE_DEVELOPMENT = undefined.endsWith(".ts");
4707
4705
  async function findPackageVersionFromEntry(pkg, resolver) {
4708
- const entry = await resolver.resolvePath(pkg, { fallbackToOriginal: false }).catch(() => null);
4706
+ const entry = await resolver.resolvePath(pkg, { fallbackToOriginal: false }).catch(() => {
4707
+ return null;
4708
+ });
4709
4709
  if (!entry || entry === pkg)
4710
4710
  return;
4711
4711
  let dir = pathe.dirname(entry);
4712
4712
  while (dir && dir !== pathe.dirname(dir)) {
4713
4713
  const pkgPath = pathe.join(dir, "package.json");
4714
4714
  if (fs.existsSync(pkgPath)) {
4715
- const pkgJson = await pkgTypes.readPackageJSON(pkgPath).catch(() => null);
4715
+ const pkgJson = await pkgTypes.readPackageJSON(pkgPath);
4716
4716
  if (pkgJson?.name === pkg)
4717
4717
  return pkgJson.version;
4718
4718
  }
@@ -4790,7 +4790,7 @@ const module$1 = kit.defineNuxtModule({
4790
4790
  await onUpgrade(nuxt, options, previousVersion);
4791
4791
  },
4792
4792
  async setup(config, nuxt) {
4793
- const _resolver = kit.createResolver((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('shared/nuxt-og-image.BRBtdkUp.cjs', document.baseURI).href)));
4793
+ const _resolver = kit.createResolver((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('shared/nuxt-og-image.Cctpuv4O.cjs', document.baseURI).href)));
4794
4794
  const fixSharedPath = (p) => {
4795
4795
  return p.replace(/\/shared\/runtime(\/|$)/, "/runtime$1").replace(/\/shared\/client(\/|$)/, "/client$1").replace(/\/shared\/devtools(\/|$)/, "/devtools$1");
4796
4796
  };
@@ -4835,7 +4835,13 @@ const module$1 = kit.defineNuxtModule({
4835
4835
  if (!nuxt.options.dev || config.zeroRuntime || !hasServerRuntime)
4836
4836
  return;
4837
4837
  if (signing.optOut) {
4838
- logger_js.logger.warn("OG image URL signing is disabled (`security.secret: false`). Anyone can craft arbitrary image generation requests.");
4838
+ logger_js.logger.warn([
4839
+ "OG image URL signing is disabled (`security.secret: false`).",
4840
+ "Attackers can craft image requests and poison the cache so your real OG image URLs serve attacker-controlled content (content spoofing).",
4841
+ "Signing will be required in v7 whenever runtime image generation is enabled. Leave signing on, or set an explicit secret:",
4842
+ " NUXT_OG_IMAGE_SECRET=<secret>",
4843
+ " Generate one with: npx nuxt-og-image generate-secret"
4844
+ ].join("\n"));
4839
4845
  } else if (signing.generated) {
4840
4846
  logger_js.logger.warn([
4841
4847
  "OG image URLs are signed with an auto-generated secret that changes every build.",
@@ -4930,7 +4936,9 @@ Or pin to a specific version in package.json:
4930
4936
  const cssPath = typeof cssEntry === "string" ? cssEntry : cssEntry?.src;
4931
4937
  if (!cssPath || !cssPath.endsWith(".css"))
4932
4938
  continue;
4933
- const resolved = await resolver.resolvePath(cssPath).catch(() => null);
4939
+ const resolved = await resolver.resolvePath(cssPath).catch(() => {
4940
+ return null;
4941
+ });
4934
4942
  if (!resolved || !fs.existsSync(resolved))
4935
4943
  continue;
4936
4944
  return resolved;
@@ -5019,7 +5027,9 @@ Or pin to a specific version in package.json:
5019
5027
  const cssPath = typeof cssEntry === "string" ? cssEntry : cssEntry?.src;
5020
5028
  if (!cssPath || !cssPath.endsWith(".css"))
5021
5029
  continue;
5022
- const resolved = await resolver.resolvePath(cssPath).catch(() => null);
5030
+ const resolved = await resolver.resolvePath(cssPath).catch(() => {
5031
+ return null;
5032
+ });
5023
5033
  if (!resolved || !fs.existsSync(resolved))
5024
5034
  continue;
5025
5035
  const content = await promises.readFile(resolved, "utf-8");
@@ -42,7 +42,9 @@ function checkLocalChrome() {
42
42
  return hasChromeLocally;
43
43
  }
44
44
  async function hasResolvableDependency(dep) {
45
- return await resolvePath(dep, { fallbackToOriginal: true }).catch(() => null).then((r) => r && r !== dep);
45
+ return await resolvePath(dep, { fallbackToOriginal: true }).catch(() => {
46
+ return null;
47
+ }).then((r) => r && r !== dep);
46
48
  }
47
49
  const VALID_RENDERER_SUFFIXES = ["satori", "browser", "takumi"];
48
50
  const RE_RENDERER_SUFFIX_CI = /\.?(satori|browser|takumi)$/i;
@@ -893,7 +895,6 @@ const RE_QUOTES = /^['"]|['"]$/g;
893
895
  const RE_WIDTH_VALUE = /width:([^;}]+)/;
894
896
  const RE_CALC_VAR_MULTIPLY = /calc\(var\((--[\w-]+)\)\s*\*\s*([\d.]+)\)/;
895
897
  const RE_NUMERIC_WITH_UNIT = /([\d.]+)(rem|px|em|%)/;
896
- const RE_EXTREME_VALUE = /^(-?[\d.]+e\+?\d+)(px|rem|em|%)$/;
897
898
  const RE_CSS_KEYWORD = /^(?:initial|inherit|unset|revert|revert-layer)$/;
898
899
  const RE_UNRESOLVED_VAR = /var\((--[\w-]+)/g;
899
900
  const RE_INVALID_CALC = /calc\(\s*[*/]/;
@@ -1503,18 +1504,6 @@ function convertLogicalProperties(styles) {
1503
1504
  }
1504
1505
  }
1505
1506
  }
1506
- function clampExtremeValues(styles) {
1507
- for (const [prop, value] of Object.entries(styles)) {
1508
- if (!value.includes("e+") && !value.includes("e38"))
1509
- continue;
1510
- const match = value.match(RE_EXTREME_VALUE);
1511
- if (match?.[1] && match?.[2]) {
1512
- const num = Number.parseFloat(match[1]);
1513
- if (Math.abs(num) > 9999)
1514
- styles[prop] = `9999${match[2]}`;
1515
- }
1516
- }
1517
- }
1518
1507
  function stripGradientColorSpace(value) {
1519
1508
  return value.replace(GRADIENT_COLOR_SPACE_RE, "");
1520
1509
  }
@@ -1562,7 +1551,6 @@ async function postProcessStyles(rawStyles, vars, resolveVar, context) {
1562
1551
  }
1563
1552
  convertIndividualTransforms(styles);
1564
1553
  convertLogicalProperties(styles);
1565
- clampExtremeValues(styles);
1566
1554
  return Object.keys(styles).length ? styles : null;
1567
1555
  }
1568
1556
  function walkTemplateAst(nodes, visitor) {
@@ -1965,7 +1953,9 @@ async function parseFontsFromTemplate(nuxt, options) {
1965
1953
  async function downloadFontFile(url, destPath) {
1966
1954
  if (existsSync(destPath))
1967
1955
  return true;
1968
- const res = await fetch(url).catch(() => null);
1956
+ const res = await fetch(url).catch(() => {
1957
+ return null;
1958
+ });
1969
1959
  if (!res?.ok)
1970
1960
  return false;
1971
1961
  await writeFile(destPath, Buffer.from(await res.arrayBuffer()));
@@ -2606,7 +2596,7 @@ const TreeShakeComposablesPlugin = createUnplugin(() => {
2606
2596
  },
2607
2597
  transform(code, id) {
2608
2598
  const s = new MagicString(code);
2609
- if (id.endsWith("components.islands.mjs")) ; else {
2599
+ if (!id.endsWith("components.islands.mjs")) {
2610
2600
  const strippedCode = stripLiteral(code);
2611
2601
  if (!COMPOSABLE_RE.test(code)) {
2612
2602
  return;
@@ -3203,7 +3193,9 @@ const iconCache = /* @__PURE__ */ new Map();
3203
3193
  async function loadIconSet(prefix) {
3204
3194
  if (iconCache.has(prefix))
3205
3195
  return iconCache.get(prefix);
3206
- const icons = await import(`@iconify-json/${prefix}/icons.json`, { with: { type: 'json' } }).then((m) => m.default).catch(() => null);
3196
+ const icons = await import(`@iconify-json/${prefix}/icons.json`, { with: { type: 'json' } }).then((m) => m.default).catch(() => {
3197
+ return null;
3198
+ });
3207
3199
  iconCache.set(prefix, icons);
3208
3200
  if (iconCache.size > 20)
3209
3201
  iconCache.delete(iconCache.keys().next().value);
@@ -3387,7 +3379,9 @@ const AssetTransformPlugin = createUnplugin((options) => {
3387
3379
  let hasChanges = false;
3388
3380
  if (options.emojiSet && RE_MATCH_EMOJIS.test(template)) {
3389
3381
  if (!emojiIcons) {
3390
- emojiIcons = options.emojiIcons ?? await import(`@iconify-json/${options.emojiSet}/icons.json`, { with: { type: 'json' } }).then((m) => m.default).catch(() => null);
3382
+ emojiIcons = options.emojiIcons ?? await import(`@iconify-json/${options.emojiSet}/icons.json`, { with: { type: 'json' } }).then((m) => m.default).catch(() => {
3383
+ return null;
3384
+ });
3391
3385
  }
3392
3386
  RE_MATCH_EMOJIS.lastIndex = 0;
3393
3387
  const allEmojis = /* @__PURE__ */ new Set();
@@ -3677,7 +3671,9 @@ const AssetTransformPlugin = createUnplugin((options) => {
3677
3671
  } else {
3678
3672
  continue;
3679
3673
  }
3680
- const fileBuffer = await readFile(resolvedPath).catch(() => null);
3674
+ const fileBuffer = await readFile(resolvedPath).catch(() => {
3675
+ return null;
3676
+ });
3681
3677
  if (!fileBuffer)
3682
3678
  continue;
3683
3679
  const mimeType = getMimeType(ext);
@@ -4061,7 +4057,6 @@ ${importStatements}
4061
4057
  const warnings = [];
4062
4058
  const counts = {
4063
4059
  config: /* @__PURE__ */ new Map(),
4064
- composable: /* @__PURE__ */ new Map(),
4065
4060
  component: /* @__PURE__ */ new Map()
4066
4061
  };
4067
4062
  let hasEmitted = false;
@@ -4083,13 +4078,6 @@ const REMOVED_CONFIG = {
4083
4078
  "defaults.renderer": "Removed (renderer determined by component filename suffix)",
4084
4079
  "defaults.component": "Removed (rename component to OgImage/Default.{renderer}.vue)"
4085
4080
  };
4086
- const DEPRECATED_COMPOSABLES$1 = {
4087
- defineOgImageComponent: "defineOgImage()",
4088
- defineOgImageStatic: "defineOgImage()",
4089
- defineOgImageDynamic: "defineOgImage()",
4090
- defineOgImageCached: "defineOgImage()",
4091
- defineOgImageWithoutCache: "defineOgImage()"
4092
- };
4093
4081
  function addWarning(warning) {
4094
4082
  const countMap = counts[warning.type];
4095
4083
  const current = countMap.get(warning.code) || 0;
@@ -4119,13 +4107,13 @@ function addComponentWarning(componentPath) {
4119
4107
  });
4120
4108
  }
4121
4109
  function hasWarnings() {
4122
- return warnings.length > 0 || counts.config.size > 0 || counts.composable.size > 0 || counts.component.size > 0;
4110
+ return warnings.length > 0 || counts.config.size > 0 || counts.component.size > 0;
4123
4111
  }
4124
4112
  function emitWarnings() {
4125
4113
  if (hasEmitted || !hasWarnings())
4126
4114
  return;
4127
4115
  hasEmitted = true;
4128
- const totalIssues = [...counts.config.values()].reduce((a, b) => a + b, 0) + [...counts.composable.values()].reduce((a, b) => a + b, 0) + [...counts.component.values()].reduce((a, b) => a + b, 0);
4116
+ const totalIssues = [...counts.config.values()].reduce((a, b) => a + b, 0) + [...counts.component.values()].reduce((a, b) => a + b, 0);
4129
4117
  const body = [
4130
4118
  formatWarnings(),
4131
4119
  "",
@@ -4162,17 +4150,6 @@ function formatWarnings() {
4162
4150
  }
4163
4151
  lines.push("");
4164
4152
  }
4165
- if (counts.composable.size > 0) {
4166
- lines.push("Deprecated composables:");
4167
- for (const [name, count] of counts.composable) {
4168
- const replacement = DEPRECATED_COMPOSABLES$1[name];
4169
- const suffix = count > 1 ? ` (\xD7${count})` : "";
4170
- lines.push(` \u2022 ${name}()${suffix}`);
4171
- if (replacement)
4172
- lines.push(` \u2192 Use: ${replacement}`);
4173
- }
4174
- lines.push("");
4175
- }
4176
4153
  if (counts.component.size > 0) {
4177
4154
  const componentCount = [...counts.component.values()].reduce((a, b) => a + b, 0);
4178
4155
  lines.push(`Components missing renderer suffix: ${componentCount}`);
@@ -4649,6 +4626,12 @@ declare module '#og-image-cache' {
4649
4626
  import type { OgImageOptions, OgImageRenderEventContext, VNode } from '${typesPath}'
4650
4627
 
4651
4628
  declare module 'nitropack' {
4629
+ interface NitroRuntimeConfig {
4630
+ 'nuxt-og-image': OgImageRuntimeConfig
4631
+ ogImage?: {
4632
+ secret?: string
4633
+ }
4634
+ }
4652
4635
  interface NitroRouteRules {
4653
4636
  ogImage?: false | OgImageOptions & Record<string, any>
4654
4637
  }
@@ -4662,6 +4645,12 @@ declare module 'nitropack' {
4662
4645
  }
4663
4646
 
4664
4647
  declare module 'nitropack/types' {
4648
+ interface NitroRuntimeConfig {
4649
+ 'nuxt-og-image': OgImageRuntimeConfig
4650
+ ogImage?: {
4651
+ secret?: string
4652
+ }
4653
+ }
4665
4654
  interface NitroRouteRules {
4666
4655
  ogImage?: false | OgImageOptions & Record<string, any>
4667
4656
  }
@@ -4674,6 +4663,15 @@ declare module 'nitropack/types' {
4674
4663
  }
4675
4664
  }
4676
4665
 
4666
+ declare module 'h3' {
4667
+ interface H3EventContext {
4668
+ _nitro?: {
4669
+ routeRules?: import('nitropack').NitroRouteRules
4670
+ }
4671
+ _ogImagePrerenderPaths?: Map<string, string>
4672
+ }
4673
+ }
4674
+
4677
4675
  export {}
4678
4676
  `;
4679
4677
  }
@@ -4685,14 +4683,16 @@ const RE_PASCAL_TO_KEBAB = /([a-z])([A-Z])/g;
4685
4683
  const RE_TILDE_PREFIX = /^~\//;
4686
4684
  const IS_MODULE_DEVELOPMENT = import.meta.filename.endsWith(".ts");
4687
4685
  async function findPackageVersionFromEntry(pkg, resolver) {
4688
- const entry = await resolver.resolvePath(pkg, { fallbackToOriginal: false }).catch(() => null);
4686
+ const entry = await resolver.resolvePath(pkg, { fallbackToOriginal: false }).catch(() => {
4687
+ return null;
4688
+ });
4689
4689
  if (!entry || entry === pkg)
4690
4690
  return;
4691
4691
  let dir = dirname(entry);
4692
4692
  while (dir && dir !== dirname(dir)) {
4693
4693
  const pkgPath = join(dir, "package.json");
4694
4694
  if (existsSync(pkgPath)) {
4695
- const pkgJson = await readPackageJSON(pkgPath).catch(() => null);
4695
+ const pkgJson = await readPackageJSON(pkgPath);
4696
4696
  if (pkgJson?.name === pkg)
4697
4697
  return pkgJson.version;
4698
4698
  }
@@ -4815,7 +4815,13 @@ const module$1 = defineNuxtModule({
4815
4815
  if (!nuxt.options.dev || config.zeroRuntime || !hasServerRuntime)
4816
4816
  return;
4817
4817
  if (signing.optOut) {
4818
- logger.warn("OG image URL signing is disabled (`security.secret: false`). Anyone can craft arbitrary image generation requests.");
4818
+ logger.warn([
4819
+ "OG image URL signing is disabled (`security.secret: false`).",
4820
+ "Attackers can craft image requests and poison the cache so your real OG image URLs serve attacker-controlled content (content spoofing).",
4821
+ "Signing will be required in v7 whenever runtime image generation is enabled. Leave signing on, or set an explicit secret:",
4822
+ " NUXT_OG_IMAGE_SECRET=<secret>",
4823
+ " Generate one with: npx nuxt-og-image generate-secret"
4824
+ ].join("\n"));
4819
4825
  } else if (signing.generated) {
4820
4826
  logger.warn([
4821
4827
  "OG image URLs are signed with an auto-generated secret that changes every build.",
@@ -4910,7 +4916,9 @@ Or pin to a specific version in package.json:
4910
4916
  const cssPath = typeof cssEntry === "string" ? cssEntry : cssEntry?.src;
4911
4917
  if (!cssPath || !cssPath.endsWith(".css"))
4912
4918
  continue;
4913
- const resolved = await resolver.resolvePath(cssPath).catch(() => null);
4919
+ const resolved = await resolver.resolvePath(cssPath).catch(() => {
4920
+ return null;
4921
+ });
4914
4922
  if (!resolved || !existsSync(resolved))
4915
4923
  continue;
4916
4924
  return resolved;
@@ -4999,7 +5007,9 @@ Or pin to a specific version in package.json:
4999
5007
  const cssPath = typeof cssEntry === "string" ? cssEntry : cssEntry?.src;
5000
5008
  if (!cssPath || !cssPath.endsWith(".css"))
5001
5009
  continue;
5002
- const resolved = await resolver.resolvePath(cssPath).catch(() => null);
5010
+ const resolved = await resolver.resolvePath(cssPath).catch(() => {
5011
+ return null;
5012
+ });
5003
5013
  if (!resolved || !existsSync(resolved))
5004
5014
  continue;
5005
5015
  const content = await readFile(resolved, "utf-8");
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nuxt-og-image",
3
3
  "type": "module",
4
- "version": "6.7.4",
4
+ "version": "6.7.5",
5
5
  "description": "Enlightened OG Image generation for Nuxt.",
6
6
  "author": {
7
7
  "website": "https://harlanzw.com",
@@ -103,28 +103,27 @@
103
103
  },
104
104
  "dependencies": {
105
105
  "@clack/prompts": "^1.7.0",
106
- "@nuxt/kit": "^4.5.0",
106
+ "@nuxt/kit": "^4.5.1",
107
107
  "@unocss/config": "^66.7.5",
108
108
  "@unocss/core": "^66.7.5",
109
109
  "@vue/compiler-sfc": "^3.5.40",
110
110
  "chrome-launcher": "^1.2.1",
111
111
  "consola": "^3.4.2",
112
- "culori": "^4.0.2",
113
112
  "defu": "^6.1.7",
114
- "devalue": "^5.8.1",
115
- "exsolve": "^1.1.0",
116
- "fnv1a-64": "^0.1.1",
117
- "lightningcss": "^1.32.0",
118
- "magic-string": "^1.0.0",
113
+ "devalue": "^5.8.2",
114
+ "exsolve": "^1.1.1",
115
+ "fnv1a-64": "^0.1.2",
116
+ "lightningcss": "^1.33.0",
117
+ "magic-string": "^1.1.0",
119
118
  "magicast": "^0.5.3",
120
119
  "mocked-exports": "^0.1.1",
121
120
  "nuxt-site-config": "^4.1.2",
122
- "nuxtseo-shared": "^5.3.3",
121
+ "nuxtseo-shared": "^5.3.6",
123
122
  "nypm": "^0.6.8",
124
123
  "object-identity": "^0.2.3",
125
124
  "ofetch": "^1.5.1",
126
125
  "ohash": "^2.0.11",
127
- "oxc-parser": "^0.140.0",
126
+ "oxc-parser": "^0.142.0",
128
127
  "oxc-walker": "^1.0.0",
129
128
  "pathe": "^2.0.3",
130
129
  "pkg-types": "^2.3.1",
@@ -132,42 +131,41 @@
132
131
  "std-env": "^4.2.0",
133
132
  "strip-literal": "^3.1.0",
134
133
  "tinyexec": "^1.2.4",
135
- "tinyglobby": "^0.2.17",
136
134
  "ufo": "^1.6.4",
137
135
  "ultrahtml": "^1.7.0",
138
136
  "unplugin": "^3.3.0"
139
137
  },
140
138
  "devDependencies": {
141
- "@antfu/eslint-config": "^9.1.0",
139
+ "@antfu/eslint-config": "^9.2.0",
142
140
  "@fontsource/noto-sans-sc": "^5.3.0",
143
141
  "@iconify-json/carbon": "^1.2.24",
144
142
  "@iconify-json/logos": "^1.2.11",
145
143
  "@iconify-json/noto": "^1.2.7",
146
144
  "@iconify-json/ri": "^1.2.10",
147
- "@iconify-json/tabler": "^1.2.36",
145
+ "@iconify-json/tabler": "^1.2.37",
148
146
  "@iconify/types": "^2.0.0",
149
147
  "@img/sharp-linux-x64": "^0.35.3",
150
- "@nuxt/content": "^3.15.0",
151
- "@nuxt/devtools": "4.0.0-alpha.7",
152
- "@nuxt/devtools-kit": "4.0.0-alpha.7",
148
+ "@nuxt/content": "^3.15.2",
149
+ "@nuxt/devtools": "4.0.0-alpha.9",
150
+ "@nuxt/devtools-kit": "4.0.0-alpha.9",
153
151
  "@nuxt/fonts": "^0.14.0",
154
152
  "@nuxt/icon": "^2.3.1",
155
153
  "@nuxt/image": "^2.0.0",
156
- "@nuxt/module-builder": "^1.0.2",
157
- "@nuxt/test-utils": "^4.0.3",
154
+ "@nuxt/module-builder": "^1.0.3",
155
+ "@nuxt/test-utils": "^4.1.0",
158
156
  "@nuxt/ui": "^4.10.0",
159
157
  "@nuxtjs/color-mode": "^4.0.1",
160
158
  "@nuxtjs/eslint-config-typescript": "^12.1.0",
161
- "@nuxtjs/i18n": "^10.4.1",
159
+ "@nuxtjs/i18n": "^10.5.0",
162
160
  "@nuxtjs/tailwindcss": "7.0.0-beta.1",
163
161
  "@resvg/resvg-js": "^2.6.2",
164
162
  "@resvg/resvg-wasm": "^2.6.2",
165
163
  "@tailwindcss/vite": "^4.3.3",
166
- "@takumi-rs/core": "^2.3.2",
164
+ "@takumi-rs/core": "^2.5.2",
167
165
  "@takumi-rs/core-v1": "npm:@takumi-rs/core@1.8.7",
168
- "@takumi-rs/helpers": "^2.3.2",
166
+ "@takumi-rs/helpers": "^2.5.2",
169
167
  "@takumi-rs/helpers-v1": "npm:@takumi-rs/helpers@1.8.7",
170
- "@takumi-rs/wasm": "^2.3.2",
168
+ "@takumi-rs/wasm": "^2.5.2",
171
169
  "@takumi-rs/wasm-v1": "npm:@takumi-rs/wasm@1.8.7",
172
170
  "@unocss/nuxt": "^66.7.5",
173
171
  "@unocss/preset-icons": "^66.7.5",
@@ -177,23 +175,23 @@
177
175
  "@vue/compiler-core": "^3.5.40",
178
176
  "@vueuse/nuxt": "^14.3.0",
179
177
  "birpc": "^4.0.0",
180
- "bumpp": "^11.1.0",
181
- "eslint": "^10.7.0",
182
- "eslint-plugin-harlanzw": "^0.17.0",
178
+ "bumpp": "^12.0.0",
179
+ "eslint": "^10.8.0",
180
+ "eslint-plugin-harlanzw": "^0.17.1",
183
181
  "fontless": "^0.2.1",
184
182
  "get-image-colors": "^4.0.1",
185
183
  "globby": "^16.2.2",
186
- "happy-dom": "^20.11.0",
184
+ "happy-dom": "^20.11.1",
187
185
  "hookable": "^6.1.1",
188
186
  "jest-image-snapshot": "^6.5.2",
189
- "lightningcss": "^1.32.0",
187
+ "lightningcss": "^1.33.0",
190
188
  "nitropack": "^2.13.4",
191
- "nuxt": "^4.5.0",
192
- "nuxtseo-layer-devtools": "^5.3.3",
193
- "playwright": "^1.61.1",
194
- "playwright-core": "^1.61.1",
195
- "sass": "^1.101.0",
196
- "satori": "^0.28.0",
189
+ "nuxt": "^4.5.1",
190
+ "nuxtseo-layer-devtools": "^5.3.6",
191
+ "playwright": "^1.62.0",
192
+ "playwright-core": "^1.62.0",
193
+ "sass": "^1.102.0",
194
+ "satori": "^0.29.0",
197
195
  "sharp": "^0.35.3",
198
196
  "sirv": "^3.0.2",
199
197
  "tailwindcss": "^4.3.3",
@@ -203,8 +201,8 @@
203
201
  "unocss": "^66.7.5",
204
202
  "vitest": "^4.1.10",
205
203
  "vue": "^3.5.40",
206
- "vue-tsc": "^3.3.7",
207
- "wrangler": "^4.112.0",
204
+ "vue-tsc": "^3.3.8",
205
+ "wrangler": "^4.114.0",
208
206
  "yoga-wasm-web": "^0.3.3",
209
207
  "zod": "^4.4.3"
210
208
  },