nuxt-og-image 3.0.0-rc.0 → 3.0.0-rc.10

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 (45) hide show
  1. package/README.md +0 -4
  2. package/dist/client/200.html +5 -5
  3. package/dist/client/404.html +5 -5
  4. package/dist/client/_nuxt/{IconCSS.9f95294e.js → IconCSS.b32ce867.js} +1 -1
  5. package/dist/client/_nuxt/builds/latest.json +1 -1
  6. package/dist/client/_nuxt/builds/meta/bb3bd895-b72a-4970-a205-33afc62f06bc.json +1 -0
  7. package/dist/client/_nuxt/entry.47125dcd.css +1 -0
  8. package/dist/client/_nuxt/{entry.c5e613a6.js → entry.ecf0d33f.js} +47 -47
  9. package/dist/client/_nuxt/{error-404.e1564a51.js → error-404.b9a11c8e.js} +1 -1
  10. package/dist/client/_nuxt/{error-500.90b12af8.js → error-500.eb8225d3.js} +1 -1
  11. package/dist/client/index.html +5 -5
  12. package/dist/module.d.mts +5 -0
  13. package/dist/module.d.ts +5 -0
  14. package/dist/module.json +1 -1
  15. package/dist/module.mjs +37 -10
  16. package/dist/runtime/cache.d.ts +2 -1
  17. package/dist/runtime/cache.mjs +33 -18
  18. package/dist/runtime/components/Templates/Community/NuxtSeo.vue +1 -1
  19. package/dist/runtime/composables/defineOgImage.mjs +8 -10
  20. package/dist/runtime/core/font/fetch.mjs +4 -1
  21. package/dist/runtime/core/html/devIframeTemplate.mjs +3 -2
  22. package/dist/runtime/core/html/fetchIsland.mjs +1 -1
  23. package/dist/runtime/core/options/extract.d.ts +1 -0
  24. package/dist/runtime/core/options/extract.mjs +3 -0
  25. package/dist/runtime/core/options/fetch.mjs +7 -1
  26. package/dist/runtime/core/renderers/chromium/index.mjs +2 -1
  27. package/dist/runtime/core/renderers/satori/index.mjs +6 -5
  28. package/dist/runtime/core/renderers/satori/vnodes.mjs +2 -0
  29. package/dist/runtime/core/utils/resolveRendererContext.mjs +14 -16
  30. package/dist/runtime/nitro/kit.d.ts +3 -0
  31. package/dist/runtime/nitro/kit.mjs +23 -0
  32. package/dist/runtime/nitro/plugins/prerender.d.ts +1 -1
  33. package/dist/runtime/nitro/plugins/prerender.mjs +5 -12
  34. package/dist/runtime/nitro/utils.mjs +2 -3
  35. package/dist/runtime/nuxt/utils.mjs +10 -3
  36. package/dist/runtime/server/routes/__og-image__/debug.json.d.ts +0 -4
  37. package/dist/runtime/server/routes/__og-image__/debug.json.mjs +0 -6
  38. package/dist/runtime/server/routes/__og-image__/font-[name]-[weight].[extension].mjs +31 -5
  39. package/dist/runtime/server/routes/__og-image__/image.mjs +8 -5
  40. package/dist/runtime/types.d.ts +5 -0
  41. package/dist/runtime/utils.pure.d.ts +2 -0
  42. package/dist/runtime/utils.pure.mjs +10 -1
  43. package/package.json +16 -15
  44. package/dist/client/_nuxt/builds/meta/01a72661-4cae-4637-8364-242cd0ee1a35.json +0 -1
  45. package/dist/client/_nuxt/entry.a30f63d0.css +0 -1
