nuxt-og-image 2.0.0-beta.2 → 2.0.0-beta.22

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 (72) hide show
  1. package/README.md +172 -44
  2. package/dist/client/200.html +2 -2
  3. package/dist/client/404.html +2 -2
  4. package/dist/client/_nuxt/IconCSS.779331aa.js +1 -0
  5. package/dist/client/_nuxt/{ImageLoader.9bf39d71.js → ImageLoader.9ed308b0.js} +1 -1
  6. package/dist/client/_nuxt/entry.acc10163.css +1 -0
  7. package/dist/client/_nuxt/entry.e7270163.js +5 -0
  8. package/dist/client/_nuxt/{error-404.1ff52902.js → error-404.dcc06a80.js} +1 -1
  9. package/dist/client/_nuxt/{error-500.f7d30da5.js → error-500.fb40d400.js} +1 -1
  10. package/dist/client/_nuxt/{error-component.cf7543e5.js → error-component.9702a511.js} +2 -2
  11. package/dist/client/_nuxt/{index.3f356409.js → index.6a247c9d.js} +1 -1
  12. package/dist/client/_nuxt/{options.56a3e5f9.js → options.481faa9f.js} +1 -1
  13. package/dist/client/_nuxt/{png.37f3e77b.js → png.7e62d84b.js} +1 -1
  14. package/dist/client/_nuxt/{shiki.3a930bb8.js → shiki.0c927d45.js} +1 -1
  15. package/dist/client/_nuxt/{svg.186c6bd1.js → svg.81bf3f5a.js} +1 -1
  16. package/dist/client/_nuxt/{vnodes.a799f183.js → vnodes.096af306.js} +1 -1
  17. package/dist/client/index.html +2 -2
  18. package/dist/client/options/index.html +2 -2
  19. package/dist/client/png/index.html +2 -2
  20. package/dist/client/svg/index.html +2 -2
  21. package/dist/client/vnodes/index.html +2 -2
  22. package/dist/module.d.ts +15 -6
  23. package/dist/module.json +1 -1
  24. package/dist/module.mjs +239 -117
  25. package/dist/runtime/browserUtil.d.ts +1 -0
  26. package/dist/runtime/browserUtil.mjs +10 -5
  27. package/dist/runtime/composables/defineOgImage.mjs +14 -12
  28. package/dist/runtime/nitro/middleware/og.png.mjs +50 -7
  29. package/dist/runtime/nitro/middleware/playground.mjs +4 -3
  30. package/dist/runtime/nitro/plugins/prerender.d.ts +3 -0
  31. package/dist/runtime/nitro/plugins/prerender.mjs +18 -0
  32. package/dist/runtime/nitro/providers/browser/lambda.d.ts +1 -1
  33. package/dist/runtime/nitro/providers/browser/lambda.mjs +5 -5
  34. package/dist/runtime/nitro/providers/browser/{node.mjs → playwright.mjs} +0 -9
  35. package/dist/runtime/nitro/providers/browser/universal.d.ts +1 -0
  36. package/dist/runtime/nitro/providers/browser/universal.mjs +33 -0
  37. package/dist/runtime/nitro/providers/png/resvg.d.ts +4 -0
  38. package/dist/runtime/nitro/providers/png/resvg.mjs +11 -0
  39. package/dist/runtime/nitro/providers/png/svg2png.mjs +11 -0
  40. package/dist/runtime/nitro/providers/satori/{webworker.mjs → yoga-wasm.mjs} +4 -5
  41. package/dist/runtime/nitro/renderers/browser.mjs +12 -6
  42. package/dist/runtime/nitro/renderers/satori/index.mjs +3 -3
  43. package/dist/runtime/nitro/renderers/satori/plugins/encoding.mjs +2 -1
  44. package/dist/runtime/nitro/renderers/satori/utils.mjs +1 -0
  45. package/dist/runtime/nitro/routes/debug.d.ts +4 -0
  46. package/dist/runtime/nitro/routes/debug.mjs +9 -0
  47. package/dist/runtime/nitro/routes/html.mjs +11 -8
  48. package/dist/runtime/nitro/routes/options.mjs +9 -6
  49. package/dist/runtime/nitro/routes/svg.mjs +3 -1
  50. package/dist/runtime/nitro/routes/vnode.mjs +3 -1
  51. package/dist/runtime/nitro/util-hostname.d.ts +2 -0
  52. package/dist/runtime/nitro/util-hostname.mjs +15 -0
  53. package/dist/runtime/nitro/utils-pure.d.ts +3 -2
  54. package/dist/runtime/nitro/utils-pure.mjs +16 -13
  55. package/dist/runtime/nitro/utils.d.ts +6 -4
  56. package/dist/runtime/nitro/utils.mjs +44 -33
  57. package/dist/runtime/public-assets/__nuxt_og_image__/browser-provider-not-supported.png +0 -0
  58. package/dist/runtime/public-assets-optional/resvg/resvg.wasm +0 -0
  59. package/package.json +27 -19
  60. package/dist/client/_nuxt/IconCSS.a041aca0.js +0 -1
  61. package/dist/client/_nuxt/entry.74018bda.js +0 -5
  62. package/dist/client/_nuxt/entry.7a8c1ab2.css +0 -1
  63. package/dist/runtime/nitro/providers/svg2png/universal.mjs +0 -9
  64. /package/dist/runtime/nitro/providers/browser/{node.d.ts → playwright.d.ts} +0 -0
  65. /package/dist/runtime/nitro/providers/{svg2png/universal.d.ts → png/svg2png.d.ts} +0 -0
  66. /package/dist/runtime/nitro/providers/satori/{node.d.ts → default.d.ts} +0 -0
  67. /package/dist/runtime/nitro/providers/satori/{node.mjs → default.mjs} +0 -0
  68. /package/dist/runtime/nitro/providers/satori/{webworker.d.ts → yoga-wasm.d.ts} +0 -0
  69. /package/dist/runtime/{public-assets → public-assets-optional/inter-font}/inter-latin-ext-400-normal.woff +0 -0
  70. /package/dist/runtime/{public-assets → public-assets-optional/inter-font}/inter-latin-ext-700-normal.woff +0 -0
  71. /package/dist/runtime/{public-assets → public-assets-optional/svg2png}/svg2png.wasm +0 -0
  72. /package/dist/runtime/{public-assets → public-assets-optional/yoga}/yoga.wasm +0 -0
