nuxt-og-image 2.0.3 → 2.0.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 (54) hide show
  1. package/README.md +2 -0
  2. package/dist/client/200.html +2 -2
  3. package/dist/client/404.html +2 -2
  4. package/dist/client/_nuxt/{IconCSS.f4347589.js → IconCSS.c66ac96c.js} +1 -1
  5. package/dist/client/_nuxt/{ImageLoader.b38d1d6c.js → ImageLoader.eea58cf7.js} +1 -1
  6. package/dist/client/_nuxt/{entry.6afde11b.js → entry.db904b01.js} +63 -63
  7. package/dist/client/_nuxt/{error-404.6f854c9c.js → error-404.3fd437f7.js} +1 -1
  8. package/dist/client/_nuxt/{error-500.6c46b8cd.js → error-500.48bc2fce.js} +1 -1
  9. package/dist/client/_nuxt/{index.d11550ac.js → index.62ad0f4a.js} +1 -1
  10. package/dist/client/_nuxt/{options.f74220bf.js → options.8bd8132d.js} +1 -1
  11. package/dist/client/_nuxt/{png.493e2b66.js → png.8fd55f17.js} +1 -1
  12. package/dist/client/_nuxt/shiki.eca11a4d.js +7 -0
  13. package/dist/client/_nuxt/{svg.b775edc5.js → svg.6552a6ca.js} +1 -1
  14. package/dist/client/_nuxt/{vnodes.1003b66c.js → vnodes.5bb613d8.js} +1 -1
  15. package/dist/client/index.html +2 -2
  16. package/dist/module.json +1 -1
  17. package/dist/module.mjs +58 -37
  18. package/dist/runtime/browserUtil.d.ts +1 -1
  19. package/dist/runtime/components/OgImage/Cached.d.ts +1 -1
  20. package/dist/runtime/components/OgImage/Dynamic.d.ts +1 -1
  21. package/dist/runtime/components/OgImage/Screenshot.d.ts +1 -1
  22. package/dist/runtime/components/OgImage/Static.d.ts +1 -1
  23. package/dist/runtime/components/OgImage/WithoutCache.d.ts +1 -1
  24. package/dist/runtime/components/OgImage/index.d.ts +1 -1
  25. package/dist/runtime/composables/defineOgImage.d.ts +1 -1
  26. package/dist/runtime/composables/util.d.ts +1 -1
  27. package/dist/runtime/composables/util.mjs +5 -8
  28. package/dist/runtime/nitro/middleware/og.png.mjs +2 -2
  29. package/dist/runtime/nitro/providers/png/resvg-node.d.ts +1 -1
  30. package/dist/runtime/nitro/providers/png/resvg-wasm.d.ts +1 -1
  31. package/dist/runtime/nitro/providers/png/svg2png.d.ts +1 -1
  32. package/dist/runtime/nitro/providers/satori/yoga-wasm.d.ts +1 -1
  33. package/dist/runtime/nitro/renderers/browser.d.ts +1 -1
  34. package/dist/runtime/nitro/renderers/satori/index.d.ts +1 -1
  35. package/dist/runtime/nitro/renderers/satori/plugins/emojis.d.ts +1 -1
  36. package/dist/runtime/nitro/renderers/satori/plugins/encoding.d.ts +1 -1
  37. package/dist/runtime/nitro/renderers/satori/plugins/flex.d.ts +1 -1
  38. package/dist/runtime/nitro/renderers/satori/plugins/imageSrc.d.ts +1 -1
  39. package/dist/runtime/nitro/renderers/satori/plugins/twClasses.d.ts +1 -1
  40. package/dist/runtime/nitro/renderers/satori/utils.d.ts +1 -1
  41. package/dist/runtime/nitro/routes/options.d.ts +1 -1
  42. package/dist/runtime/nitro/routes/options.mjs +8 -8
  43. package/dist/runtime/nitro/utils-pure.d.ts +2 -2
  44. package/dist/runtime/nitro/utils-pure.mjs +9 -3
  45. package/dist/runtime/nitro/utils.d.ts +1 -1
  46. package/dist/runtime/nitro/utils.mjs +4 -5
  47. package/dist/runtime/types.d.ts +69 -0
  48. package/dist/runtime/types.mjs +0 -0
  49. package/package.json +14 -11
  50. package/dist/client/_nuxt/shiki.74220414.js +0 -7
  51. package/dist/client/options/index.html +0 -7
  52. package/dist/client/png/index.html +0 -7
  53. package/dist/client/svg/index.html +0 -7
  54. package/dist/client/vnodes/index.html +0 -7