@@ -1 +1 @@
1
- import{_ as a,u as n,o as r,c as l,a as e,t as s,b as d,w as c,d as p,e as f,p as x,f as h}from"./entry.c5e613a6.js";const m=t=>(x("data-v-05a2b8a3"),t=t(),h(),t),u={class:"font-sans antialiased bg-white dark:bg-black text-black dark:text-white grid min-h-screen place-content-center overflow-hidden"},g=m(()=>e("div",{class:"fixed left-0 right-0 spotlight z-10"},null,-1)),b={class:"max-w-520px text-center z-20"},_=["textContent"],w=["textContent"],y={class:"w-full flex items-center justify-center"},S={__name:"error-404",props:{appName:{type:String,default:"Nuxt"},version:{type:String,default:""},statusCode:{type:Number,default:404},statusMessage:{type:String,default:"Not Found"},description:{type:String,default:"Sorry, the page you are looking for could not be found."},backHome:{type:String,default:"Go back home"}},setup(t){const o=t;return n({title:`${o.statusCode} - ${o.statusMessage} | ${o.appName}`,script:[],style:[{children:'*,:before,:after{-webkit-box-sizing:border-box;box-sizing:border-box;border-width:0;border-style:solid;border-color:#e0e0e0}*{--tw-ring-inset:var(--tw-empty, );--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(14, 165, 233, .5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000}:root{-moz-tab-size:4;-o-tab-size:4;tab-size:4}a{color:inherit;text-decoration:inherit}body{margin:0;font-family:inherit;line-height:inherit}html{-webkit-text-size-adjust:100%;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";line-height:1.5}h1,p{margin:0}h1{font-size:inherit;font-weight:inherit}'}]}),(k,v)=>{const i=f;return r(),l("div",u,[g,e("div",b,[e("h1",{class:"text-8xl sm:text-10xl font-medium mb-8",textContent:s(t.statusCode)},null,8,_),e("p",{class:"text-xl px-8 sm:px-0 sm:text-4xl font-light mb-16 leading-tight",textContent:s(t.description)},null,8,w),e("div",y,[d(i,{to:"/",class:"gradient-border text-md sm:text-xl py-2 px-4 sm:py-3 sm:px-6 cursor-pointer"},{default:c(()=>[p(s(t.backHome),1)]),_:1})])])])}}},z=a(S,[["__scopeId","data-v-05a2b8a3"]]);export{z as default};
1
+ import{_ as a,u as n,o as r,c as l,a as e,t as s,b as d,w as c,d as p,e as f,p as x,f as h}from"./entry.ecf0d33f.js";const m=t=>(x("data-v-05a2b8a3"),t=t(),h(),t),u={class:"font-sans antialiased bg-white dark:bg-black text-black dark:text-white grid min-h-screen place-content-center overflow-hidden"},g=m(()=>e("div",{class:"fixed left-0 right-0 spotlight z-10"},null,-1)),b={class:"max-w-520px text-center z-20"},_=["textContent"],w=["textContent"],y={class:"w-full flex items-center justify-center"},S={__name:"error-404",props:{appName:{type:String,default:"Nuxt"},version:{type:String,default:""},statusCode:{type:Number,default:404},statusMessage:{type:String,default:"Not Found"},description:{type:String,default:"Sorry, the page you are looking for could not be found."},backHome:{type:String,default:"Go back home"}},setup(t){const o=t;return n({title:`${o.statusCode} - ${o.statusMessage} | ${o.appName}`,script:[],style:[{children:'*,:before,:after{-webkit-box-sizing:border-box;box-sizing:border-box;border-width:0;border-style:solid;border-color:#e0e0e0}*{--tw-ring-inset:var(--tw-empty, );--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(14, 165, 233, .5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000}:root{-moz-tab-size:4;-o-tab-size:4;tab-size:4}a{color:inherit;text-decoration:inherit}body{margin:0;font-family:inherit;line-height:inherit}html{-webkit-text-size-adjust:100%;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";line-height:1.5}h1,p{margin:0}h1{font-size:inherit;font-weight:inherit}'}]}),(k,v)=>{const i=f;return r(),l("div",u,[g,e("div",b,[e("h1",{class:"text-8xl sm:text-10xl font-medium mb-8",textContent:s(t.statusCode)},null,8,_),e("p",{class:"text-xl px-8 sm:px-0 sm:text-4xl font-light mb-16 leading-tight",textContent:s(t.description)},null,8,w),e("div",y,[d(i,{to:"/",class:"gradient-border text-md sm:text-xl py-2 px-4 sm:py-3 sm:px-6 cursor-pointer"},{default:c(()=>[p(s(t.backHome),1)]),_:1})])])])}}},z=a(S,[["__scopeId","data-v-05a2b8a3"]]);export{z as default};
@@ -1 +1 @@
1
- import{_ as i,u as a,o as r,c as n,a as e,t as s,p as l,f as d}from"./entry.c5e613a6.js";const c=t=>(l("data-v-c967d9a9"),t=t(),d(),t),p={class:"font-sans antialiased bg-white dark:bg-black text-black dark:text-white grid min-h-screen place-content-center overflow-hidden"},h=c(()=>e("div",{class:"fixed -bottom-1/2 left-0 right-0 h-1/2 spotlight"},null,-1)),f={class:"max-w-520px text-center"},g=["textContent"],m=["textContent"],x={__name:"error-500",props:{appName:{type:String,default:"Nuxt"},version:{type:String,default:""},statusCode:{type:Number,default:500},statusMessage:{type:String,default:"Server error"},description:{type:String,default:"This page is temporarily unavailable."}},setup(t){const o=t;return a({title:`${o.statusCode} - ${o.statusMessage} | ${o.appName}`,script:[],style:[{children:'*,:before,:after{-webkit-box-sizing:border-box;box-sizing:border-box;border-width:0;border-style:solid;border-color:#e0e0e0}*{--tw-ring-inset:var(--tw-empty, );--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(14, 165, 233, .5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000}:root{-moz-tab-size:4;-o-tab-size:4;tab-size:4}body{margin:0;font-family:inherit;line-height:inherit}html{-webkit-text-size-adjust:100%;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";line-height:1.5}h1,p{margin:0}h1{font-size:inherit;font-weight:inherit}'}]}),(u,b)=>(r(),n("div",p,[h,e("div",f,[e("h1",{class:"text-8xl sm:text-10xl font-medium mb-8",textContent:s(t.statusCode)},null,8,g),e("p",{class:"text-xl px-8 sm:px-0 sm:text-4xl font-light mb-16 leading-tight",textContent:s(t.description)},null,8,m)])]))}},w=i(x,[["__scopeId","data-v-c967d9a9"]]);export{w as default};
1
+ import{_ as i,u as a,o as r,c as n,a as e,t as s,p as l,f as d}from"./entry.ecf0d33f.js";const c=t=>(l("data-v-c967d9a9"),t=t(),d(),t),p={class:"font-sans antialiased bg-white dark:bg-black text-black dark:text-white grid min-h-screen place-content-center overflow-hidden"},h=c(()=>e("div",{class:"fixed -bottom-1/2 left-0 right-0 h-1/2 spotlight"},null,-1)),f={class:"max-w-520px text-center"},g=["textContent"],m=["textContent"],x={__name:"error-500",props:{appName:{type:String,default:"Nuxt"},version:{type:String,default:""},statusCode:{type:Number,default:500},statusMessage:{type:String,default:"Server error"},description:{type:String,default:"This page is temporarily unavailable."}},setup(t){const o=t;return a({title:`${o.statusCode} - ${o.statusMessage} | ${o.appName}`,script:[],style:[{children:'*,:before,:after{-webkit-box-sizing:border-box;box-sizing:border-box;border-width:0;border-style:solid;border-color:#e0e0e0}*{--tw-ring-inset:var(--tw-empty, );--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(14, 165, 233, .5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000}:root{-moz-tab-size:4;-o-tab-size:4;tab-size:4}body{margin:0;font-family:inherit;line-height:inherit}html{-webkit-text-size-adjust:100%;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";line-height:1.5}h1,p{margin:0}h1{font-size:inherit;font-weight:inherit}'}]}),(u,b)=>(r(),n("div",p,[h,e("div",f,[e("h1",{class:"text-8xl sm:text-10xl font-medium mb-8",textContent:s(t.statusCode)},null,8,g),e("p",{class:"text-xl px-8 sm:px-0 sm:text-4xl font-light mb-16 leading-tight",textContent:s(t.description)},null,8,m)])]))}},w=i(x,[["__scopeId","data-v-c967d9a9"]]);export{w as default};
@@ -2,14 +2,14 @@
2
2
  <html >