@@ -1,19 +1,21 @@
1
- import { createError, defineEventHandler, setHeader } from "h3";
2
- import { parseURL, withBase, withoutTrailingSlash } from "ufo";
1
+ import { Buffer } from "node:buffer";
2
+ import { createError, defineEventHandler, sendRedirect, setHeader } from "h3";
3
+ import { joinURL, parseURL, withBase, withoutTrailingSlash } from "ufo";
4
+ import { prefixStorage } from "unstorage";
3
5
  import { fetchOptions, useHostname } from "../utils.mjs";
4
6
  import { useProvider } from "#nuxt-og-image/provider";
7
+ import { useRuntimeConfig, useStorage } from "#imports";
5
8
  export default defineEventHandler(async (e) => {
9
+ const { runtimeBrowser, runtimeCacheStorage } = useRuntimeConfig()["nuxt-og-image"];
6
10
  const path = parseURL(e.path).pathname;
7
11
  if (!path.endsWith("__og_image__/og.png"))
8
12
  return;
9
13
  const basePath = withoutTrailingSlash(
10
14
  path.replace("__og_image__/og.png", "")
11
15
  );
12
- setHeader(e, "Content-Type", "image/png");
13
- setHeader(e, "Cache-Control", "no-cache, no-store, must-revalidate");
14
- setHeader(e, "Pragma", "no-cache");
15
- setHeader(e, "Expires", "0");
16
16
  const options = await fetchOptions(e, basePath);
17
+ if (process.env.NODE_ENV === "production" && !process.env.prerender && !runtimeBrowser && options.provider === "browser")
18
+ return sendRedirect(e, joinURL(useHostname(e), "__nuxt_og_image__/browser-provider-not-supported.png"));
17
19
  const provider = await useProvider(options.provider);
18
20
  if (!provider) {
19
21
  throw createError({
@@ -21,5 +23,46 @@ export default defineEventHandler(async (e) => {
21
23
  statusMessage: `Provider ${options.provider} is missing.`
22
24
  });
23
25
  }
24
- return provider.createPng(withBase(basePath, useHostname(e)), options);
26
+ const cache = prefixStorage(useStorage(), "og-image-cache:images");
27
+ const key = options.cacheKey || e.node.req.url;
28
+ let png;
29
+ if (runtimeCacheStorage && await cache.hasItem(key)) {
30
+ const { value, expiresAt } = await cache.getItem(key);
31
+ if (expiresAt > Date.now()) {
32
+ setHeader(e, "Cache-Control", "public, max-age=31536000");
33
+ setHeader(e, "Content-Type", "image/png");
34
+ png = Buffer.from(value, "base64");
35
+ } else {
36
+ await cache.removeItem(key);
37
+ }
38
+ }
39
+ if (!png) {
40
+ try {
41
+ png = await provider.createPng(withBase(basePath, useHostname(e)), options);
42
+ if (png && runtimeCacheStorage && options.static) {
43
+ const base64png = Buffer.from(png).toString("base64");
44
+ await cache.setItem(key, { value: base64png, expiresAt: Date.now() + (options.cacheTtl || 0) });
45
+ }
46
+ } catch (err) {
47
+ throw createError({
48
+ statusCode: 500,
49
+ statusMessage: `Failed to create og image: ${err.message}`
50
+ });
51
+ }
52
+ }
53
+ if (png) {
54
+ if (!process.dev && options.static) {
55
+ setHeader(e, "Cache-Control", "public, max-age=31536000");
56
+ } else {
57
+ setHeader(e, "Cache-Control", "no-cache, no-store, must-revalidate");
58
+ setHeader(e, "Pragma", "no-cache");
59
+ setHeader(e, "Expires", "0");
60
+ }
61
+ setHeader(e, "Content-Type", "image/png");
62
+ return png;
63
+ }
64
+ throw createError({
65
+ statusCode: 500,
66
+ statusMessage: "Failed to create og image, unknown error."
67
+ });
25
68
  });
@@ -1,11 +1,12 @@
1
1
  import { defineEventHandler } from "h3";
2
- import { parseURL, withoutTrailingSlash } from "ufo";
2
+ import { parseURL, withBase, withoutTrailingSlash } from "ufo";
3
3
  import { fetchOptions } from "../utils.mjs";
4
+ import { useRuntimeConfig } from "#imports";
4
5
  export default defineEventHandler(async (e) => {
5
6
  const path = withoutTrailingSlash(parseURL(e.path).pathname);
6
7
  if (!path.endsWith("/__og_image__"))
7
8
  return;
8
- const basePath = path.replace("/__og_image__", "");
9
+ const basePath = withBase(path.replace("/__og_image__", ""), useRuntimeConfig().app.baseURL);
9
10
  const options = await fetchOptions(e, basePath === "" ? "/" : basePath);
10
11
  if (!options)
11
12
  return `The route ${basePath} has not been set up for og:image generation.`;
@@ -22,5 +23,5 @@ export default defineEventHandler(async (e) => {
22
23
  }
23
24
  </style>
24
25
  <title>OG Image Playground</title>
25
- <iframe src="/__nuxt_og_image__/client/?&path=${basePath}"></iframe>`;
26
+ <iframe src="/__nuxt_og_image__/client?&path=${basePath}&base=${useRuntimeConfig().app.baseURL}"></iframe>`;
26
27
  });
@@ -0,0 +1,3 @@
1
+ import type { NitroAppPlugin } from 'nitropack';
2
+ declare const OgImagePrenderNitroPlugin: NitroAppPlugin;
3
+ export default OgImagePrenderNitroPlugin;
@@ -0,0 +1,18 @@
1
+ import { appendHeader } from "h3";
2
+ import { joinURL } from "ufo";
3
+ import { extractOgImageOptions } from "../utils-pure.mjs";
4
+ const OgImagePrenderNitroPlugin = (nitroApp) => {
5
+ if (!process.env.prerender)
6
+ return;
7
+ nitroApp.hooks.hook("render:html", async (ctx, { event }) => {
8
+ const url = event.node.req.url;
9
+ if (url.includes(".") || url.startsWith("/__nuxt_island/"))
10
+ return;
11
+ const options = extractOgImageOptions(ctx.head.join("\n"));
12
+ if (!options)
13
+ return;
14
+ if (options.static && options.provider === "satori")
15
+ appendHeader(event, "x-nitro-prerender", joinURL(url, "/__og_image__/og.png"));
16
+ });
17
+ };
18
+ export default OgImagePrenderNitroPlugin;
@@ -1 +1 @@
1
- export default function createBrowser(): Promise<import("puppeteer-core").Browser>;
1
+ export default function createBrowser(): Promise<import("playwright-core").Browser>;
@@ -1,9 +1,9 @@
1
- import edgeChromium from "chrome-aws-lambda";
2
- import puppeteer from "puppeteer-core";
1
+ import awsChromium from "chrome-aws-lambda";
2
+ import { chromium } from "playwright-core";
3
3
  export default async function createBrowser() {
4
- return puppeteer.launch({
5
- args: edgeChromium.args,
6
- executablePath: await edgeChromium.executablePath,
4
+ return await chromium.launch({
5
+ args: awsChromium.args,
6
+ executablePath: await awsChromium.executablePath,
7
7
  headless: true
8
8
  });
9
9
  }
@@ -1,14 +1,5 @@
1
1
  import playwrightCore from "playwright-core";
2
2
  export default async function createBrowser() {
3
- try {
4
- const { Launcher } = await import(String("chrome-launcher"));
5
- const chromePath = Launcher.getFirstInstallation();
6
- return await playwrightCore.chromium.launch({
7
- headless: true,
8
- executablePath: chromePath
9
- });
10
- } catch (e) {
11
- }
12
3
  try {
13
4
  return await playwrightCore.chromium.launch({
14
5
  headless: true
@@ -0,0 +1 @@
1
+ export default function createBrowser(): Promise<any>;
@@ -0,0 +1,33 @@
1
+ import playwrightCore from "playwright-core";
2
+ export default async function createBrowser() {
3
+ if (process.dev || process.env.prerender) {
4
+ try {
5
+ const { Launcher } = await import(String("chrome-launcher"));
6
+ const chromePath = Launcher.getFirstInstallation();
7
+ return await playwrightCore.chromium.launch({
8
+ headless: true,
9
+ executablePath: chromePath
10
+ });
11
+ } catch (e) {
12
+ }
13
+ }
14
+ try {
15
+ return await playwrightCore.chromium.launch({
16
+ headless: true
17
+ });
18
+ } catch (e) {
19
+ }
20
+ try {
21
+ const playwright = await import(String("playwright"));
22
+ return await playwright.chromium.launch({
23
+ headless: true
24
+ });
25
+ } catch (e) {
26
+ if (process.dev) {
27
+ console.warn("Failed to load chromium instance. Ensure you have chrome installed, otherwise add the dependency: `npm add -D playwright`.");
28
+ } else {
29
+ console.error("Failed to load browser instance. Please open an issue with the exception: https://github.com/harlan-zw/nuxt-og-image/issues.");
30
+ throw e;
31
+ }
32
+ }
33
+ }
@@ -0,0 +1,4 @@
1
+ import type { ResvgRenderOptions } from '@resvg/resvg-wasm';
2
+ export default function (svg: string, options: ResvgRenderOptions & {
3
+ baseUrl: string;
4
+ }): Promise<Uint8Array>;
@@ -0,0 +1,11 @@
1
+ import { Resvg, initWasm } from "@resvg/resvg-wasm";
2
+ import { wasmLoader } from "../../utils.mjs";
3
+ const ReSvgLoader = wasmLoader("/* NUXT_OG_IMAGE_RESVG_WASM */", "/resvg.wasm");
4
+ export default async function(svg, options) {
5
+ const ReSvgWasm = await ReSvgLoader.load({ baseUrl: options.baseUrl });
6
+ await initWasm(ReSvgWasm).catch(() => {
7
+ });
8
+ const resvgJS = new Resvg(svg, {});
9
+ const pngData = resvgJS.render();
10
+ return pngData.asPng();
11
+ }
@@ -0,0 +1,11 @@
1
+ import { initialize, svg2png } from "svg2png-wasm";
2
+ import { wasmLoader } from "../../utils.mjs";
3
+ const Svg2PngLoader = wasmLoader("/* NUXT_OG_IMAGE_SVG2PNG_WASM */", "/svg2png.wasm");
4
+ export default async function(svg, options) {
5
+ const Svg2PngWasm = await Svg2PngLoader.load({ baseUrl: options.baseUrl });
6
+ await initialize(Svg2PngWasm).catch((e) => {
7
+ if (!e.message.trim().endsWith("function can be used only once."))
8
+ throw e;
9
+ });
10
+ return await svg2png(svg, options);
11
+ }
@@ -1,11 +1,10 @@
1
1
  import satori, { init } from "satori/wasm";
2
2
  import initYoga from "yoga-wasm-web";
3
3
  import { wasmLoader } from "../../utils.mjs";
4
+ const YogaLoader = wasmLoader("/* NUXT_OG_IMAGE_YOGA_WASM */", "/yoga.wasm");
4
5
  export default async function(nodes, options) {
5
- const loader = wasmLoader("/* NUXT_OG_IMAGE_YOGA_WASM */", "/yoga.wasm", options.baseUrl);
6
- if (!await loader.loaded()) {
7
- const yoga = await initYoga(await loader.load());
8
- init(yoga);
9
- }
6
+ const yogaWasm = await YogaLoader.load({ baseUrl: options.baseUrl });
7
+ const yoga = await initYoga(yogaWasm);
8
+ init(yoga);
10
9
  return await satori(nodes, options);
11
10
  }
@@ -1,5 +1,7 @@
1
+ import { withBase } from "ufo";
1
2
  import { screenshot } from "../../browserUtil.mjs";
2
- import loadBrowser from "#nuxt-og-image/browser";
3
+ import loadBrowserLauncherChunk from "#nuxt-og-image/browser";
4
+ import { useRuntimeConfig } from "#imports";
3
5
  export default {
4
6
  name: "browser",
5
7
  createSvg: async function createSvg() {
@@ -10,19 +12,23 @@ export default {
10
12
  },
11
13
  createPng: async function createPng(basePath, options) {
12
14
  const url = new URL(basePath);
13
- const createBrowser = await loadBrowser();
14
- const browser = await createBrowser();
15
+ const launchBrowser = await loadBrowserLauncherChunk();
16
+ if (!launchBrowser) {
17
+ throw new Error("Failed to load browser. Is the `browserProvider` enabled?");
18
+ }
19
+ const browser = await launchBrowser();
20
+ let res = null;
15
21
  if (browser) {
16
22
  try {
17
- return await screenshot(browser, {
23
+ res = await screenshot(browser, {
18
24
  ...options,
19
- host: url.origin,
25
+ host: withBase(useRuntimeConfig().app.baseURL, url.origin),
20
26
  path: `/api/og-image-html?path=${url.pathname}`
21
27
  });
22
28
  } finally {
23
29
  browser.close();
24
30
  }
25
31
  }
26
- return null;
32
+ return res;
27
33
  }
28
34
  };
@@ -7,7 +7,7 @@ import twClasses from "./plugins/twClasses.mjs";
7
7
  import flex from "./plugins/flex.mjs";
8
8
  import emojis from "./plugins/emojis.mjs";
9
9
  import encoding from "./plugins/encoding.mjs";
10
- import loadSvg2png from "#nuxt-og-image/svg2png";
10
+ import loadPngCreator from "#nuxt-og-image/png";
11
11
  import loadSatori from "#nuxt-og-image/satori";
12
12
  import { useRuntimeConfig } from "#internal/nitro";
13
13
  const satoriFonts = [];
@@ -21,8 +21,8 @@ export default {
21
21
  name: "satori",
22
22
  createPng: async function createPng(baseUrl, options) {
23
23
  const svg = await this.createSvg(baseUrl, options);
24
- const svg2png = await loadSvg2png();
25
- return svg2png(svg, { baseUrl, ...options });
24
+ const pngCreator = await loadPngCreator();
25
+ return pngCreator(svg, { baseUrl, ...options });
26
26
  },
27
27
  createVNode: async function createVNode(baseUrl, options) {
28
28
  const url = parseURL(baseUrl);
@@ -1,9 +1,10 @@
1
1
  import { defineSatoriTransformer } from "../utils.mjs";
2
+ import { decodeHtml } from "../../../utils-pure.mjs";
2
3
  export default defineSatoriTransformer(() => {
3
4
  return {
4
5
  filter: (node) => typeof node.props?.children === "string",
5
6
  transform: async (node) => {
6
- node.props.children = node.props.children.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&amp;/g, "&").replace(/&quot;/g, '"').replace(/&#x27;/g, "'").replace(/&#x2F;/g, "/");
7
+ node.props.children = decodeHtml(node.props.children);
7
8
  }
8
9
  };
9
10
  });
@@ -1,3 +1,4 @@
1
+ import { Buffer } from "node:buffer";
1
2
  import { base64ToArrayBuffer, readPublicAsset } from "../../utils.mjs";
2
3
  import { useStorage } from "#internal/nitro";
3
4
  const cachedFonts = {};
@@ -0,0 +1,4 @@
1
+ declare const _default: import("h3").EventHandler<{
2
+ runtimeConfig: any;
3
+ }>;
4
+ export default _default;
@@ -0,0 +1,9 @@
1
+ import { defineEventHandler, setHeader } from "h3";
2
+ import { useRuntimeConfig } from "#imports";
3
+ export default defineEventHandler(async (e) => {
4
+ setHeader(e, "Content-Type", "application/json");
5
+ const runtimeConfig = useRuntimeConfig()["nuxt-og-image"];
6
+ return {
7
+ runtimeConfig
8
+ };
9
+ });
@@ -3,19 +3,22 @@ import { renderSSRHead } from "@unhead/ssr";
3
3
  import { createHeadCore } from "@unhead/vue";
4
4
  import { defineEventHandler, getQuery, sendRedirect } from "h3";
5
5
  import { fetchOptions, renderIsland, useHostname } from "../utils.mjs";
6
- import { useRuntimeConfig } from "#internal/nitro";
6
+ import { useRuntimeConfig } from "#imports";
7
7
  export default defineEventHandler(async (e) => {
8
8
  const { fonts, defaults } = useRuntimeConfig()["nuxt-og-image"];
9
- const path = getQuery(e).path || "/";
10
- const scale = getQuery(e).scale;
11
- const mode = getQuery(e).mode || "light";
9
+ const query = getQuery(e);
10
+ const path = withBase(query.path || "/", useRuntimeConfig().app.baseURL);
11
+ const scale = query.scale;
12
+ const mode = query.mode || "light";
12
13
  let options;
13
- if (getQuery(e).options)
14
- options = JSON.parse(getQuery(e).options);
14
+ if (query.options)
15
+ options = JSON.parse(query.options);
15
16
  if (!options)
16
17
  options = await fetchOptions(e, path);
17
- if (options.provider === "browser" && !options.component)
18
- return sendRedirect(e, withBase(path, useHostname(e)));
18
+ if (options.provider === "browser" && !options.component) {
19
+ const pathWithoutBase = path.replace(new RegExp(`^${useRuntimeConfig().app.baseURL}`), "");
20
+ return sendRedirect(e, withBase(pathWithoutBase, useHostname(e)));
21
+ }
19
22
  const island = await renderIsland(options);
20
23
  const head = createHeadCore();
21
24
  head.push(island.head);
@@ -1,9 +1,12 @@
1
1
  import { createError, defineEventHandler, getHeaders, getQuery } from "h3";
2
- import { extractOgImageOptions, useHostname } from "../utils.mjs";
3
- import { getRouteRules, useRuntimeConfig } from "#internal/nitro";
2
+ import { withoutBase } from "ufo";
3
+ import { extractOgImageOptions } from "../utils.mjs";
4
+ import { useHostname } from "../util-hostname.mjs";
5
+ import { getRouteRules } from "#internal/nitro";
6
+ import { useRuntimeConfig } from "#imports";
4
7
  export default defineEventHandler(async (e) => {
5
8
  const query = getQuery(e);
6
- const path = query.path || "/";
9
+ const path = withoutBase(query.path || "/", useRuntimeConfig().app.baseURL);
7
10
  const fetchOptions = process.dev || process.env.prerender ? {
8
11
  headers: getHeaders(e)
9
12
  } : {
@@ -20,8 +23,10 @@ export default defineEventHandler(async (e) => {
20
23
  });
21
24
  }
22
25
  e.node.req.url = path;
26
+ const oldRouteRules = e.context._nitro.routeRules;
23
27
  e.context._nitro.routeRules = void 0;
24
28
  const routeRules = getRouteRules(e)?.ogImage;
29
+ e.context._nitro.routeRules = oldRouteRules;
25
30
  e.node.req.url = e.path;
26
31
  if (routeRules === false)
27
32
  return false;
@@ -32,8 +37,6 @@ export default defineEventHandler(async (e) => {
32
37
  // use route rules
33
38
  ...routeRules || {},
34
39
  // use provided data
35
- ...extractedPayload,
36
- // use query data
37
- ...query
40
+ ...extractedPayload
38
41
  };
39
42
  });
@@ -2,8 +2,10 @@ import { createError, defineEventHandler, getQuery, setHeader } from "h3";
2
2
  import { withBase } from "ufo";
3
3
  import { fetchOptions, useHostname } from "../utils.mjs";
4
4
  import { useProvider } from "#nuxt-og-image/provider";
5
+ import { useRuntimeConfig } from "#imports";
5
6
  export default defineEventHandler(async (e) => {
6
- const path = getQuery(e).path || "/";
7
+ const query = getQuery(e);
8
+ const path = withBase(query.path || "/", useRuntimeConfig().app.baseURL);
7
9
  const options = await fetchOptions(e, path);
8
10
  setHeader(e, "Content-Type", "image/svg+xml");
9
11
  const provider = await useProvider(options.provider);
@@ -2,8 +2,10 @@ import { createError, defineEventHandler, getQuery, setHeader } from "h3";
2
2
  import { withBase } from "ufo";
3
3
  import { fetchOptions, useHostname } from "../utils.mjs";
4
4
  import { useProvider } from "#nuxt-og-image/provider";
5
+ import { useRuntimeConfig } from "#imports";
5
6
  export default defineEventHandler(async (e) => {
6
- const path = getQuery(e).path || "/";
7
+ const query = getQuery(e);
8
+ const path = withBase(query.path || "/", useRuntimeConfig().app.baseURL);
7
9
  const options = await fetchOptions(e, path);
8
10
  setHeader(e, "Content-Type", "application/json");
9
11
  const provider = await useProvider(options.provider);
@@ -0,0 +1,2 @@
1
+ import type { H3Event } from 'h3';
2
+ export declare function useHostname(e: H3Event): string;
@@ -0,0 +1,15 @@
1
+ import { getRequestHost, getRequestProtocol } from "h3";
2
+ import { withBase } from "ufo";
3
+ import { useRuntimeConfig } from "#imports";
4
+ export function useHostname(e) {
5
+ const base = useRuntimeConfig().app.baseURL;
6
+ let host = getRequestHost(e);
7
+ if (host === "localhost")
8
+ host = process.env.NITRO_HOST || process.env.HOST || host;
9
+ const protocol = getRequestProtocol(e);
10
+ const useHttp = process.dev || host.includes("127.0.0.1") || host.includes("localhost") || protocol === "http";
11
+ let port = host.includes(":") ? host.split(":").pop() : false;
12
+ if ((process.dev || process.env.prerender || host.includes("localhost")) && !port)
13
+ port = process.env.NITRO_PORT || process.env.PORT;
14
+ return withBase(base, `http${useHttp ? "" : "s"}://${host.includes(":") ? host.split(":")[0] : host}${port ? `:${port}` : ""}`);
15
+ }
@@ -1,2 +1,3 @@
1
- export declare function extractOgImageOptions(html: string): false | Record<string, any>;
2
- export declare function stripOgImageOptions(html: string): string;
1
+ import type { OgImageOptions } from '../../types';
2
+ export declare function decodeHtml(html: string): string;
3
+ export declare function extractOgImageOptions(html: string): OgImageOptions | false;
@@ -1,8 +1,12 @@
1
- function decodeHtmlEntities(obj) {
1
+ export function decodeHtml(html) {
2
+ 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
+ return String.fromCharCode(parseInt(int));
4
+ });
5
+ }
6
+ function decodeObjectHtmlEntities(obj) {
2
7
  Object.entries(obj).forEach(([key, value]) => {
3
- if (typeof value === "string") {
4
- obj[key] = value.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&amp;/g, "&").replace(/&quot;/g, '"').replace(/&#x27;/g, "'").replace(/&#x2F;/g, "/");
5
- }
8
+ if (typeof value === "string")
9
+ obj[key] = decodeHtml(value);
6
10
  });
7
11
  return obj;
8
12
  }
@@ -19,15 +23,14 @@ export function extractOgImageOptions(html) {
19
23
  console.warn("Failed to parse #nuxt-og-image-options", e, options);
20
24
  }
21
25
  if (options) {
22
- const description = html.match(/<meta property="og:description" content="(.*?)">/)?.[1];
23
- if (description)
24
- options.description = description;
25
- else
26
- options.description = html.match(/<meta name="description" content="(.*?)">/)?.[1];
27
- return decodeHtmlEntities(options);
26
+ if (!options.description) {
27
+ const description = html.match(/<meta property="og:description" content="(.*?)">/)?.[1];
28
+ if (description)
29
+ options.description = description;
30
+ else
31
+ options.description = html.match(/<meta name="description" content="(.*?)">/)?.[1];
32
+ }
33
+ return decodeObjectHtmlEntities(options);
28
34
  }
29
35
  return false;
30
36
  }
31
- export function stripOgImageOptions(html) {
32
- return html.replace(/<script id="nuxt-og-image-options" type="application\/json">(.*?)<\/script>/, "");
33
- }
@@ -1,9 +1,12 @@
1
1
  /// <reference types="node" />
2
+ import { Buffer } from 'node:buffer';
2
3
  import type { H3Event } from 'h3';
3
4
  import type { OgImageOptions } from '../../types';
4
- export declare function wasmLoader(key: any, fallback: string, baseUrl: string): {
5
- loaded(): boolean | Promise<any>;
6
- load(): Promise<any>;
5
+ export * from './util-hostname';
6
+ export declare function wasmLoader(asyncModuleLoad: Promise<any> | Buffer | string, fallback: string): {
7
+ load(options: {
8
+ baseUrl: string;
9
+ }): Promise<any>;
7
10
  };
8
11
  export declare function fetchOptions(e: H3Event, path: string): Promise<OgImageOptions>;
9
12
  export declare function base64ToArrayBuffer(base64: string): ArrayBuffer;
@@ -11,7 +14,6 @@ export declare function renderIsland(payload: OgImageOptions): Promise<{
11
14
  html: string;
12
15
  head: any;
13
16
  }>;
14
- export declare function useHostname(e: H3Event): any;
15
17
  export declare function readPublicAsset(file: string, encoding?: BufferEncoding): Promise<string | Buffer | undefined>;
16
18
  export declare function readPublicAssetBase64(file: string): Promise<string | undefined>;
17
19
  export * from './utils-pure';