package/dist/module.mjs CHANGED
@@ -1,8 +1,10 @@
1
1
  import { readFile, writeFile } from 'node:fs/promises';
2
+ import * as fs from 'node:fs';
3
+ import { existsSync } from 'node:fs';
2
4
  import { useNuxt, addTemplate, defineNuxtModule, useLogger, createResolver, addServerHandler, addImports, addComponent, hasNuxtModule, addServerPlugin } from '@nuxt/kit';
3
5
  import { execa } from 'execa';
4
6
  import chalk from 'chalk';
5
- import defu from 'defu';
7
+ import defu$1, { defu } from 'defu';
6
8
  import { toRouteMatcher, createRouter } from 'radix3';
7
9
  import { withBase, joinURL } from 'ufo';
8
10
  import { resolve, relative, dirname } from 'pathe';
@@ -10,14 +12,16 @@ import { tinyws } from 'tinyws';
10
12
  import sirv from 'sirv';
11
13
  import { pathExists, copy, mkdirp } from 'fs-extra';
12
14
  import { globby } from 'globby';
13
- import { installNuxtSiteConfig, updateSiteConfig, requireSiteConfig } from 'nuxt-site-config-kit';
15
+ import { installNuxtSiteConfig, updateSiteConfig } from 'nuxt-site-config-kit';
14
16
  import { provider } from 'std-env';
17
+ import { hash } from 'ohash';
15
18
  import playwrightCore from 'playwright-core';
16
- import { existsSync } from 'node:fs';
17
19
  import { createBirpcGroup } from 'birpc';
18
20
  import { stringify, parse } from 'flatted';
19
21
  import { addDependency } from 'nypm';
20
22
 