3
3
  <head><meta charset="utf-8">
4
4
  <meta name="viewport" content="width=device-width, initial-scale=1">
5
- <link rel="stylesheet" href="/__nuxt-og-image/_nuxt/entry.a30f63d0.css">
6
- <link rel="modulepreload" as="script" crossorigin href="/__nuxt-og-image/_nuxt/entry.c5e613a6.js">
5
+ <link rel="stylesheet" href="/__nuxt-og-image/_nuxt/entry.47125dcd.css">
6
+ <link rel="modulepreload" as="script" crossorigin href="/__nuxt-og-image/_nuxt/entry.ecf0d33f.js">
7
7
  <link rel="prefetch" as="script" crossorigin href="/__nuxt-og-image/_nuxt/vanilla-picker-NKbIFE8h.23409a58.js">
8
8
  <link rel="prefetch" as="style" href="/__nuxt-og-image/_nuxt/error-404.b751fa02.css">
9
- <link rel="prefetch" as="script" crossorigin href="/__nuxt-og-image/_nuxt/error-404.e1564a51.js">
9
+ <link rel="prefetch" as="script" crossorigin href="/__nuxt-og-image/_nuxt/error-404.b9a11c8e.js">
10
10
  <link rel="prefetch" as="style" href="/__nuxt-og-image/_nuxt/error-500.69009e70.css">
11
- <link rel="prefetch" as="script" crossorigin href="/__nuxt-og-image/_nuxt/error-500.90b12af8.js">
12
- <script type="module" src="/__nuxt-og-image/_nuxt/entry.c5e613a6.js" crossorigin></script><script>"use strict";(()=>{const a=window,e=document.documentElement,m=["dark","light"],c=window&&window.localStorage&&window.localStorage.getItem&&window.localStorage.getItem("nuxt-color-mode")||"system";let n=c==="system"?d():c;const l=e.getAttribute("data-color-mode-forced");l&&(n=l),i(n),a["__NUXT_COLOR_MODE__"]={preference:c,value:n,getColorScheme:d,addColorScheme:i,removeColorScheme:f};function i(o){const t=""+o+"",s="";e.classList?e.classList.add(t):e.className+=" "+t,s&&e.setAttribute("data-"+s,o)}function f(o){const t=""+o+"",s="";e.classList?e.classList.remove(t):e.className=e.className.replace(new RegExp(t,"g"),""),s&&e.removeAttribute("data-"+s)}function r(o){return a.matchMedia("(prefers-color-scheme"+o+")")}function d(){if(a.matchMedia&&r("").media!=="not all"){for(const o of m)if(r(":"+o).matches)return o}return"light"}})();
11
+ <link rel="prefetch" as="script" crossorigin href="/__nuxt-og-image/_nuxt/error-500.eb8225d3.js">
12
+ <script type="module" src="/__nuxt-og-image/_nuxt/entry.ecf0d33f.js" crossorigin></script><script>"use strict";(()=>{const a=window,e=document.documentElement,m=["dark","light"],c=window&&window.localStorage&&window.localStorage.getItem&&window.localStorage.getItem("nuxt-color-mode")||"system";let n=c==="system"?d():c;const l=e.getAttribute("data-color-mode-forced");l&&(n=l),i(n),a["__NUXT_COLOR_MODE__"]={preference:c,value:n,getColorScheme:d,addColorScheme:i,removeColorScheme:f};function i(o){const t=""+o+"",s="";e.classList?e.classList.add(t):e.className+=" "+t,s&&e.setAttribute("data-"+s,o)}function f(o){const t=""+o+"",s="";e.classList?e.classList.remove(t):e.className=e.className.replace(new RegExp(t,"g"),""),s&&e.removeAttribute("data-"+s)}function r(o){return a.matchMedia("(prefers-color-scheme"+o+")")}function d(){if(a.matchMedia&&r("").media!=="not all"){for(const o of m)if(r(":"+o).matches)return o}return"light"}})();
13
13
  </script></head>
14
14
  <body ><div id="__nuxt"></div><script type="application/json" id="__NUXT_DATA__" data-ssr="false">[{"_errors":1,"serverRendered":2,"data":3,"state":4},{},false,{},{}]</script>
15
15
  <script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-og-image",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body>
package/dist/module.d.mts CHANGED
@@ -80,9 +80,14 @@ interface OgImageOptions<T extends keyof OgImageComponents = 'NuxtSeo'> {
80
80
  sharp?: SharpOptions;
81
81
  fonts?: InputFontConfig[];
82
82
  cacheMaxAgeSeconds?: number;
83
+ /**
84
+ * @internal
85
+ */
86
+ _query?: Record<string, any>;
83
87
  }
84
88
  interface FontConfig {
85
89
  name: string;
90
+ style?: string;
86
91
  weight?: string | number;
87
92
  path?: string;
88
93
  key?: string;
package/dist/module.d.ts CHANGED
@@ -80,9 +80,14 @@ interface OgImageOptions<T extends keyof OgImageComponents = 'NuxtSeo'> {
80
80
  sharp?: SharpOptions;
81
81
  fonts?: InputFontConfig[];
82
82
  cacheMaxAgeSeconds?: number;
83
+ /**
84
+ * @internal
85
+ */
86
+ _query?: Record<string, any>;
83
87
  }
84
88
  interface FontConfig {
85
89
  name: string;
90
+ style?: string;
86
91
  weight?: string | number;
87
92
  path?: string;
88
93
  key?: string;
package/dist/module.json CHANGED
@@ -5,5 +5,5 @@
5
5
  "bridge": false
6
6
  },
7
7
  "configKey": "ogImage",
8
- "version": "3.0.0-rc.0"
8
+ "version": "3.0.0-rc.9"
9
9
  }
package/dist/module.mjs CHANGED
@@ -14,7 +14,7 @@ import { createHash } from 'node:crypto';
14
14
  import { execa } from 'execa';
15
15
  import terminate from 'terminate';
16
16
 
17
- const version = "3.0.0-rc.0";
17
+ const version = "3.0.0-rc.9";
18
18
 
