nuxt-og-image 5.1.13 → 6.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (233) hide show
  1. package/README.md +1 -1
  2. package/bin/cli.mjs +2 -0
  3. package/dist/chunks/tw4-classes.cjs +116 -0
  4. package/dist/chunks/tw4-classes.mjs +113 -0
  5. package/dist/chunks/tw4-generator.cjs +118 -0
  6. package/dist/chunks/tw4-generator.mjs +110 -0
  7. package/dist/cli.cjs +333 -0
  8. package/dist/cli.d.cts +1 -0
  9. package/dist/cli.d.mts +1 -0
  10. package/dist/cli.d.ts +1 -0
  11. package/dist/cli.mjs +330 -0
  12. package/dist/client/200.html +1 -1
  13. package/dist/client/404.html +1 -1
  14. package/dist/client/_fonts/0xp3SbCWC1OhX7q1-uF6kilMZFm-alJNkUtkLTPCy_A-tN9KwPUWhhXvtqh74sU9FIkI4W6hsbm85r0X24hjOfM.woff2 +0 -0
  15. package/dist/client/_fonts/1ZTlEDqU4DtwDJiND8f6qaugUpa0RIDvQl-v7iM6l54-D6hedAgqRfOCLZzaShnyeAvlEnMzk4Wm7g9WDKWFHIc.woff +0 -0
  16. package/dist/client/_fonts/4HA9tc4y8BVQeLXvLn3JgQqilAj1xrAnUSprQGHIPSw-ZPswEL_UDOYaxTLQDUySPjoOHDxhD83pD19HMfKfK9s.woff2 +0 -0
  17. package/dist/client/_fonts/Bmul3LaKlc7BUKqJHE_UmEoF40Sg_2ga52yJjwyDcKs-TnYmYl1DNYkiWMu0Vx49DakCPBuiCCj9zoLIuQjUdKY.woff2 +0 -0
  18. package/dist/client/_fonts/DfgmjWGpWte3Q3a54Nevr_BYmMM5YEJXRI1CdI2VwO0-ox5RadQfCyVTmKl_hubTaIJjtRw9oaQz2GDBeZR6l1M.woff2 +0 -0
  19. package/dist/client/_fonts/Lc_5lWuBuZcZ166p1-s-mnGkMJwIYJE_QDCkws8iCkI-r45Qbm2hCykrfOZ0kowz__uTTTUOPDN9hz34QcRNTY4.woff2 +0 -0
  20. package/dist/client/_fonts/iEvApgDRmzKzNqOYocBTrmcHZmuGAJloawKDP1S0nyE-T3oc_9We24QGwfw5naik4cM0g7VxylWVaQwKm4dy3cw.woff2 +0 -0
  21. package/dist/client/_nuxt/0kYTU2a7.js +2 -0
  22. package/dist/client/_nuxt/B0QDx5EE.js +2 -0
  23. package/dist/client/_nuxt/BKqzYw6x.js +3 -0
  24. package/dist/client/_nuxt/C-Ivr2Rl.js +1 -0
  25. package/dist/client/_nuxt/CLgn8DCr.js +1 -0
  26. package/dist/client/_nuxt/CwWm-XE3.js +1 -0
  27. package/dist/client/_nuxt/D9eL2h5z.js +1 -0
  28. package/dist/client/_nuxt/DJXHIJSq.js +1 -0
  29. package/dist/client/_nuxt/DVnX3Z-O.js +1 -0
  30. package/dist/client/_nuxt/DXObZt09.js +184 -0
  31. package/dist/client/_nuxt/Dxi6QG7I.js +1 -0
  32. package/dist/client/_nuxt/E8AZ6HoH.js +1 -0
  33. package/dist/client/_nuxt/IFrameLoader.CGrV1TpP.css +1 -0
  34. package/dist/client/_nuxt/JAMwWy1K.js +3864 -0
  35. package/dist/client/_nuxt/OSectionBlock.BVHnMsIr.css +1 -0
  36. package/dist/client/_nuxt/PONEy9N-.js +1 -0
  37. package/dist/client/_nuxt/UdkqSAsD.js +1 -0
  38. package/dist/client/_nuxt/builds/latest.json +1 -1
  39. package/dist/client/_nuxt/builds/meta/5205806b-8e5a-41ea-90c0-9cd83a75fc0a.json +1 -0
  40. package/dist/client/_nuxt/entry.BEExJd9R.css +2 -0
  41. package/dist/client/_nuxt/error-404.B79WD2X-.css +1 -0
  42. package/dist/client/_nuxt/error-500.DT3Sd0Wu.css +1 -0
  43. package/dist/client/_nuxt/pages.eW3hi7XF.css +1 -0
  44. package/dist/client/_nuxt/templates.dUiUBaip.css +1 -0
  45. package/dist/client/_payload.json +1 -0
  46. package/dist/client/debug/_payload.json +1 -0
  47. package/dist/client/debug/index.html +1 -0
  48. package/dist/client/docs/_payload.json +1 -0
  49. package/dist/client/docs/index.html +1 -0
  50. package/dist/client/fonts/HubotSans-Regular.woff2 +0 -0
  51. package/dist/client/index.html +1 -1
  52. package/dist/client/templates/_payload.json +1 -0
  53. package/dist/client/templates/index.html +1 -0
  54. package/dist/module.cjs +36 -1027
  55. package/dist/module.d.cts +63 -25
  56. package/dist/module.d.mts +63 -25
  57. package/dist/module.d.ts +63 -25
  58. package/dist/module.json +1 -1
  59. package/dist/module.mjs +32 -1009
  60. package/dist/runtime/app/components/Templates/Community/Brutalist.satori.d.vue.ts +14 -0
  61. package/dist/runtime/app/components/Templates/Community/Brutalist.satori.vue +51 -0
  62. package/dist/runtime/app/components/Templates/Community/Brutalist.satori.vue.d.ts +14 -0
  63. package/dist/runtime/app/components/Templates/Community/{Frame.vue.d.ts → Frame.satori.d.vue.ts} +2 -2
  64. package/dist/runtime/app/components/Templates/Community/Frame.satori.vue +71 -0
  65. package/dist/runtime/app/components/Templates/Community/{Frame.d.vue.ts → Frame.satori.vue.d.ts} +2 -2
  66. package/dist/runtime/app/components/Templates/Community/Newspaper.satori.d.vue.ts +12 -0
  67. package/dist/runtime/app/components/Templates/Community/Newspaper.satori.vue +70 -0
  68. package/dist/runtime/app/components/Templates/Community/Newspaper.satori.vue.d.ts +12 -0
  69. package/dist/runtime/app/components/Templates/Community/Nuxt.satori.d.vue.ts +12 -0
  70. package/dist/runtime/app/components/Templates/Community/{Nuxt.vue → Nuxt.satori.vue} +3 -3
  71. package/dist/runtime/app/components/Templates/Community/Nuxt.satori.vue.d.ts +12 -0
  72. package/dist/runtime/app/components/Templates/Community/NuxtSeo.satori.d.vue.ts +12 -0
  73. package/dist/runtime/app/components/Templates/Community/NuxtSeo.satori.vue +69 -0
  74. package/dist/runtime/app/components/Templates/Community/NuxtSeo.satori.vue.d.ts +12 -0
  75. package/dist/runtime/app/components/Templates/Community/Pergel.satori.d.vue.ts +12 -0
  76. package/dist/runtime/app/components/Templates/Community/{Pergel.vue → Pergel.satori.vue} +14 -11
  77. package/dist/runtime/app/components/Templates/Community/Pergel.satori.vue.d.ts +12 -0
  78. package/dist/runtime/app/components/Templates/Community/Retro.satori.d.vue.ts +12 -0
  79. package/dist/runtime/app/components/Templates/Community/Retro.satori.vue +64 -0
  80. package/dist/runtime/app/components/Templates/Community/Retro.satori.vue.d.ts +12 -0
  81. package/dist/runtime/app/components/Templates/Community/SaaS.satori.d.vue.ts +12 -0
  82. package/dist/runtime/app/components/Templates/Community/SaaS.satori.vue +60 -0
  83. package/dist/runtime/app/components/Templates/Community/SaaS.satori.vue.d.ts +12 -0
  84. package/dist/runtime/app/components/Templates/Community/SimpleBlog.satori.d.vue.ts +9 -0
  85. package/dist/runtime/app/components/Templates/Community/SimpleBlog.satori.vue +38 -0
  86. package/dist/runtime/app/components/Templates/Community/SimpleBlog.satori.vue.d.ts +9 -0
  87. package/dist/runtime/app/components/Templates/Community/{UnJs.d.vue.ts → UnJs.satori.d.vue.ts} +2 -2
  88. package/dist/runtime/app/components/Templates/Community/{UnJs.vue → UnJs.satori.vue} +41 -33
  89. package/dist/runtime/app/components/Templates/Community/{UnJs.vue.d.ts → UnJs.satori.vue.d.ts} +2 -2
  90. package/dist/runtime/app/components/Templates/Community/WithEmoji.satori.d.vue.ts +13 -0
  91. package/dist/runtime/app/components/Templates/Community/WithEmoji.satori.vue +27 -0
  92. package/dist/runtime/app/components/Templates/Community/WithEmoji.satori.vue.d.ts +13 -0
  93. package/dist/runtime/app/composables/_defineOgImageRaw.d.ts +6 -0
  94. package/dist/runtime/app/composables/_defineOgImageRaw.js +70 -0
  95. package/dist/runtime/app/composables/defineOgImage.d.ts +14 -2
  96. package/dist/runtime/app/composables/defineOgImage.js +13 -42
  97. package/dist/runtime/app/composables/defineOgImageComponent.d.ts +5 -1
  98. package/dist/runtime/app/composables/defineOgImageComponent.js +4 -5
  99. package/dist/runtime/app/composables/defineOgImageScreenshot.d.ts +1 -1
  100. package/dist/runtime/app/composables/defineOgImageScreenshot.js +2 -2
  101. package/dist/runtime/app/composables/mock.d.ts +7 -4
  102. package/dist/runtime/app/composables/mock.js +4 -4
  103. package/dist/runtime/app/utils/plugins.js +22 -28
  104. package/dist/runtime/app/utils.d.ts +15 -1
  105. package/dist/runtime/app/utils.js +74 -46
  106. package/dist/runtime/pure.d.ts +7 -0
  107. package/dist/runtime/pure.js +105 -0
  108. package/dist/runtime/server/og-image/bindings/css-inline/wasm-fs.d.ts +3 -2
  109. package/dist/runtime/server/og-image/bindings/css-inline/wasm.d.ts +3 -2
  110. package/dist/runtime/server/og-image/bindings/font-assets/cloudflare.d.ts +3 -0
  111. package/dist/runtime/server/og-image/bindings/font-assets/cloudflare.js +22 -0
  112. package/dist/runtime/server/og-image/bindings/font-assets/dev-prerender.d.ts +3 -0
  113. package/dist/runtime/server/og-image/bindings/font-assets/dev-prerender.js +49 -0
  114. package/dist/runtime/server/og-image/bindings/font-assets/node.d.ts +3 -0
  115. package/dist/runtime/server/og-image/bindings/font-assets/node.js +14 -0
  116. package/dist/runtime/server/og-image/bindings/resvg/node-dev.d.ts +5 -0
  117. package/dist/runtime/server/og-image/bindings/resvg/node-dev.js +70 -0
  118. package/dist/runtime/server/og-image/bindings/takumi/node.d.ts +6 -0
  119. package/dist/runtime/server/og-image/bindings/takumi/node.js +5 -0
  120. package/dist/runtime/server/og-image/bindings/takumi/wasm.d.ts +6 -0
  121. package/dist/runtime/server/og-image/bindings/takumi/wasm.js +6 -0
  122. package/dist/runtime/server/og-image/cache/buildCache.d.ts +16 -0
  123. package/dist/runtime/server/og-image/cache/buildCache.js +48 -0
  124. package/dist/runtime/server/og-image/cache/lru.d.ts +2 -2
  125. package/dist/runtime/server/og-image/cache/lru.js +3 -3
  126. package/dist/runtime/server/og-image/cache/mock.d.ts +1 -2
  127. package/dist/runtime/server/og-image/cache/mock.js +0 -1
  128. package/dist/runtime/server/og-image/chromium/screenshot.js +4 -3
  129. package/dist/runtime/server/og-image/context.d.ts +2 -3
  130. package/dist/runtime/server/og-image/context.js +55 -193
  131. package/dist/runtime/server/og-image/devtools.d.ts +10 -0
  132. package/dist/runtime/server/og-image/devtools.js +74 -0
  133. package/dist/runtime/server/og-image/fonts.d.ts +6 -0
  134. package/dist/runtime/server/og-image/fonts.js +41 -0
  135. package/dist/runtime/server/og-image/instances.d.ts +1 -0
  136. package/dist/runtime/server/og-image/instances.js +5 -0
  137. package/dist/runtime/server/og-image/satori/instances.d.ts +1 -36
  138. package/dist/runtime/server/og-image/satori/plugins/emojis.js +83 -4
  139. package/dist/runtime/server/og-image/satori/plugins/encoding.js +11 -1
  140. package/dist/runtime/server/og-image/satori/plugins/imageSrc.js +5 -1
  141. package/dist/runtime/server/og-image/satori/plugins/twClasses.js +35 -0
  142. package/dist/runtime/server/og-image/satori/renderer.js +16 -53
  143. package/dist/runtime/server/og-image/satori/transforms/emojis/emoji-names-minimal.d.ts +1 -0
  144. package/dist/runtime/server/og-image/satori/transforms/emojis/emoji-names-minimal.js +223 -0
  145. package/dist/runtime/server/og-image/satori/transforms/emojis/emoji-utils.d.ts +45 -0
  146. package/dist/runtime/server/og-image/satori/transforms/emojis/emoji-utils.js +13 -0
  147. package/dist/runtime/server/og-image/satori/transforms/emojis/fetch.d.ts +6 -0
  148. package/dist/runtime/server/og-image/satori/transforms/emojis/fetch.js +38 -0
  149. package/dist/runtime/server/og-image/satori/transforms/emojis/index.d.ts +7 -0
  150. package/dist/runtime/server/og-image/satori/transforms/emojis/index.js +64 -0
  151. package/dist/runtime/server/og-image/satori/transforms/emojis/local.d.ts +7 -0
  152. package/dist/runtime/server/og-image/satori/transforms/emojis/local.js +32 -0
  153. package/dist/runtime/server/og-image/satori/utils.js +5 -4
  154. package/dist/runtime/server/og-image/satori/vnodes.js +7 -6
  155. package/dist/runtime/server/og-image/takumi/instances.d.ts +1 -0
  156. package/dist/runtime/server/og-image/takumi/instances.js +6 -0
  157. package/dist/runtime/server/og-image/takumi/nodes.d.ts +12 -0
  158. package/dist/runtime/server/og-image/takumi/nodes.js +86 -0
  159. package/dist/runtime/server/og-image/takumi/renderer.d.ts +3 -0
  160. package/dist/runtime/server/og-image/takumi/renderer.js +45 -0
  161. package/dist/runtime/server/og-image/templates/html.js +32 -23
  162. package/dist/runtime/server/plugins/prerender.d.ts +1 -1
  163. package/dist/runtime/server/plugins/prerender.js +17 -7
  164. package/dist/runtime/server/util/auto-eject.d.ts +2 -0
  165. package/dist/runtime/server/util/auto-eject.js +30 -0
  166. package/dist/runtime/server/util/eventHandlers.d.ts +0 -1
  167. package/dist/runtime/server/util/eventHandlers.js +15 -85
  168. package/dist/runtime/server/util/options.d.ts +7 -2
  169. package/dist/runtime/server/util/options.js +40 -6
  170. package/dist/runtime/server/utils.d.ts +6 -2
  171. package/dist/runtime/server/utils.js +12 -8
  172. package/dist/runtime/shared/urlEncoding.d.ts +64 -0
  173. package/dist/runtime/shared/urlEncoding.js +194 -0
  174. package/dist/runtime/shared.d.ts +4 -9
  175. package/dist/runtime/shared.js +31 -50
  176. package/dist/runtime/types.d.ts +71 -25
  177. package/dist/shared/nuxt-og-image.DroaQ3v-.cjs +2852 -0
  178. package/dist/shared/nuxt-og-image.HMyihp-D.mjs +2825 -0
  179. package/dist/types.d.mts +2 -0
  180. package/package.json +105 -43
  181. package/types/virtual.d.ts +7 -1
  182. package/dist/client/_nuxt/B3LgXoKV.js +0 -2
  183. package/dist/client/_nuxt/B8PEiB0p.js +0 -1
  184. package/dist/client/_nuxt/CPsbVDfV.js +0 -1
  185. package/dist/client/_nuxt/CVO1_9PV.js +0 -1
  186. package/dist/client/_nuxt/CjQm5wk3.js +0 -4029
  187. package/dist/client/_nuxt/Cp-IABpG.js +0 -1
  188. package/dist/client/_nuxt/D0TMZt8T.js +0 -1
  189. package/dist/client/_nuxt/D0r3Knsf.js +0 -1
  190. package/dist/client/_nuxt/builds/meta/eb2c0390-3125-4af7-b189-e76a7dfe3017.json +0 -1
  191. package/dist/client/_nuxt/entry.cdy4VsCK.css +0 -1
  192. package/dist/client/_nuxt/error-404.Cu4JbXd7.css +0 -1
  193. package/dist/client/_nuxt/error-500.B79uceR7.css +0 -1
  194. package/dist/runtime/app/components/OgImage/OgImage.d.ts +0 -3
  195. package/dist/runtime/app/components/OgImage/OgImage.js +0 -10
  196. package/dist/runtime/app/components/Templates/Community/BrandedLogo.d.vue.ts +0 -13
  197. package/dist/runtime/app/components/Templates/Community/BrandedLogo.vue +0 -22
  198. package/dist/runtime/app/components/Templates/Community/BrandedLogo.vue.d.ts +0 -13
  199. package/dist/runtime/app/components/Templates/Community/Frame.vue +0 -58
  200. package/dist/runtime/app/components/Templates/Community/Nuxt.d.vue.ts +0 -12
  201. package/dist/runtime/app/components/Templates/Community/Nuxt.vue.d.ts +0 -12
  202. package/dist/runtime/app/components/Templates/Community/NuxtSeo.d.vue.ts +0 -15
  203. package/dist/runtime/app/components/Templates/Community/NuxtSeo.vue +0 -103
  204. package/dist/runtime/app/components/Templates/Community/NuxtSeo.vue.d.ts +0 -15
  205. package/dist/runtime/app/components/Templates/Community/Pergel.d.vue.ts +0 -12
  206. package/dist/runtime/app/components/Templates/Community/Pergel.vue.d.ts +0 -12
  207. package/dist/runtime/app/components/Templates/Community/SimpleBlog.d.vue.ts +0 -9
  208. package/dist/runtime/app/components/Templates/Community/SimpleBlog.vue +0 -27
  209. package/dist/runtime/app/components/Templates/Community/SimpleBlog.vue.d.ts +0 -9
  210. package/dist/runtime/app/components/Templates/Community/Wave.d.vue.ts +0 -11
  211. package/dist/runtime/app/components/Templates/Community/Wave.vue +0 -28
  212. package/dist/runtime/app/components/Templates/Community/Wave.vue.d.ts +0 -11
  213. package/dist/runtime/app/components/Templates/Community/WithEmoji.d.vue.ts +0 -13
  214. package/dist/runtime/app/components/Templates/Community/WithEmoji.vue +0 -21
  215. package/dist/runtime/app/components/Templates/Community/WithEmoji.vue.d.ts +0 -13
  216. package/dist/runtime/assets/Inter-normal-400.ttf.base64 +0 -1
  217. package/dist/runtime/assets/Inter-normal-700.ttf.base64 +0 -1
  218. package/dist/runtime/server/og-image/satori/font.d.ts +0 -3
  219. package/dist/runtime/server/og-image/satori/font.js +0 -40
  220. package/dist/runtime/server/og-image/satori/plugins/unocss.js +0 -55
  221. package/dist/runtime/server/og-image/satori/transforms/emojis.d.ts +0 -3
  222. package/dist/runtime/server/og-image/satori/transforms/emojis.js +0 -3595
  223. package/dist/runtime/server/plugins/__zero-runtime/nuxt-content-v2.d.ts +0 -2
  224. package/dist/runtime/server/plugins/__zero-runtime/nuxt-content-v2.js +0 -9
  225. package/dist/runtime/server/plugins/nuxt-content-v2.d.ts +0 -2
  226. package/dist/runtime/server/plugins/nuxt-content-v2.js +0 -5
  227. package/dist/runtime/server/routes/__zero-runtime/font.d.ts +0 -2
  228. package/dist/runtime/server/routes/__zero-runtime/font.js +0 -8
  229. package/dist/runtime/server/routes/font.d.ts +0 -2
  230. package/dist/runtime/server/routes/font.js +0 -3
  231. package/dist/runtime/server/util/plugins.d.ts +0 -2
  232. package/dist/runtime/server/util/plugins.js +0 -56
  233. /package/dist/runtime/server/og-image/satori/plugins/{unocss.d.ts → twClasses.d.ts} +0 -0