23
+ const version = "2.0.5";
24
+
21
25
  async function createBrowser() {
22
26
  if (process.dev || process.env.prerender) {
23
27
  try {
@@ -186,15 +190,20 @@ function decodeObjectHtmlEntities(obj) {
186
190
  });
187
191
  return obj;
188
192
  }
189
- function extractOgImageOptions(html) {
193
+ function extractOgImageOptions(html, routeRules) {
190
194
  const htmlPayload = html.match(/<script id="nuxt-og-image-options" type="application\/json">(.+?)<\/script>/)?.[1];
191
195
  if (!htmlPayload)
192
196
  return false;
193
197
  let options;
194
198
  try {
195
- options = JSON.parse(htmlPayload);
199
+ const payload = JSON.parse(htmlPayload);
200
+ Object.entries(payload).forEach(([key, value]) => {
201
+ if (!value)
202
+ delete payload[key];
203
+ });
204
+ options = defu(payload, routeRules);
196
205
  } catch (e) {
197
- options = false;
206
+ options = routeRules;
198
207
  if (process.dev)
199
208
  console.warn("Failed to parse #nuxt-og-image-options", e, options);
200
209
  }
@@ -318,7 +327,7 @@ function getNitroProviderCompatibility(defaults, nuxt = useNuxt()) {
318
327
  return false;
319
328
  compatibility = lookup || {};
320
329
  }
321
- compatibility = defu(compatibility, defaults);
330
+ compatibility = defu$1(compatibility, defaults);
322
331
  compatibility.inlineCss = compatibility.inlineCss || (compatibility.node ? "node" : "mock");
323
332
  return compatibility;
324
333
  }
@@ -331,9 +340,9 @@ function ensureDependencies(nuxt, dep) {
331
340
  function extendTypes(module, template) {
332
341
  const nuxt = useNuxt();
333
342
  addTemplate({
334
- filename: `${module}.d.ts`,
335
- getContents: () => {
336
- const s = template();
343
+ filename: `module/${module}.d.ts`,
344
+ getContents: async () => {
345
+ const s = await template();
337
346
  return `// Generated by ${module}
338
347
  ${s}
339
348
  export {}
@@ -341,7 +350,7 @@ export {}
341
350
  }
342
351
  });
343
352
  nuxt.hooks.hook("prepare:types", ({ references }) => {
344
- references.push({ path: resolve(nuxt.options.buildDir, `${module}.d.ts`) });
353
+ references.push({ path: resolve(nuxt.options.buildDir, `module/${module}.d.ts`) });
345
354
  });
346
355
  }
347
356
 
@@ -408,9 +417,6 @@ const module = defineNuxtModule({
408
417
  _context: "nuxt-og-image:config",
409
418
  url: config.siteUrl || config.host
410
419
  });
411
- requireSiteConfig("nuxt-og-image", {
412
- url: "Required to generate absolute URLs for the og:image."
413
- }, { prerender: true });
414
420
  nuxt.options.nitro.storage = nuxt.options.nitro.storage || {};
415
421
  if (nuxt.options._generate) {
416
422
  nuxt.options.nitro.storage["og-image"] = {
@@ -429,12 +435,16 @@ const module = defineNuxtModule({
429
435
  };
430
436
  nuxt.options.experimental.componentIslands = true;
431
437
  extendTypes("nuxt-og-image", () => {
432
- return `interface NuxtOgImageNitroRules {
433
- ogImage?: false | Record<string, any>
434
- }
438
+ return `
439
+ import type { OgImageOptions } from '${resolve("./runtime/types")}'
440
+
435
441
  declare module 'nitropack' {
436
- interface NitroRouteRules extends NuxtOgImageNitroRules {}
437
- interface NitroRouteConfig extends NuxtOgImageNitroRules {}
442
+ interface NitroRouteRules {
443
+ ogImage?: false | OgImageOptions
444
+ }
445
+ interface NitroRouteConfig {
446
+ ogImage?: false | OgImageOptions
447
+ }
438
448
  }`;
439
449
  });
440
450
  addServerHandler({
@@ -520,13 +530,18 @@ declare module 'nitropack' {
520
530
  components.forEach((component) => {
521
531
  let valid = false;
522
532
  config.componentDirs.forEach((dir) => {
523
- if (component.pascalName.startsWith(dir) || component.kebabName.startsWith(dir))
533
+ if (component.pascalName.startsWith(dir) || component.kebabName.startsWith(dir) || component.shortPath.includes(`/${dir}/`))
524
534
  valid = true;
525
535
  });
526
- if (valid) {
536
+ if (valid || component.pascalName === "OgImageTemplateFoo") {
527
537
  component.island = true;
528
538
  component.mode = "server";
529
- ogImageComponents.push({ pascalName: component.pascalName, kebabName: component.kebabName });
539
+ ogImageComponents.push({
540
+ // purge cache when component changes
541
+ hash: hash(fs.readFileSync(component.filePath, "utf-8")),
542
+ pascalName: component.pascalName,
543
+ kebabName: component.kebabName
544
+ });
530
545
  }
531
546
  });
532
547
  });
@@ -557,6 +572,7 @@ declare module 'nitropack' {
557
572
  nuxt.hooks.hook("modules:done", async () => {
558
573
  nuxt.hooks.callHook("og-image:config", config);
559
574
  nuxt.options.runtimeConfig["nuxt-og-image"] = {
575
+ version,
560
576
  satoriOptions: config.satoriOptions,
561
577
  runtimeSatori: config.runtimeSatori,
562
578
  runtimeBrowser: config.runtimeBrowser,
@@ -587,7 +603,7 @@ declare module 'nitropack' {
587
603
  };
588
604
  });
589
605
  nuxt.hooks.hook("nitro:config", async (nitroConfig) => {
590
- nitroConfig.externals = defu(nitroConfig.externals || {}, {
606
+ nitroConfig.externals = defu$1(nitroConfig.externals || {}, {
591
607
  inline: [runtimeDir]
592
608
  });
593
609
  if (config.runtimeBrowser) {
@@ -704,15 +720,14 @@ export async function useProvider(provider) {
704
720
  const html = ctx.contents;
705
721
  if (!html)
706
722
  return;
707
- const extractedOptions = extractOgImageOptions(html);
708
- const routeRules = defu({}, ..._routeRulesMatcher.matchAll(ctx.route).reverse());
723
+ const routeRules = defu$1({}, ..._routeRulesMatcher.matchAll(ctx.route).reverse());
724
+ const extractedOptions = extractOgImageOptions(html, routeRules.ogImage || {});
709
725
  if (!extractedOptions || routeRules.ogImage === false)
710
726
  return;
711
727
  const entry = {
712
728
  route: ctx.route,
713
729
  path: extractedOptions.component ? `/api/og-image-html?path=${ctx.route}` : ctx.route,
714
- ...extractedOptions,
715
- ...routeRules.ogImage || {}
730
+ ...extractedOptions
716
731
  };
717
732
  if ((nuxt.options._generate || entry.cache) && entry.provider === "browser")
718
733
  screenshotQueue.push(entry);
@@ -749,23 +764,29 @@ export async function useProvider(provider) {
749
764
  browser = await createBrowser();
750
765
  if (browser) {
751
766
  nitro.logger.info(`Prerendering ${screenshotQueue.length} og:image screenshots...`);
752
- for (const entry of screenshotQueue) {
767
+ for (const k in screenshotQueue) {
768
+ let entry = screenshotQueue[k];
753
769
  if (entry.route && Object.keys(entry).length === 1) {
754
770
  const html = await $fetch(entry.route, { baseURL: withBase(nuxt.options.app.baseURL, host) });
755
- const extractedOptions = extractOgImageOptions(html);
756
- const routeRules = defu({}, ..._routeRulesMatcher.matchAll(entry.route).reverse());
757
- Object.assign(entry, {
758
- // @ts-expect-error runtime
759
- path: extractedOptions.component ? `/api/og-image-html?path=${entry.route}` : entry.route,
760
- ...extractedOptions,
761
- ...routeRules.ogImage || {}
762
- });
771
+ const routeRules = defu$1({}, ..._routeRulesMatcher.matchAll(entry.route).reverse());
772
+ const extractedOptions = extractOgImageOptions(html, routeRules.ogImage || {});
773
+ if (!extractedOptions || routeRules.ogImage === false) {
774
+ entry.skip = true;
775
+ continue;
776
+ }
777
+ screenshotQueue[k] = entry = defu$1(
778
+ { path: extractedOptions.component ? `/api/og-image-html?path=${entry.route}` : entry.route },
779
+ entry,
780
+ extractedOptions
781
+ );
763
782
  }
764
- if (entry.component)
783
+ if (!entry.skip && entry.component)
765
784
  entry.html = await globalThis.$fetch(entry.path);
766
785
  }
767
786
  for (const k in screenshotQueue) {
768
787
  const entry = screenshotQueue[k];
788
+ if (entry.skip)
789
+ continue;
769
790
  const start = Date.now();
770
791
  let hasError = false;
771
792
  const dirname2 = joinURL(nitro.options.output.publicDir, entry.route, "/__og_image__/");
@@ -1,5 +1,5 @@
1
1
  /// <reference types="node" />
2
2
  import type { Buffer } from 'node:buffer';
3
3
  import type { Browser } from 'playwright-core';
4
- import type { ScreenshotOptions } from '../types';
4
+ import type { ScreenshotOptions } from './types';
5
5
  export declare function screenshot(browser: Browser, options: Partial<ScreenshotOptions> & Record<string, any>): Promise<Buffer>;
@@ -1,4 +1,4 @@
1
- import type { OgImageOptions } from '../../../types';
1
+ import type { OgImageOptions } from '../../types';
2
2
  declare const _default: import("vue").DefineComponent<OgImageOptions, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<OgImageOptions>>, {
3
3
  [x: string]: any;
4
4
  }, {}>;
@@ -1,4 +1,4 @@
1
- import type { OgImageOptions } from '../../../types';
1
+ import type { OgImageOptions } from '../../types';
2
2
  /**
3
3
  * @deprecated Use OgImageWithoutCache
4
4
  */
@@ -1,4 +1,4 @@
1
- import type { OgImageScreenshotOptions } from '../../../types';
1
+ import type { OgImageScreenshotOptions } from '../../types';
2
2
  declare const _default: import("vue").DefineComponent<OgImageScreenshotOptions, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<OgImageScreenshotOptions>>, {
3
3
  [x: string]: any;
4
4
  [x: number]: any;
@@ -1,4 +1,4 @@
1
- import type { OgImageOptions } from '../../../types';
1
+ import type { OgImageOptions } from '../../types';
2
2
  /**
3
3
  * @deprecated Use OgImageCached instead
4
4
  */
@@ -1,4 +1,4 @@
1
- import type { OgImageOptions } from '../../../types';
1
+ import type { OgImageOptions } from '../../types';
2
2
  declare const _default: import("vue").DefineComponent<OgImageOptions, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<OgImageOptions>>, {
3
3
  [x: string]: any;
4
4
  }, {}>;
@@ -1,4 +1,4 @@
1
- import type { OgImageOptions } from '../../../types';
1
+ import type { OgImageOptions } from '../../types';
2
2
  declare const _default: import("vue").DefineComponent<OgImageOptions, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<OgImageOptions>>, {
3
3
  [x: string]: any;
4
4
  }, {}>;
@@ -1,4 +1,4 @@
1
- import type { OgImageOptions, OgImageScreenshotOptions } from '../../types';
1
+ import type { OgImageOptions, OgImageScreenshotOptions } from '../types';
2
2
  export declare function defineOgImageScreenshot(options?: OgImageScreenshotOptions): Promise<void>;
3
3
  /**
4
4
  * @deprecated Use `defineOgImage` or `defineOgImageCached` instead
@@ -1,2 +1,2 @@
1
- import type { OgImageOptions } from '../../types';
1
+ import type { OgImageOptions } from '../types';
2
2
  export declare function normaliseOgImageOptions(_options: OgImageOptions): any;
@@ -11,14 +11,11 @@ export function normaliseOgImageOptions(_options) {
11
11
  options.provider = "browser";
12
12
  if (options.component && componentNames) {
13
13
  const originalName = options.component;
14
- let isValid = componentNames.some((component) => component.pascalName === originalName || component.kebabName === originalName);
15
- if (!isValid) {
16
- for (const component of componentNames) {
17
- if (component.pascalName.endsWith(originalName) || component.kebabName.endsWith(originalName)) {
18
- options.component = component.pascalName;
19
- isValid = true;
20
- break;
21
- }
14
+ for (const component of componentNames) {
15
+ if (component.pascalName.endsWith(originalName) || component.kebabName.endsWith(originalName)) {
16
+ options.component = component.pascalName;
17
+ options.componentHash = component.hash;
18
+ break;
22
19
  }
23
20
  }
24
21
  }
@@ -7,7 +7,7 @@ import { fetchOptions } from "../utils.mjs";
7
7
  import { useProvider } from "#nuxt-og-image/provider";
8
8
  import { useNitroOrigin, useRuntimeConfig, useStorage } from "#imports";
9
9
  export default defineEventHandler(async (e) => {
10
- const { runtimeBrowser, runtimeCacheStorage } = useRuntimeConfig()["nuxt-og-image"];
10
+ const { runtimeBrowser, runtimeCacheStorage, version } = useRuntimeConfig()["nuxt-og-image"];
11
11
  const path = parseURL(e.path).pathname;
12
12
  if (!path.endsWith("__og_image__/og.png"))
13
13
  return;
@@ -25,7 +25,7 @@ export default defineEventHandler(async (e) => {
25
25
  });
26
26
  }
27
27
  const useCache = runtimeCacheStorage && !process.dev && options.cacheTtl && options.cacheTtl > 0 && options.cache;
28
- const baseCacheKey = runtimeCacheStorage === "default" ? "/cache/og-image" : "/og-image";
28
+ const baseCacheKey = runtimeCacheStorage === "default" ? `/cache/og-image${version}` : `/og-image/${version}`;
29
29
  const cache = prefixStorage(useStorage(), `${baseCacheKey}/images`);
30
30
  const key = [options.path === "/" || !options.path ? "index" : options.path, hash(options)].join(":");
31
31
  let png;
@@ -1,4 +1,4 @@
1
1
  /// <reference types="node" />
2
2
  import type { ResvgRenderOptions } from '@resvg/resvg-js';
3
- import type { RuntimeOgImageOptions } from '../../../../types';
3
+ import type { RuntimeOgImageOptions } from '../../../types';
4
4
  export default function (svg: string, options: ResvgRenderOptions & RuntimeOgImageOptions): Promise<Buffer>;
@@ -1,3 +1,3 @@
1
1
  import type { ResvgRenderOptions } from '@resvg/resvg-wasm';
2
- import type { RuntimeOgImageOptions } from '../../../../types';
2
+ import type { RuntimeOgImageOptions } from '../../../types';
3
3
  export default function (svg: string, options: ResvgRenderOptions & RuntimeOgImageOptions): Promise<Uint8Array>;
@@ -1,3 +1,3 @@
1
1
  import type { ConvertOptions } from 'svg2png-wasm';
2
- import type { RuntimeOgImageOptions } from '../../../../types';
2
+ import type { RuntimeOgImageOptions } from '../../../types';
3
3
  export default function (svg: string, options: ConvertOptions & RuntimeOgImageOptions): Promise<Uint8Array>;
@@ -1,3 +1,3 @@
1
1
  import type { SatoriOptions } from 'satori';
2
- import type { RuntimeOgImageOptions } from '../../../../types';
2
+ import type { RuntimeOgImageOptions } from '../../../types';
3
3
  export default function (nodes: string, options: SatoriOptions & RuntimeOgImageOptions): Promise<string>;
@@ -1,3 +1,3 @@
1
- import type { Renderer } from '../../../types';
1
+ import type { Renderer } from '../../types';
2
2
  declare const BrowserRenderer: Renderer;
3
3
  export default BrowserRenderer;
@@ -1,3 +1,3 @@
1
- import type { Renderer } from '../../../../types';
1
+ import type { Renderer } from '../../../types';
2
2
  declare const SatoriRenderer: Renderer;
3
3
  export default SatoriRenderer;
@@ -1,2 +1,2 @@
1
- declare const _default: import("../../../../../types").SatoriTransformer | import("../../../../../types").SatoriTransformer[];
1
+ declare const _default: import("../../../../types").SatoriTransformer | import("../../../../types").SatoriTransformer[];
2
2
  export default _default;
@@ -1,2 +1,2 @@
1
- declare const _default: import("../../../../../types").SatoriTransformer | import("../../../../../types").SatoriTransformer[];
1
+ declare const _default: import("../../../../types").SatoriTransformer | import("../../../../types").SatoriTransformer[];
2
2
  export default _default;
@@ -1,2 +1,2 @@
1
- declare const _default: import("../../../../../types").SatoriTransformer | import("../../../../../types").SatoriTransformer[];
1
+ declare const _default: import("../../../../types").SatoriTransformer | import("../../../../types").SatoriTransformer[];
2
2
  export default _default;
@@ -1,2 +1,2 @@
1
- declare const _default: import("../../../../../types").SatoriTransformer | import("../../../../../types").SatoriTransformer[];
1
+ declare const _default: import("../../../../types").SatoriTransformer | import("../../../../types").SatoriTransformer[];
2
2
  export default _default;
@@ -1,2 +1,2 @@
1
- declare const _default: import("../../../../../types").SatoriTransformer | import("../../../../../types").SatoriTransformer[];
1
+ declare const _default: import("../../../../types").SatoriTransformer | import("../../../../types").SatoriTransformer[];
2
2
  export default _default;
@@ -1,4 +1,4 @@
1
- import type { FontConfig, RuntimeOgImageOptions, SatoriTransformer, VNode } from '../../../../types';
1
+ import type { FontConfig, RuntimeOgImageOptions, SatoriTransformer, VNode } from '../../../types';
2
2
  export declare function loadFont(requestOrigin: string, font: FontConfig): Promise<any>;
3
3
  export declare function walkSatoriTree(node: VNode, plugins: (SatoriTransformer | SatoriTransformer[])[], props: RuntimeOgImageOptions): Promise<void>;
4
4
  export declare function defineSatoriTransformer(transformer: SatoriTransformer | SatoriTransformer[]): SatoriTransformer | SatoriTransformer[];
@@ -1,3 +1,3 @@
1
- import type { RuntimeOgImageOptions } from '../../../types';
1
+ import type { RuntimeOgImageOptions } from '../../types';
2
2
  declare const _default: import("h3").EventHandler<false | RuntimeOgImageOptions>;
3
3
  export default _default;
@@ -16,21 +16,21 @@ export default defineEventHandler(async (e) => {
16
16
  statusMessage: `Failed to read the path ${path} for og-image extraction. ${err.message}.`
17
17
  });
18
18
  }
19
- const extractedPayload = extractOgImageOptions(html);
20
- if (!extractedPayload) {
21
- throw createError({
22
- statusCode: 500,
23
- statusMessage: `The path ${path} is missing the og-image payload.`
24
- });
25
- }
26
19
  e.node.req.url = path;
27
20
  const oldRouteRules = e.context._nitro.routeRules;
28
21
  e.context._nitro.routeRules = void 0;
29
- const routeRules = getRouteRules(e)?.ogImage;
22
+ const routeRules = getRouteRules(e)?.ogImage || {};
30
23
  e.context._nitro.routeRules = oldRouteRules;
31
24
  e.node.req.url = e.path;
32
25
  if (routeRules === false)
33
26
  return false;
27
+ const extractedPayload = extractOgImageOptions(html, routeRules);
28
+ if (!extractedPayload) {
29
+ throw createError({
30
+ statusCode: 500,
31
+ statusMessage: `The path ${path} is missing the og-image payload.`
32
+ });
33
+ }
34
34
  const { defaults } = useRuntimeConfig()["nuxt-og-image"];
35
35
  return defu(
36
36
  extractedPayload,
@@ -1,3 +1,3 @@
1
- import type { OgImageOptions } from '../../types';
1
+ import type { OgImageOptions } from '../types';
2
2
  export declare function decodeHtml(html: string): string;
3
- export declare function extractOgImageOptions(html: string): OgImageOptions | false;
3
+ export declare function extractOgImageOptions(html: string, routeRules: OgImageOptions): OgImageOptions | false;
@@ -1,3 +1,4 @@
1
+ import { defu } from "defu";
1
2
  export function decodeHtml(html) {
2
3
  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
4
  return String.fromCharCode(Number.parseInt(int));
@@ -10,15 +11,20 @@ function decodeObjectHtmlEntities(obj) {
10
11
  });
11
12
  return obj;
12
13
  }
13
- export function extractOgImageOptions(html) {
14
+ export function extractOgImageOptions(html, routeRules) {
14
15
  const htmlPayload = html.match(/<script id="nuxt-og-image-options" type="application\/json">(.+?)<\/script>/)?.[1];
15
16
  if (!htmlPayload)
16
17
  return false;
17
18
  let options;
18
19
  try {
19
- options = JSON.parse(htmlPayload);
20
+ const payload = JSON.parse(htmlPayload);
21
+ Object.entries(payload).forEach(([key, value]) => {
22
+ if (!value)
23
+ delete payload[key];
24
+ });
25
+ options = defu(payload, routeRules);
20
26
  } catch (e) {
21
- options = false;
27
+ options = routeRules;
22
28
  if (process.dev)
23
29
  console.warn("Failed to parse #nuxt-og-image-options", e, options);
24
30
  }
@@ -1,7 +1,7 @@
1
1
  /// <reference types="node" />
2
2
  import { Buffer } from 'node:buffer';
3
3
  import type { H3Event } from 'h3';
4
- import type { RuntimeOgImageOptions } from '../../types';
4
+ import type { RuntimeOgImageOptions } from '../types';
5
5
  export declare function wasmLoader(asyncModuleLoad: Promise<any> | Buffer | string, fallback: string): {
6
6
  load(options: RuntimeOgImageOptions): Promise<any>;
7
7
  };
@@ -37,11 +37,10 @@ export function wasmLoader(asyncModuleLoad, fallback) {
37
37
  };
38
38
  }
39
39
  export async function fetchOptions(e, path) {
40
- const { runtimeCacheStorage } = useRuntimeConfig()["nuxt-og-image"];
41
- const baseCacheKey = runtimeCacheStorage === "default" ? "/cache/og-image" : "/og-image";
40
+ const { runtimeCacheStorage, version } = useRuntimeConfig()["nuxt-og-image"];
41
+ const baseCacheKey = runtimeCacheStorage === "default" ? `/cache/og-image${version}` : `/og-image/${version}`;
42
42
  const cache = runtimeCacheStorage || process.env.prerender ? prefixStorage(useStorage(), `${baseCacheKey}/options`) : false;
43
- let key = path.replace("/__og_image__/og.png", "");
44
- key = key === "/" || !key ? "index" : key;
43
+ const key = [path === "/" || !path ? "index" : path].join(":");
45
44
  let options;
46
45
  if (!process.dev && cache && await cache.hasItem(key)) {
47
46
  const cachedValue = await cache.getItem(key);
@@ -61,7 +60,7 @@ export async function fetchOptions(e, path) {
61
60
  await cache.setItem(key, {
62
61
  value: options,
63
62
  // cache for 1 minute or 5 seconds, avoids subsequent internal fetches
64
- expiresAt: Date.now() + (options.cache ? 60 * 60 * 1e3 : 5 * 1e3)
63
+ expiresAt: Date.now() + (options.cache ? 60 * 1e3 : 5 * 1e3)
65
64
  });
66
65
  }
67
66
  }
@@ -0,0 +1,69 @@
1
+ /// <reference types="node" />
2
+ import type { Buffer } from 'node:buffer';
3
+ import type { html } from 'satori-html';
4
+ import type { ModuleOptions } from '../module';
5
+ export interface ScreenshotOptions {
6
+ colorScheme?: 'dark' | 'light';
7
+ selector?: string;
8
+ mask?: string;
9
+ /**
10
+ * The width of the screenshot.
11
+ *
12
+ * @default 1200
13
+ */
14
+ width: number;
15
+ /**
16
+ * The height of the screenshot.
17
+ *
18
+ * @default 630
19
+ */
20
+ height: number;
21
+ /**
22
+ * How long to wait before taking the screenshot. Useful for waiting for animations.
23
+ */
24
+ delay?: number;
25
+ }
26
+ export interface OgImageOptions extends Partial<ScreenshotOptions> {
27
+ provider?: 'browser' | 'satori';
28
+ title?: string;
29
+ description?: string;
30
+ component?: string | null;
31
+ alt?: string;
32
+ cache?: boolean;
33
+ cacheKey?: string;
34
+ cacheTtl?: number;
35
+ /**
36
+ * @deprecated Use `cache` instead
37
+ */
38
+ static?: boolean;
39
+ [key: string]: any;
40
+ }
41
+ export interface RuntimeOgImageOptions extends OgImageOptions {
42
+ path: string;
43
+ requestOrigin: string;
44
+ }
45
+ export interface FontConfig {
46
+ name: string;
47
+ weight: number;
48
+ path?: string;
49
+ }
50
+ export type InputFontConfig = (`${string}:${number}` | FontConfig);
51
+ export interface Renderer {
52
+ name: 'browser' | 'satori';
53
+ createSvg: (options: RuntimeOgImageOptions) => Promise<string>;
54
+ createPng: (options: RuntimeOgImageOptions) => Promise<Buffer>;
55
+ createVNode: (options: RuntimeOgImageOptions) => Promise<VNode>;
56
+ }
57
+ export type OgImageScreenshotOptions = Omit<OgImageOptions, 'component'>;
58
+ export interface PlaygroundServerFunctions {
59
+ openInEditor(filepath: string): void;
60
+ getConfig(): ModuleOptions;
61
+ }
62
+ export interface PlaygroundClientFunctions {
63
+ refresh(type: string): void;
64
+ }
65
+ export type VNode = ReturnType<typeof html>;
66
+ export interface SatoriTransformer {
67
+ filter: (node: VNode) => boolean;
68
+ transform: (node: VNode, props: RuntimeOgImageOptions) => Promise<void>;
69
+ }
File without changes
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "nuxt-og-image",
3
3
  "type": "module",
4
- "version": "2.0.3",
5
- "packageManager": "pnpm@8.6.5",
4
+ "version": "2.0.5",
5
+ "packageManager": "pnpm@8.6.6",
6
6
  "description": "Enlightened OG Image generation for Nuxt.",
7
7
  "license": "MIT",
8
8
  "funding": "https://github.com/sponsors/harlan-zw",
@@ -27,7 +27,7 @@
27
27
  "dist"
28
28
  ],
29
29
  "dependencies": {
30
- "@nuxt/kit": "^3.6.1",
30
+ "@nuxt/kit": "^3.6.2",
31
31
  "@resvg/resvg-js": "^2.4.1",
32
32
  "@resvg/resvg-wasm": "^2.4.1",
33
33
  "@types/fs-extra": "^11.0.1",
@@ -39,12 +39,12 @@
39
39
  "fast-glob": "^3.3.0",
40
40
  "flatted": "^3.2.7",
41
41
  "fs-extra": "^11.1.1",
42
- "globby": "^13.2.1",
42
+ "globby": "^13.2.2",
43
43
  "image-size": "^1.0.2",
44
44
  "inline-css": "^4.0.2",
45
45
  "launch-editor": "^2.6.0",
46
- "nuxt-site-config": "^0.8.1",
47
- "nuxt-site-config-kit": "^0.8.1",
46
+ "nuxt-site-config": "^1.0.3",
47
+ "nuxt-site-config-kit": "^1.0.3",
48
48
  "nypm": "^0.2.2",
49
49
  "ofetch": "^1.1.1",
50
50
  "ohash": "^1.1.2",
@@ -63,20 +63,23 @@
63
63
  "yoga-wasm-web": "^0.3.3"
64
64
  },
65
65
  "devDependencies": {
66
- "@antfu/eslint-config": "^0.39.6",
67
- "@nuxt/devtools-edge": "0.6.6-28139075.95f3dd8",
66
+ "@antfu/eslint-config": "^0.39.7",
67
+ "@nuxt/devtools-edge": "0.6.6-28142701.2977264",
68
68
  "@nuxt/module-builder": "^0.4.0",
69
- "@nuxt/test-utils": "3.6.1",
69
+ "@nuxt/test-utils": "3.6.2",
70
70
  "@nuxtjs/eslint-config-typescript": "^12.0.0",
71
71
  "@types/ws": "^8.5.5",
72
72
  "bumpp": "^9.1.1",
73
73
  "eslint": "8.44.0",
74
74
  "jest-image-snapshot": "^6.1.0",
75
- "nuxt": "^3.6.1",
75
+ "nuxt": "^3.6.2",
76
76
  "nuxt-icon": "^0.4.2",
77
77
  "playwright": "^1.35.1",
78
78
  "sass": "^1.63.6",
79
- "vitest": "^0.32.4"
79
+ "vitest": "^0.33.0"
80
+ },
81
+ "resolutions": {
82
+ "@nuxt/schema": "3.6.2"
80
83
  },
81
84
  "scripts": {
82
85
  "build": "pnpm dev:prepare && pnpm build:module && pnpm build:client",