19
19
  const autodetectableProviders = {
20
20
  azure_static: "azure",
@@ -205,6 +205,9 @@ export {}
205
205
  references.push({ path: resolve(nuxt.options.buildDir, `module/${module}.d.ts`) });
206
206
  });
207
207
  }
208
+ function isNuxtGenerate(nuxt = useNuxt()) {
209
+ return nuxt.options._generate || nuxt.options.nitro.static || nuxt.options.nitro.preset === "static";
210
+ }
208
211
 
209
212
  const DEVTOOLS_UI_ROUTE = "/__nuxt-og-image";
210
213
  const DEVTOOLS_UI_LOCAL_PORT = 3030;
@@ -295,7 +298,9 @@ function setupGenerateHandler(options, resolve, nuxt = useNuxt()) {
295
298
  function setupPrerenderHandler(options, resolve, nuxt = useNuxt()) {
296
299
  nuxt.hooks.hook("nitro:init", async (nitro) => {
297
300
  nitro.hooks.hook("prerender:config", async (nitroConfig) => {
298
- applyNitroPresetCompatibility(nitroConfig, { compatibility: options.compatibility.prerender, resolve });
301
+ nitroConfig.serverAssets = nitroConfig.serverAssets || [];
302
+ nitroConfig.serverAssets.push({ baseName: "nuxt-og-image:fonts", dir: resolve("./runtime/server/assets") });
303
+ applyNitroPresetCompatibility(nitroConfig, { compatibility: options.compatibility?.prerender, resolve });
299
304
  nitroConfig.wasm = nitroConfig.wasm || {};
300
305
  nitroConfig.wasm.esmImport = false;
301
306
  const prerenderingPages = (nuxt.options.nitro.prerender?.routes || []).some((r) => r && (!r.includes(".") || r.includes("*")));
@@ -365,7 +370,7 @@ function normaliseFontInput(fonts) {
365
370
  return {
366
371
  cacheKey: f,
367
372
  name,
368
- weight: weight || "400",
373
+ weight: weight || 400,
369
374
  style: "normal",
370
375
  path: void 0
371
376
  };
@@ -395,6 +400,7 @@ const module = defineNuxtModule({
395
400
  emojis: "noto",
396
401
  renderer: "satori",
397
402
  component: "NuxtSeo",
403
+ extension: "png",
398
404
  width: 1200,
399
405
  height: 600,
400
406
  // default is to cache the image for 3 day (72 hours)
@@ -423,7 +429,6 @@ const module = defineNuxtModule({
423
429
  const hasSharpDependency = !!await tryResolveModule("sharp");
424
430
  const userConfiguredExtension = config.defaults.extension;
425
431
  const hasConfiguredJpegs = userConfiguredExtension && ["jpeg", "jpg"].includes(userConfiguredExtension);
426
- config.defaults.extension = userConfiguredExtension || (hasSharpDependency && targetCompatibility.sharp ? "jpg" : "png");
427
432
  if (hasConfiguredJpegs && config.defaults.renderer !== "chromium") {
428
433
  if (hasSharpDependency && !targetCompatibility.sharp) {
429
434
  logger.warn(`Rendering JPEGs requires sharp which does not work with ${preset}. Images will be rendered as PNG at runtime.`);
@@ -468,6 +473,18 @@ const module = defineNuxtModule({
468
473
  } else if (!hasChromeLocally && nuxt.options.dev && config.compatibility?.dev?.chromium === "node") {
469
474
  await ensureChromium(logger);
470
475
  }
476
+ await import('@resvg/resvg-js').catch(() => {
477
+ logger.warn("ReSVG is missing dependencies for environment. Falling back to WASM version, this may slow down PNG rendering.");
478
+ config.compatibility = defu(config.compatibility, {
479
+ dev: { resvg: "wasm-fs" },
480
+ prerender: { resvg: "wasm-fs" }
481
+ });
482
+ if (targetCompatibility.resvg === "node") {
483
+ config.compatibility = defu(config.compatibility, {
484
+ runtime: { resvg: "wasm" }
485
+ });
486
+ }
487
+ });
471
488
  await installNuxtSiteConfig();
472
489
  if (hasNuxtModule("@nuxt/content"))
473
490
  addServerPlugin(resolve("./runtime/nitro/plugins/nuxt-content"));
@@ -616,7 +633,7 @@ declare module 'nitropack' {
616
633
  }
617
634
  interface NitroRuntimeHooks {
618
635
  'nuxt-og-image:context': (ctx: import('${typesPath}').OgImageRenderEventContext) => void | Promise<void>
619
- 'nuxt-og-image:satori:vnodes': (vnodes: import('${typesPath}').VNode, ctx: ctx: import('${typesPath}').OgImageRenderEventContext) => void | Promise<void>
636
+ 'nuxt-og-image:satori:vnodes': (vnodes: import('${typesPath}').VNode, ctx: import('${typesPath}').OgImageRenderEventContext) => void | Promise<void>
620
637
  }
621
638
  }
622
639
 
@@ -629,16 +646,26 @@ ${componentImports}
629
646
  });
630
647
  const cacheEnabled = typeof config.runtimeCacheStorage !== "undefined" && config.runtimeCacheStorage !== false;
631
648
  const runtimeCacheStorage = typeof config.runtimeCacheStorage === "boolean" ? "default" : config.runtimeCacheStorage.driver;
632
- let baseCacheKey = runtimeCacheStorage === "default" ? `/cache/nuxt-og-image@${version}` : `/nuxt-og-image@${version}`;
649
+ let baseCacheKey = runtimeCacheStorage === "default" ? `/cache/nuxt-og-image@${version}` : `/nuxt-og-image/${version}`;
633
650
  if (!cacheEnabled)
634
651
  baseCacheKey = false;
652
+ if (!nuxt.options.dev && config.runtimeCacheStorage && typeof config.runtimeCacheStorage === "object") {
653
+ nuxt.options.nitro.storage = nuxt.options.nitro.storage || {};
654
+ nuxt.options.nitro.storage["nuxt-og-image"] = config.runtimeCacheStorage;
655
+ }
635
656
  nuxt.hooks.hook("modules:done", async () => {
636
657
  const normalisedFonts = normaliseFontInput(config.fonts);
637
- if (!nuxt.options._generate && nuxt.options.build) {
658
+ if (!isNuxtGenerate() && nuxt.options.build) {
659
+ nuxt.options.nitro = nuxt.options.nitro || {};
638
660
  nuxt.options.nitro.prerender = nuxt.options.nitro.prerender || {};
639
661
  nuxt.options.nitro.prerender.routes = nuxt.options.nitro.prerender.routes || [];
640
- normalisedFonts.filter((f) => !f.path && !f.key).forEach(({ name, weight }) => {
641
- nuxt.options.nitro.prerender.routes.push(`/__og-image__/font/${name}/${weight}.ttf`);
662
+ normalisedFonts.filter((f) => !f.path && !f.key).forEach((entry, key) => {
663
+ const { name, weight } = entry;
664
+ entry.path = `/__og-image__/font/${name}/${weight}.ttf`;
665
+ nuxt.options.nitro.prerender.routes.unshift(entry.path);
666
+ if (name === "Inter" && [400, 700].includes(Number(weight)))
667
+ entry.key = `nuxt-og-image:fonts:inter-latin-ext-${weight}-normal.woff`;
668
+ normalisedFonts[key] = entry;
642
669
  });
643
670
  }
644
671
  const hasColorModeModule = hasNuxtModule("@nuxtjs/color-mode");
@@ -669,7 +696,7 @@ ${componentImports}
669
696
  if (nuxt.options.dev) {
670
697
  setupDevHandler(config, resolve);
671
698
  setupDevToolsUI(config, resolve);
672
- } else if (nuxt.options._generate) {
699
+ } else if (isNuxtGenerate()) {
673
700
  setupGenerateHandler(config, resolve);
674
701
  } else if (nuxt.options.build) {
675
702
  await setupBuildHandler(config, resolve);
@@ -1,8 +1,9 @@
1
+ import { type H3Error } from 'h3';
1
2
  import type { OgImageRenderEventContext } from './types';
2
3
  export declare function useOgImageBufferCache(ctx: OgImageRenderEventContext, options: {
3
4
  baseCacheKey: string | false;
4
5
  cacheMaxAgeSeconds?: number;
5
- }): Promise<void | {
6
+ }): Promise<void | H3Error | {
6
7
  cachedItem: false | BufferSource;
7
8
  enabled: boolean;
8
9
  update: (image: BufferSource) => Promise<void>;
@@ -1,31 +1,46 @@
1
1
  import { prefixStorage } from "unstorage";
2
- import { getQuery, handleCacheHeaders, setHeader, setHeaders } from "h3";
2
+ import { createError, getQuery, handleCacheHeaders, setHeader, setHeaders } from "h3";
3
3
  import { withTrailingSlash } from "ufo";
4
4
  import { hash } from "ohash";
5
5
  import { useStorage } from "#imports";
6
6
  export async function useOgImageBufferCache(ctx, options) {
7
7
  const maxAge = Number(options.cacheMaxAgeSeconds);
8
- const enabled = !import.meta.dev && import.meta.env.MODE !== "test" && maxAge > 0;
8
+ let enabled = !import.meta.dev && import.meta.env.MODE !== "test" && maxAge > 0;
9
9
  const cache = prefixStorage(useStorage(), withTrailingSlash(options.baseCacheKey || "/"));
10
10
  const key = ctx.key;
11
11
  let cachedItem = false;
12
- if (enabled && await cache.hasItem(key).catch(() => false)) {
13
- const { value, expiresAt, headers } = await cache.getItem(key).catch(() => ({ value: null, expiresAt: Date.now() }));
14
- if (typeof getQuery(ctx.e).purge !== "undefined") {
15
- await cache.removeItem(key).catch(() => {
16
- });
17
- } else if (expiresAt > Date.now()) {
18
- cachedItem = Buffer.from(value, "base64");
19
- if (handleCacheHeaders(ctx.e, {
20
- modifiedTime: new Date(headers["last-modified"]),
21
- etag: headers.etag,
22
- maxAge
23
- }))
24
- return;
25
- setHeaders(ctx.e, headers);
26
- } else {
27
- await cache.removeItem(key).catch(() => {
12
+ if (enabled) {
13
+ const hasItem = await cache.hasItem(key).catch((e) => {
14
+ enabled = false;
15
+ return createError({
16
+ cause: e,
17
+ statusCode: 500,
18
+ statusMessage: `[Nuxt OG Image] Failed to connect to cache ${options.baseCacheKey}. Response from cache: ${e.message}`
28
19
  });
20
+ });
21
+ if (hasItem instanceof Error)
22
+ return hasItem;
23
+ if (hasItem) {
24
+ const { value, expiresAt, headers } = await cache.getItem(key).catch(() => ({
25
+ value: null,
26
+ expiresAt: Date.now()
27
+ }));
28
+ if (typeof getQuery(ctx.e).purge !== "undefined") {
29
+ await cache.removeItem(key).catch(() => {
30
+ });
31
+ } else if (expiresAt > Date.now()) {
32
+ cachedItem = Buffer.from(value, "base64");
33
+ if (handleCacheHeaders(ctx.e, {
34
+ modifiedTime: new Date(headers["last-modified"]),
35
+ etag: headers.etag,
36
+ maxAge
37
+ }))
38
+ return;
39
+ setHeaders(ctx.e, headers);
40
+ } else {
41
+ await cache.removeItem(key).catch(() => {
42
+ });
43
+ }
29
44
  }
30
45
  }
31
46
  if (!enabled) {
@@ -117,7 +117,7 @@ if (typeof props.icon === 'string' && !runtimeConfig.hasNuxtIcon && process.dev)
117
117
  {{ description }}
118
118
  </p>
119
119
  </div>
120
- <div v-if="icon" style="width: 30%;" class="flex justify-end">
120
+ <div v-if="Boolean(icon)" style="width: 30%;" class="flex justify-end">
121
121
  <IconComponent :name="icon" size="250px" style="margin: 0 auto; opacity: 0.7;" />
122
122
  </div>
123
123
  </div>
@@ -1,22 +1,18 @@
1
1
  import { defu } from "defu";
2
2
  import { appendHeader } from "h3";
3
- import { createRouter as createRadixRouter, toRouteMatcher } from "radix3";
4
- import { withoutBase } from "ufo";
5
3
  import { getOgImagePath, separateProps, useOgImageRuntimeConfig } from "../utils.mjs";
6
4
  import { createOgImageMeta, normaliseOptions } from "../nuxt/utils.mjs";
7
- import { useNuxtApp, useRequestEvent, useRouter, useRuntimeConfig } from "#imports";
5
+ import { createNitroRouteRuleMatcher } from "../nitro/kit.mjs";
6
+ import { useNuxtApp, useRequestEvent, useRoute } from "#imports";
8
7
  export function defineOgImage(_options = {}) {
9
8
  if (!import.meta.server)
10
9
  return;
11
10
  const nuxtApp = useNuxtApp();
12
11
  const ogImageInstances = nuxtApp.ssrContext._ogImageInstances || [];
13
- const basePath = useRouter().currentRoute.value?.path || "/";
14
- const _routeRulesMatcher = toRouteMatcher(
15
- createRadixRouter({ routes: useRuntimeConfig().nitro?.routeRules })
16
- );
17
- const routeRules = defu({}, ..._routeRulesMatcher.matchAll(
18
- withoutBase(basePath.split("?")[0], useRuntimeConfig().app.baseURL)
19
- ).reverse()).ogImage;
12
+ const route = useRoute();
13
+ const basePath = route.path || "/";
14
+ const routeRuleMatcher = createNitroRouteRuleMatcher();
15
+ const routeRules = routeRuleMatcher(basePath).ogImage;
20
16
  if (!_options || nuxtApp.ssrContext?.event.context._nitro?.routeRules?.ogImage === false || typeof routeRules !== "undefined" && routeRules === false) {
21
17
  ogImageInstances.forEach((e) => {
22
18
  e.dispose();
@@ -27,6 +23,8 @@ export function defineOgImage(_options = {}) {
27
23
  const options = normaliseOptions({
28
24
  ..._options
29
25
  });
26
+ if (route.query)
27
+ options._query = route.query;
30
28
  const { defaults } = useOgImageRuntimeConfig();
31
29
  const resolvedOptions = normaliseOptions(defu(separateProps(_options), separateProps(routeRules), defaults));
32
30
  if (_options.url) {
@@ -27,7 +27,10 @@ export async function loadFont({ e }, font) {
27
27
  }
28
28
  } else {
29
29
  data = await e.$fetch(`/__og-image__/font/${name}/${weight}.ttf`, {
30
- responseType: "arrayBuffer"
30
+ responseType: "arrayBuffer",
31
+ query: {
32
+ font
33
+ }
31
34
  });
32
35
  }
33
36
  }
@@ -1,6 +1,6 @@
1
1
  import { createHeadCore } from "@unhead/vue";
2
2
  import { renderSSRHead } from "@unhead/ssr";
3
- import { useOgImageRuntimeConfig } from "../../utils.mjs";
3
+ import { normaliseFontInput, useOgImageRuntimeConfig } from "../../utils.mjs";
4
4
  import { applyEmojis } from "./applyEmojis.mjs";
5
5
  import { fetchIsland } from "./fetchIsland.mjs";
6
6
  import { theme } from "#nuxt-og-image/unocss-config.mjs";
@@ -11,7 +11,8 @@ export async function devIframeTemplate(ctx) {
11
11
  const head = createHeadCore();
12
12
  head.push(island.head);
13
13
  let defaultFontFamily = "sans-serif";
14
- const firstFont = fonts[0];
14
+ const normalisedFonts = normaliseFontInput([...options.fonts || [], ...fonts]);
15
+ const firstFont = normalisedFonts[0];
15
16
  if (firstFont)
16
17
  defaultFontFamily = firstFont.name;
17
18
  await applyEmojis(ctx, island);
@@ -4,7 +4,7 @@ export function fetchIsland({ options, e }) {
4
4
  if (!options.component) {
5
5
  throw createError({
6
6
  statusCode: 500,
7
- statusMessage: `Nuxt OG Image trying to render an invalid component. Received options ${JSON.stringify(options)}`
7
+ statusMessage: `[Nuxt OG Image] Rendering an invalid component. Received options: ${JSON.stringify(options)}.`
8
8
  });
9
9
  }
10
10
  const hashId = hash([options.component, options]);
@@ -1,3 +1,4 @@
1
1
  import type { OgImageOptions } from '../../types';
2
+ export declare function htmlDecodeQuotes(html: string): string;
2
3
  export declare function decodeHtml(html: string): string;
3
4
  export declare function extractAndNormaliseOgImageOptions(html: string): OgImageOptions | false;
@@ -1,3 +1,6 @@
1
+ export function htmlDecodeQuotes(html) {
2
+ return html.replace(/&quot;/g, '"').replace(/&#39;/g, "'").replace(/&#x27;/g, "'");
3
+ }
1
4
  export function decodeHtml(html) {
2
5
  return html.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&amp;/g, "&").replace(/&cent;/g, "\xA2").replace(/&pound;/g, "\xA3").replace(/&yen;/g, "\xA5").replace(/&euro;/g, "\u20AC").replace(/&copy;/g, "\xA9").replace(/&reg;/g, "\xAE").replace(/&quot;/g, '"').replace(/&#39;/g, "'").replace(/&#x27;/g, "'").replace(/&#x2F;/g, "/").replace(/&#([0-9]+);/g, (full, int) => {
3
6
  return String.fromCharCode(Number.parseInt(int));
@@ -11,7 +11,13 @@ export async function fetchPathHtmlAndExtractOptions(e, path, key) {
11
11
  } catch (err) {
12
12
  return createError({
13
13
  statusCode: 500,
14
- statusMessage: `Failed to read the path ${path} for og-image extraction. ${err.message}.`
14
+ statusMessage: `[Nuxt OG Image] Failed to read the path ${path} for og-image extraction. ${err.message}.`
15
+ });
16
+ }
17
+ if (typeof html !== "string") {
18
+ return createError({
19
+ statusCode: 500,
20
+ statusMessage: `[Nuxt OG Image] Got invalid response from ${path} for og-image extraction.`
15
21
  });
16
22
  }
17
23
  const payload = extractAndNormaliseOgImageOptions(html);
@@ -14,7 +14,8 @@ const ChromiumRenderer = {
14
14
  if (screenshot instanceof Error) {
15
15
  return createError({
16
16
  statusCode: 400,
17
- statusMessage: `Failed to create screenshot ${screenshot.message}.`
17
+ cause: screenshot,
18
+ statusMessage: `[Nuxt OG Image] Failed to create screenshot ${screenshot.message}.`
18
19
  });
19
20
  }
20
21
  return screenshot;
@@ -7,10 +7,10 @@ import { useResvg, useSatori, useSharp } from "./instances.mjs";
7
7
  import { theme } from "#nuxt-og-image/unocss-config.mjs";
8
8
  export async function createSvg(event) {
9
9
  const { options } = event;
10
- const { fonts, satoriOptions } = useOgImageRuntimeConfig();
10
+ const { fonts, satoriOptions: _satoriOptions } = useOgImageRuntimeConfig();
11
11
  const vnodes = await createVNodes(event);
12
12
  await event._nitro.hooks.callHook("nuxt-og-image:satori:vnodes", vnodes, event);
13
- const normalisedFonts = normaliseFontInput([...fonts, ...event.options.fonts || []]);
13
+ const normalisedFonts = normaliseFontInput([...event.options.fonts || [], ...fonts]);
14
14
  const localFontPromises = [];
15
15
  const preloadedFonts = [];
16
16
  for (const font of normalisedFonts) {
@@ -30,15 +30,16 @@ export async function createSvg(event) {
30
30
  }
31
31
  const awaitedFonts = await Promise.all(localFontPromises);
32
32
  const satori = await useSatori();
33
- return satori(vnodes, defu(options.satori, satoriOptions, {
33
+ const satoriOptions = defu(options.satori, _satoriOptions, {
34
34
  fonts: [...preloadedFonts, ...awaitedFonts].map((_f) => {
35
- return { ..._f, weight: Number(_f.weight) };
35
+ return { name: _f.name, data: _f.data, style: _f.style, weight: Number(_f.weight) };
36
36
  }),
37
37
  tailwindConfig: { theme },
38
38
  embedFont: true,
39
39
  width: options.width,
40
40
  height: options.height
41
- }));
41
+ });
42
+ return satori(vnodes, satoriOptions);
42
43
  }
43
44
  async function createPng(event) {
44
45
  const { resvgOptions } = useOgImageRuntimeConfig();
@@ -2,6 +2,7 @@ import { html as convertHtmlToSatori } from "satori-html";
2
2
  import { fetchIsland } from "../../html/fetchIsland.mjs";
3
3
  import { applyInlineCss } from "../../html/applyInlineCss.mjs";
4
4
  import { applyEmojis } from "../../html/applyEmojis.mjs";
5
+ import { htmlDecodeQuotes } from "../../options/extract.mjs";
5
6
  import { walkSatoriTree } from "./utils.mjs";
6
7
  import unocss from "./plugins/unocss.mjs";
7
8
  import emojis from "./plugins/emojis.mjs";
@@ -13,6 +14,7 @@ export async function createVNodes(ctx) {
13
14
  let html = ctx.options.html;
14
15
  if (!html) {
15
16
  const island = await fetchIsland(ctx);
17
+ island.html = htmlDecodeQuotes(island.html);
16
18
  await applyInlineCss(ctx, island);
17
19
  await applyEmojis(ctx, island);
18
20
  html = island.html;
@@ -1,13 +1,13 @@
1
- import { parseURL, withoutBase, withoutTrailingSlash } from "ufo";
1
+ import { parseURL, withQuery, withoutTrailingSlash } from "ufo";
2
2
  import { createError, getQuery } from "h3";
3
3
  import { defu } from "defu";
4
- import { createRouter as createRadixRouter, toRouteMatcher } from "radix3";
5
4
  import { fetchPathHtmlAndExtractOptions } from "../options/fetch.mjs";
6
5
  import { prerenderOptionsCache } from "../cache/prerender.mjs";
7
6
  import { useChromiumRenderer, useSatoriRenderer } from "../renderers/satori/instances.mjs";
8
7
  import { separateProps, useOgImageRuntimeConfig } from "../../utils.mjs";
9
8
  import { resolvePathCacheKey } from "../../nitro/utils.mjs";
10
- import { useNitroApp, useRuntimeConfig } from "#internal/nitro";
9
+ import { createNitroRouteRuleMatcher } from "../../nitro/kit.mjs";
10
+ import { useNitroApp } from "#internal/nitro/app";
11
11
  export async function resolveRendererContext(e) {
12
12
  const runtimeConfig = useOgImageRuntimeConfig();
13
13
  const path = parseURL(e.path).pathname;
@@ -15,21 +15,23 @@ export async function resolveRendererContext(e) {
15
15
  if (!extension) {
16
16
  return createError({
17
17
  statusCode: 400,
18
- statusMessage: `Missing OG Image type.`
18
+ statusMessage: `[Nuxt OG Image] Missing OG Image type.`
19
19
  });
20
20
  }
21
21
  if (!["png", "jpeg", "jpg", "svg", "html", "json"].includes(extension)) {
22
22
  return createError({
23
23
  statusCode: 400,
24
- statusMessage: `Unknown OG Image type ${extension}.`
24
+ statusMessage: `[Nuxt OG Image] Unknown OG Image type ${extension}.`
25
25
  });
26
26
  }
27
- const basePath = withoutTrailingSlash(
28
- path.replace(`/__og-image__/image`, "").replace(`/og.${extension}`, "")
29
- );
30
27
  let queryParams = { ...getQuery(e) };
31
28
  queryParams.props = JSON.parse(queryParams.props || "{}");
32
29
  queryParams = separateProps(queryParams);
30
+ let basePath = withoutTrailingSlash(
31
+ path.replace(`/__og-image__/image`, "").replace(`/og.${extension}`, "")
32
+ );
33
+ if (queryParams._query)
34
+ basePath = withQuery(basePath, JSON.parse(queryParams._query));
33
35
  const isDebugJsonPayload = extension === "json" && runtimeConfig.debug;
34
36
  const key = resolvePathCacheKey(e, basePath);
35
37
  let options = queryParams.options;
@@ -44,12 +46,8 @@ export async function resolveRendererContext(e) {
44
46
  }
45
47
  }
46
48
  delete queryParams.options;
47
- const _routeRulesMatcher = toRouteMatcher(
48
- createRadixRouter({ routes: useRuntimeConfig().nitro?.routeRules })
49
- );
50
- const routeRules = defu({}, ..._routeRulesMatcher.matchAll(
51
- withoutBase(basePath.split("?")[0], useRuntimeConfig().app.baseURL)
52
- ).reverse());
49
+ const routeRuleMatcher = createNitroRouteRuleMatcher();
50
+ const routeRules = routeRuleMatcher(basePath);
53
51
  if (typeof routeRules.ogImage === "undefined" && !options) {
54
52
  return createError({
55
53
  statusCode: 400,
@@ -61,7 +59,7 @@ export async function resolveRendererContext(e) {
61
59
  if (!options) {
62
60
  return createError({
63
61
  statusCode: 404,
64
- statusMessage: "OG Image not found."
62
+ statusMessage: "[Nuxt OG Image] OG Image not found."
65
63
  });
66
64
  }
67
65
  let renderer;
@@ -76,7 +74,7 @@ export async function resolveRendererContext(e) {
76
74
  if (!renderer || renderer.__unenv__) {
77
75
  throw createError({
78
76
  statusCode: 400,
79
- statusMessage: `Renderer ${options.renderer} is missing.`
77
+ statusMessage: `[Nuxt OG Image] Renderer ${options.renderer} is missing.`
80
78
  });
81
79
  }
82
80
  const ctx = {
@@ -0,0 +1,3 @@
1
+ import type { NitroRouteRules } from 'nitropack';
2
+ export declare function withoutQuery(path: string): string;
3
+ export declare function createNitroRouteRuleMatcher(): (path: string) => NitroRouteRules;
@@ -0,0 +1,23 @@
1
+ import { createRouter as createRadixRouter, toRouteMatcher } from "radix3";
2
+ import { defu } from "defu";
3
+ import { withoutBase, withoutTrailingSlash } from "ufo";
4
+ import { useRuntimeConfig } from "#imports";
5
+ export function withoutQuery(path) {
6
+ return path.split("?")[0];
7
+ }
8
+ export function createNitroRouteRuleMatcher() {
9
+ const { nitro, app } = useRuntimeConfig();
10
+ const _routeRulesMatcher = toRouteMatcher(
11
+ createRadixRouter({
12
+ routes: Object.fromEntries(
13
+ Object.entries(nitro?.routeRules || {}).map(([path, rules]) => [withoutTrailingSlash(path), rules])
14
+ )
15
+ })
16
+ );
17
+ return (path) => {
18
+ return defu({}, ..._routeRulesMatcher.matchAll(
19
+ // radix3 does not support trailing slashes
20
+ withoutBase(withoutTrailingSlash(withoutQuery(path)), app.baseURL)
21
+ ).reverse());
22
+ };
23
+ }
@@ -1,2 +1,2 @@
1
- declare const _default: import("nitropack").NitroAppPlugin;
1
+ declare const _default: import("nitropack/dist/runtime/plugin").NitroAppPlugin;
2
2
  export default _default;
@@ -1,12 +1,10 @@
1
- import { parseURL, withoutBase } from "ufo";
1
+ import { parseURL } from "ufo";
2
2
  import { defineNitroPlugin } from "nitropack/dist/runtime/plugin";
3
- import { createRouter as createRadixRouter, toRouteMatcher } from "radix3";
4
- import { defu } from "defu";
5
3
  import { extractAndNormaliseOgImageOptions } from "../../core/options/extract.mjs";
6
4
  import { prerenderOptionsCache } from "../../core/cache/prerender.mjs";
7
5
  import { isInternalRoute } from "../../utils.pure.mjs";
8
6
  import { resolvePathCacheKey } from "../utils.mjs";
9
- import { useRuntimeConfig } from "#internal/nitro";
7
+ import { createNitroRouteRuleMatcher } from "../kit.mjs";
10
8
  export default defineNitroPlugin(async (nitro) => {
11
9
  if (!import.meta.prerender)
12
10
  return;
@@ -15,14 +13,9 @@ export default defineNitroPlugin(async (nitro) => {
15
13
  const path = parseURL(ctx.event.path).pathname;
16
14
  if (isInternalRoute(path))
17
15
  return;
18
- const runtimeConfig = useRuntimeConfig();
19
- const _routeRulesMatcher = toRouteMatcher(
20
- createRadixRouter({ routes: runtimeConfig.nitro?.routeRules })
21
- );
22
- const routeRules = defu({}, ..._routeRulesMatcher.matchAll(
23
- withoutBase(path.split("?")[0], runtimeConfig.app.baseURL)
24
- ).reverse()).ogImage;
25
- if (routeRules === false)
16
+ const routeRuleMatcher = createNitroRouteRuleMatcher();
17
+ const routeRules = routeRuleMatcher(path);
18
+ if (routeRules.ogImage === false)
26
19
  return;
27
20
  const options = extractAndNormaliseOgImageOptions([
28
21
  head.join("\n"),
@@ -2,12 +2,11 @@ import { withoutLeadingSlash, withoutTrailingSlash } from "ufo";
2
2
  import { hash } from "ohash";
3
3
  import { normalizeKey } from "unstorage";
4
4
  import { getQuery } from "h3";
5
- import { useSiteConfig } from "#imports";
6
5
  export function resolvePathCacheKey(e, path) {
7
- const siteConfig = useSiteConfig(e);
6
+ const siteConfig = e.context.siteConfig.get();
8
7
  const basePath = withoutTrailingSlash(withoutLeadingSlash(normalizeKey(path || e.path)));
9
8
  return [
10
- !basePath ? "index" : basePath,
9
+ !basePath || basePath === "/" ? "index" : basePath,
11
10
  hash([
12
11
  basePath,
13
12
  siteConfig.url,