@@ -1,18 +1,52 @@
1
1
  import { componentNames } from "#og-image-virtual/component-names.mjs";
2
+ import { createError } from "h3";
2
3
  export function normaliseOptions(_options) {
3
4
  const options = { ..._options };
4
- if (!options)
5
- return options;
5
+ let resolved;
6
+ if (options.component === "PageScreenshot") {
7
+ return {
8
+ options,
9
+ renderer: options.renderer || "chromium",
10
+ component: void 0
11
+ };
12
+ }
6
13
  if (options.component && componentNames) {
7
14
  const originalName = options.component;
8
15
  for (const component of componentNames) {
9
- if (component.pascalName.endsWith(originalName) || component.kebabName.endsWith(originalName)) {
16
+ const basePascalName = component.pascalName.replace(/(Satori|Chromium|Takumi)$/, "");
17
+ const baseKebabName = component.kebabName.replace(/-(satori|chromium|takumi)$/, "");
18
+ if (basePascalName.endsWith(originalName) || baseKebabName.endsWith(originalName)) {
10
19
  options.component = component.pascalName;
20
+ resolved = component;
11
21
  break;
12
22
  }
13
23
  }
14
- } else if (!options.component) {
15
- options.component = componentNames[0]?.pascalName;
16
24
  }
17
- return options;
25
+ if (!resolved && options.component) {
26
+ resolved = componentNames.find((c) => c.pascalName === options.component);
27
+ }
28
+ if (!resolved) {
29
+ resolved = componentNames[0];
30
+ options.component = resolved?.pascalName;
31
+ }
32
+ if (!resolved) {
33
+ throw createError({
34
+ statusCode: 500,
35
+ message: `[Nuxt OG Image] No OG Image components found. Create a component in components/OgImage/ with a renderer suffix (e.g., Default.satori.vue)`
36
+ });
37
+ }
38
+ if (resolved.category === "community") {
39
+ if (!import.meta.dev) {
40
+ throw createError({
41
+ statusCode: 500,
42
+ message: `Community template "${resolved.pascalName}" must be ejected before production use. Run: npx nuxt-og-image eject ${resolved.pascalName}`
43
+ });
44
+ }
45
+ }
46
+ const renderer = options.renderer || resolved.renderer;
47
+ return {
48
+ options,
49
+ renderer,
50
+ component: resolved
51
+ };
18
52
  }
@@ -1,4 +1,8 @@
1
- import type { OgImageOptions, OgImageRuntimeConfig } from '#og-image/types';
2
1
  import type { H3Event } from 'h3';
3
- export declare function getOgImagePath(pagePath: string, _options?: Partial<OgImageOptions>): string;
2
+ import type { OgImageOptions, OgImageRuntimeConfig } from '../types.js';
3
+ export interface GetOgImagePathResult {
4
+ path: string;
5
+ hash?: string;
6
+ }
7
+ export declare function getOgImagePath(_pagePath: string, _options?: Partial<OgImageOptions>): GetOgImagePathResult;
4
8
  export declare function useOgImageRuntimeConfig(e?: H3Event): OgImageRuntimeConfig;
@@ -1,17 +1,21 @@
1
1
  import { useRuntimeConfig } from "nitropack/runtime";
2
- import { joinURL, withQuery } from "ufo";
3
- export function getOgImagePath(pagePath, _options) {
2
+ import { joinURL } from "ufo";
3
+ import { buildOgImageUrl } from "../shared.js";
4
+ export function getOgImagePath(_pagePath, _options) {
4
5
  const baseURL = useRuntimeConfig().app.baseURL;
5
- const extension = _options?.extension || useOgImageRuntimeConfig().defaults.extension;
6
- const path = joinURL("/", baseURL, `__og-image__/${import.meta.prerender ? "static" : "image"}`, pagePath, `og.${extension}`);
7
- if (Object.keys(_options?._query || {}).length) {
8
- return withQuery(path, _options._query);
9
- }
10
- return path;
6
+ const { defaults } = useOgImageRuntimeConfig();
7
+ const extension = _options?.extension || defaults.extension;
8
+ const isStatic = import.meta.prerender;
9
+ const result = buildOgImageUrl({ ..._options, _path: _pagePath }, extension, isStatic, defaults);
10
+ return {
11
+ path: joinURL("/", baseURL, result.url),
12
+ hash: result.hash
13
+ };
11
14
  }
12
15
  export function useOgImageRuntimeConfig(e) {
13
16
  const c = useRuntimeConfig(e);
14
17
  return {
18
+ defaults: {},
15
19
  ...c["nuxt-og-image"],
16
20
  app: {
17
21
  baseURL: c.app.baseURL
@@ -0,0 +1,64 @@
1
+ /**
2
+ * URL encoding for OG image options (Cloudinary/IPX style)
3
+ *
4
+ * Format: /_og/s/w_1200,h_630,c_NuxtSeo,title_Hello+World.png
5
+ *
6
+ * When the encoded path exceeds MAX_PATH_LENGTH (200 chars), falls back to hash mode:
7
+ * Format: /_og/s/o_<hash>.png
8
+ *
9
+ * - Known OgImageOptions use short aliases (w, h, c, etc.)
10
+ * - Component props are encoded directly (title_Hello)
11
+ * - Complex objects are base64 encoded JSON
12
+ */
13
+ /**
14
+ * Generate a deterministic hash from options object
15
+ * Excludes _path so images with same options can be cached across pages
16
+ * Optionally includes componentHash and version for cache busting
17
+ */
18
+ export declare function hashOgImageOptions(options: Record<string, any>, componentHash?: string, version?: string): string;
19
+ /**
20
+ * Encode OG image options into a URL path segment
21
+ * @param options - The options to encode
22
+ * @param defaults - Optional defaults to skip (values matching defaults won't be encoded)
23
+ * @example encodeOgImageParams({ width: 1200, props: { title: 'Hello' } })
24
+ * // Returns: "w_1200,title_Hello"
25
+ */
26
+ export declare function encodeOgImageParams(options: Record<string, any>, defaults?: Record<string, any>): string;
27
+ /**
28
+ * Decode URL path segment back into OG image options
29
+ * @example decodeOgImageParams("w_1200,title_Hello")
30
+ * // Returns: { width: 1200, props: { title: 'Hello' } }
31
+ */
32
+ export declare function decodeOgImageParams(encoded: string): Record<string, any>;
33
+ export interface BuildOgImageUrlResult {
34
+ url: string;
35
+ hash?: string;
36
+ }
37
+ /**
38
+ * Build full OG image URL
39
+ *
40
+ * When encoded params exceed MAX_PATH_LENGTH, falls back to hash mode:
41
+ * - Returns short path: /_og/s/o_<hash>.png
42
+ * - Returns hash in result for cache storage
43
+ *
44
+ * @param options - The options to encode
45
+ * @param extension - Image extension (png, jpeg, etc.)
46
+ * @param isStatic - Whether this is a static/prerendered image
47
+ * @param defaults - Optional defaults to skip from URL (keeps URLs shorter)
48
+ * @example buildOgImageUrl({ width: 1200, props: { title: 'Hello' } }, 'png', true)
49
+ * // Returns: { url: "/_og/s/w_1200,title_Hello.png" }
50
+ */
51
+ export declare function buildOgImageUrl(options: Record<string, any>, extension?: string, isStatic?: boolean, defaults?: Record<string, any>): BuildOgImageUrlResult;
52
+ /**
53
+ * Parse OG image URL back into options
54
+ * @example parseOgImageUrl("/_og/s/w_1200,h_630.png")
55
+ * // Returns: { options: { width: 1200, height: 630 }, extension: 'png', isStatic: true, hash: undefined }
56
+ * @example parseOgImageUrl("/_og/s/o_abc123.png")
57
+ * // Returns: { options: {}, extension: 'png', isStatic: true, hash: 'abc123' }
58
+ */
59
+ export declare function parseOgImageUrl(url: string): {
60
+ options: Record<string, any>;
61
+ extension: string;
62
+ isStatic: boolean;
63
+ hash?: string;
64
+ };
@@ -0,0 +1,194 @@
1
+ const MAX_PATH_LENGTH = 200;
2
+ const PARAM_ALIASES = {
3
+ w: "width",
4
+ h: "height",
5
+ c: "component",
6
+ em: "emojis",
7
+ k: "key",
8
+ a: "alt",
9
+ u: "url",
10
+ cache: "cacheMaxAgeSeconds",
11
+ p: "_path",
12
+ // page path - needs alias since _path starts with underscore
13
+ q: "_query"
14
+ // query params - needs alias since _query starts with underscore
15
+ };
16
+ const PARAM_TO_ALIAS = Object.fromEntries(
17
+ Object.entries(PARAM_ALIASES).map(([alias, param]) => [param, alias])
18
+ );
19
+ const KNOWN_PARAMS = /* @__PURE__ */ new Set([
20
+ "width",
21
+ "height",
22
+ "component",
23
+ "emojis",
24
+ "key",
25
+ "alt",
26
+ "url",
27
+ "cacheMaxAgeSeconds",
28
+ "extension",
29
+ "html",
30
+ "satori",
31
+ "resvg",
32
+ "sharp",
33
+ "screenshot",
34
+ "fonts",
35
+ "_query",
36
+ "socialPreview",
37
+ "props",
38
+ "_path"
39
+ ]);
40
+ const COMPLEX_PARAMS = /* @__PURE__ */ new Set(["satori", "resvg", "sharp", "screenshot", "fonts", "_query", "_path"]);
41
+ function b64Encode(str) {
42
+ if (typeof btoa === "function") {
43
+ const utf8 = new TextEncoder().encode(str);
44
+ const binary = String.fromCharCode(...utf8);
45
+ return btoa(binary).replace(/=/g, "");
46
+ }
47
+ return Buffer.from(str, "utf8").toString("base64").replace(/=/g, "");
48
+ }
49
+ function b64Decode(str) {
50
+ const padded = str + "=".repeat((4 - str.length % 4) % 4);
51
+ if (typeof atob === "function") {
52
+ const binary = atob(padded);
53
+ const bytes = Uint8Array.from(binary, (c) => c.charCodeAt(0));
54
+ return new TextDecoder().decode(bytes);
55
+ }
56
+ return Buffer.from(padded, "base64").toString("utf8");
57
+ }
58
+ function simpleHash(str) {
59
+ let hash = 0;
60
+ for (let i = 0; i < str.length; i++) {
61
+ const char = str.charCodeAt(i);
62
+ hash = (hash << 5) - hash + char;
63
+ hash = hash & hash;
64
+ }
65
+ return Math.abs(hash).toString(36);
66
+ }
67
+ export function hashOgImageOptions(options, componentHash, version) {
68
+ const { _path, _hash, ...hashableOptions } = options;
69
+ const hashInput = componentHash || version ? [hashableOptions, componentHash || "", version || ""] : hashableOptions;
70
+ return simpleHash(JSON.stringify(hashInput));
71
+ }
72
+ export function encodeOgImageParams(options, defaults) {
73
+ const parts = [];
74
+ const flattened = {};
75
+ for (const [key, value] of Object.entries(options)) {
76
+ if (key === "props" && typeof value === "object") {
77
+ for (const [propKey, propValue] of Object.entries(value)) {
78
+ if (typeof propValue === "string" || typeof propValue === "number" || typeof propValue === "boolean") {
79
+ flattened[propKey] = propValue;
80
+ } else {
81
+ flattened.props = flattened.props || {};
82
+ flattened.props[propKey] = propValue;
83
+ }
84
+ }
85
+ } else {
86
+ flattened[key] = value;
87
+ }
88
+ }
89
+ for (const [key, value] of Object.entries(flattened)) {
90
+ if (value === void 0 || value === null)
91
+ continue;
92
+ if (key === "extension" || key === "socialPreview")
93
+ continue;
94
+ if (defaults && key in defaults && defaults[key] === value)
95
+ continue;
96
+ const alias = PARAM_TO_ALIAS[key] || key;
97
+ if (COMPLEX_PARAMS.has(key)) {
98
+ const b64 = b64Encode(JSON.stringify(value));
99
+ parts.push(`${alias}_${b64}`);
100
+ } else if (typeof value === "object") {
101
+ const b64 = b64Encode(JSON.stringify(value));
102
+ parts.push(`${alias}_${b64}`);
103
+ } else {
104
+ const encoded = encodeURIComponent(String(value).replace(/_/g, "__")).replace(/%20/g, "+");
105
+ parts.push(`${alias}_${encoded}`);
106
+ }
107
+ }
108
+ return parts.join(",");
109
+ }
110
+ export function decodeOgImageParams(encoded) {
111
+ if (!encoded || encoded === "default")
112
+ return {};
113
+ const options = {};
114
+ const parts = encoded.split(",");
115
+ for (const part of parts) {
116
+ const idx = part.search(/(?<!_)_(?!_)/);
117
+ if (idx === -1)
118
+ continue;
119
+ const alias = part.slice(0, idx);
120
+ let value = part.slice(idx + 1);
121
+ const paramName = PARAM_ALIASES[alias] || alias;
122
+ if (COMPLEX_PARAMS.has(paramName)) {
123
+ try {
124
+ const json = b64Decode(value);
125
+ options[paramName] = JSON.parse(json);
126
+ } catch {
127
+ options[paramName] = value;
128
+ }
129
+ } else if (paramName === "props") {
130
+ try {
131
+ const json = b64Decode(value);
132
+ options.props = { ...options.props, ...JSON.parse(json) };
133
+ } catch {
134
+ }
135
+ } else if (KNOWN_PARAMS.has(paramName)) {
136
+ value = decodeURIComponent(value.replace(/\+/g, "%20")).replace(/__/g, "_");
137
+ if (value === "true") {
138
+ options[paramName] = true;
139
+ } else if (value === "false") {
140
+ options[paramName] = false;
141
+ } else {
142
+ const num = Number(value);
143
+ options[paramName] = Number.isNaN(num) ? value : num;
144
+ }
145
+ } else {
146
+ value = decodeURIComponent(value.replace(/\+/g, "%20")).replace(/__/g, "_");
147
+ options.props = options.props || {};
148
+ if (value === "true") {
149
+ options.props[paramName] = true;
150
+ } else if (value === "false") {
151
+ options.props[paramName] = false;
152
+ } else {
153
+ const num = Number(value);
154
+ options.props[paramName] = Number.isNaN(num) ? value : num;
155
+ }
156
+ }
157
+ }
158
+ return options;
159
+ }
160
+ export function buildOgImageUrl(options, extension = "png", isStatic = false, defaults) {
161
+ const encoded = encodeOgImageParams(options, defaults);
162
+ const prefix = isStatic ? "/_og/s" : "/_og/d";
163
+ if (encoded.length > MAX_PATH_LENGTH) {
164
+ const hash = hashOgImageOptions(options);
165
+ return {
166
+ url: `${prefix}/o_${hash}.${extension}`,
167
+ hash
168
+ };
169
+ }
170
+ return {
171
+ url: encoded ? `${prefix}/${encoded}.${extension}` : `${prefix}/default.${extension}`
172
+ };
173
+ }
174
+ export function parseOgImageUrl(url) {
175
+ const isStatic = url.includes("/_og/s/");
176
+ const path = url.replace(/^\/_og\/[ds]\//, "");
177
+ const extMatch = path.match(/\.(\w+)$/);
178
+ const extension = extMatch?.[1] || "png";
179
+ const encoded = path.replace(/\.\w+$/, "");
180
+ const hashMatch = encoded.match(/^o_([a-z0-9]+)$/i);
181
+ if (hashMatch) {
182
+ return {
183
+ options: {},
184
+ extension,
185
+ isStatic,
186
+ hash: hashMatch[1]
187
+ };
188
+ }
189
+ return {
190
+ options: decodeOgImageParams(encoded),
191
+ extension,
192
+ isStatic
193
+ };
194
+ }
@@ -1,15 +1,10 @@
1
1
  import type { ResolvableMeta } from '@unhead/vue';
2
- import type { InputFontConfig, OgImageOptions, OgImagePrebuilt, ResolvedFontConfig } from './types.js';
2
+ import type { OgImageOptions, OgImagePrebuilt } from './types.js';
3
+ export { extractSocialPreviewTags } from './pure.js';
4
+ export { buildOgImageUrl, decodeOgImageParams, encodeOgImageParams, hashOgImageOptions, parseOgImageUrl } from './shared/urlEncoding.js';
3
5
  export declare function generateMeta(url: OgImagePrebuilt['url'] | string, resolvedOptions: OgImageOptions | OgImagePrebuilt): ResolvableMeta[];
4
6
  export declare function toBase64Image(data: string | ArrayBuffer): string;
5
7
  export declare function isInternalRoute(path: string): boolean;
6
- export declare function separateProps(options: OgImageOptions | undefined, ignoreKeys?: string[]): {
7
- props: Record<string, any>;
8
- };
9
- export declare function normaliseFontInput(fonts: InputFontConfig[]): ResolvedFontConfig[];
8
+ export declare function separateProps(options: OgImageOptions | undefined, ignoreKeys?: string[]): OgImageOptions;
10
9
  export declare function withoutQuery(path: string): string | undefined;
11
10
  export declare function getExtension(path: string): string;
12
- /**
13
- * @deprecated Please use `#og-image/app/utils` instead.
14
- */
15
- export declare function useOgImageRuntimeConfig(): {};
@@ -1,25 +1,38 @@
1
1
  import { defu } from "defu";
2
2
  import { toValue } from "vue";
3
+ export { extractSocialPreviewTags } from "./pure.js";
4
+ export { buildOgImageUrl, decodeOgImageParams, encodeOgImageParams, hashOgImageOptions, parseOgImageUrl } from "./shared/urlEncoding.js";
3
5
  export function generateMeta(url, resolvedOptions) {
4
- const meta = [
5
- { property: "og:image", content: url },
6
- { property: "og:image:type", content: () => `image/${getExtension(toValue(url)) || resolvedOptions.extension}` },
7
- { name: "twitter:card", content: "summary_large_image" },
8
- // we don't need this but avoids issue when using useSeoMeta({ twitterImage })
9
- { name: "twitter:image", content: url },
10
- { name: "twitter:image:src", content: url }
11
- ];
6
+ const key = resolvedOptions.key || "og";
7
+ const isTwitterOnly = key === "twitter";
8
+ const includeTwitter = key === "og" || key === "twitter";
9
+ const meta = [];
10
+ if (!isTwitterOnly) {
11
+ meta.push({ property: "og:image", content: url });
12
+ meta.push({ property: "og:image:type", content: () => `image/${getExtension(toValue(url)) || resolvedOptions.extension}` });
13
+ }
14
+ if (includeTwitter) {
15
+ meta.push({ name: "twitter:card", content: "summary_large_image" });
16
+ meta.push({ name: "twitter:image", content: url });
17
+ meta.push({ name: "twitter:image:src", content: url });
18
+ }
12
19
  if (resolvedOptions.width) {
13
- meta.push({ property: "og:image:width", content: resolvedOptions.width });
14
- meta.push({ name: "twitter:image:width", content: resolvedOptions.width });
20
+ if (!isTwitterOnly)
21
+ meta.push({ property: "og:image:width", content: resolvedOptions.width });
22
+ if (includeTwitter)
23
+ meta.push({ name: "twitter:image:width", content: resolvedOptions.width });
15
24
  }
16
25
  if (resolvedOptions.height) {
17
- meta.push({ property: "og:image:height", content: resolvedOptions.height });
18
- meta.push({ name: "twitter:image:height", content: resolvedOptions.height });
26
+ if (!isTwitterOnly)
27
+ meta.push({ property: "og:image:height", content: resolvedOptions.height });
28
+ if (includeTwitter)
29
+ meta.push({ name: "twitter:image:height", content: resolvedOptions.height });
19
30
  }
20
31
  if (resolvedOptions.alt) {
21
- meta.push({ property: "og:image:alt", content: resolvedOptions.alt });
22
- meta.push({ name: "twitter:image:alt", content: resolvedOptions.alt });
32
+ if (!isTwitterOnly)
33
+ meta.push({ property: "og:image:alt", content: resolvedOptions.alt });
34
+ if (includeTwitter)
35
+ meta.push({ name: "twitter:image:alt", content: resolvedOptions.alt });
23
36
  }
24
37
  return meta;
25
38
  }
@@ -53,20 +66,21 @@ function filterIsOgImageOption(key) {
53
66
  "extension",
54
67
  "width",
55
68
  "height",
56
- "fonts",
57
69
  "alt",
58
70
  "props",
59
71
  "renderer",
72
+ // internal use only (screenshots)
60
73
  "html",
61
74
  "component",
62
- "renderer",
63
75
  "emojis",
64
76
  "_query",
77
+ "_hash",
65
78
  "satori",
66
79
  "resvg",
67
80
  "sharp",
68
81
  "screenshot",
69
- "cacheMaxAgeSeconds"
82
+ "cacheMaxAgeSeconds",
83
+ "key"
70
84
  ];
71
85
  return keys.includes(key);
72
86
  }
@@ -86,36 +100,6 @@ export function separateProps(options, ignoreKeys = []) {
86
100
  props
87
101
  };
88
102
  }
89
- export function normaliseFontInput(fonts) {
90
- return fonts.map((f) => {
91
- if (typeof f === "string") {
92
- const vals = f.split(":");
93
- const includesStyle = vals.length === 3;
94
- let name, weight, style;
95
- if (includesStyle) {
96
- name = vals[0];
97
- style = vals[1];
98
- weight = vals[2];
99
- } else {
100
- name = vals[0];
101
- weight = vals[1];
102
- }
103
- return {
104
- cacheKey: f,
105
- name,
106
- weight: weight || 400,
107
- style: style || "normal",
108
- path: void 0
109
- };
110
- }
111
- return {
112
- cacheKey: f.key || `${f.name}:${f.style}:${f.weight}`,
113
- style: "normal",
114
- weight: 400,
115
- ...f
116
- };
117
- });
118
- }
119
103
  export function withoutQuery(path) {
120
104
  return path.split("?")[0];
121
105
  }
@@ -127,6 +111,3 @@ export function getExtension(path) {
127
111
  return "jpeg";
128
112
  return extension;
129
113
  }
130
- export function useOgImageRuntimeConfig() {
131
- return {};
132
- }