nuxt-og-image 2.0.0-beta.59 → 2.0.0-beta.60

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 (51) hide show
  1. package/README.md +51 -49
  2. package/dist/client/200.html +2 -2
  3. package/dist/client/404.html +2 -2
  4. package/dist/client/_nuxt/IconCSS.b41b9663.css +1 -0
  5. package/dist/client/_nuxt/{IconCSS.3ed6665a.js → IconCSS.c2e73ab2.js} +1 -1
  6. package/dist/client/_nuxt/{ImageLoader.98cdc4fb.js → ImageLoader.ed4bfccb.js} +1 -1
  7. package/dist/client/_nuxt/{entry.ddd5fc7b.css → entry.862302d7.css} +1 -1
  8. package/dist/client/_nuxt/{entry.725a580a.js → entry.f51ac6f7.js} +3 -3
  9. package/dist/client/_nuxt/{error-404.c6d590bd.js → error-404.a94c6c21.js} +1 -1
  10. package/dist/client/_nuxt/{error-500.05e72b5f.js → error-500.3955092a.js} +1 -1
  11. package/dist/client/_nuxt/{index.80d41946.js → index.17db8b1a.js} +1 -1
  12. package/dist/client/_nuxt/{options.334f5ba2.js → options.3e6c211b.js} +1 -1
  13. package/dist/client/_nuxt/{png.823fe00d.js → png.23a5e57c.js} +1 -1
  14. package/dist/client/_nuxt/{shiki.eefdab7f.js → shiki.2980d306.js} +1 -1
  15. package/dist/client/_nuxt/{svg.04e74616.js → svg.a8bba1f1.js} +1 -1
  16. package/dist/client/_nuxt/{vnodes.1f91e005.js → vnodes.64d635d6.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 +81 -6
  23. package/dist/module.json +1 -1
  24. package/dist/module.mjs +96 -32
  25. package/dist/runtime/components/{OgImageDynamic.d.ts → OgImage/Cached.d.ts} +1 -2
  26. package/dist/runtime/components/OgImage/Cached.mjs +10 -0
  27. package/dist/runtime/components/{OgImageScreenshot.d.ts → OgImage/Screenshot.d.ts} +1 -3
  28. package/dist/runtime/components/{OgImageScreenshot.mjs → OgImage/Screenshot.mjs} +2 -2
  29. package/dist/runtime/components/{OgImageStatic.d.ts → OgImage/WithoutCache.d.ts} +1 -2
  30. package/dist/runtime/components/OgImage/WithoutCache.mjs +10 -0
  31. package/dist/runtime/components/OgImage/_OgImageDynamic.d.ts +7 -0
  32. package/dist/runtime/components/{OgImageDynamic.mjs → OgImage/_OgImageDynamic.mjs} +3 -3
  33. package/dist/runtime/components/OgImage/_OgImageStatic.d.ts +7 -0
  34. package/dist/runtime/components/{OgImageStatic.mjs → OgImage/_OgImageStatic.mjs} +3 -3
  35. package/dist/runtime/components/OgImage/index.d.ts +4 -0
  36. package/dist/runtime/components/OgImage/index.mjs +9 -0
  37. package/dist/runtime/components/OgImageTemplate/Fallback.vue +155 -0
  38. package/dist/runtime/composables/defineOgImage.d.ts +12 -4
  39. package/dist/runtime/composables/defineOgImage.mjs +46 -23
  40. package/dist/runtime/nitro/middleware/og.png.mjs +9 -7
  41. package/dist/runtime/nitro/plugins/prerender.mjs +6 -4
  42. package/dist/runtime/nitro/routes/debug.d.ts +4 -0
  43. package/dist/runtime/nitro/routes/debug.mjs +6 -1
  44. package/dist/runtime/nitro/routes/html.mjs +5 -5
  45. package/dist/runtime/nitro/utils.d.ts +0 -1
  46. package/dist/runtime/nitro/utils.mjs +11 -10
  47. package/package.json +12 -10
  48. package/dist/client/_nuxt/IconCSS.8bbd2aa2.css +0 -1
  49. package/dist/runtime/components/OgImageBasic.island.vue +0 -97
  50. package/dist/runtime/nitro/util-hostname.d.ts +0 -2
  51. package/dist/runtime/nitro/util-hostname.mjs +0 -20
@@ -2,9 +2,9 @@ import { Buffer } from "node:buffer";
2
2
  import { createError, defineEventHandler, sendRedirect, setHeader } from "h3";
3
3
  import { joinURL, parseURL, withoutTrailingSlash } from "ufo";
4
4
  import { prefixStorage } from "unstorage";
5
- import { fetchOptions, useHostname } from "../utils.mjs";
5
+ import { fetchOptions } from "../utils.mjs";
6
6
  import { useProvider } from "#nuxt-og-image/provider";
7
- import { useRuntimeConfig, useStorage } from "#imports";
7
+ import { useNitroOrigin, useRuntimeConfig, useStorage } from "#imports";
8
8
  export default defineEventHandler(async (e) => {
9
9
  const { runtimeBrowser, runtimeCacheStorage } = useRuntimeConfig()["nuxt-og-image"];
10
10
  const path = parseURL(e.path).pathname;
@@ -15,7 +15,7 @@ export default defineEventHandler(async (e) => {
15
15
  );
16
16
  const options = await fetchOptions(e, basePath);
17
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"));
18
+ return sendRedirect(e, joinURL(useNitroOrigin(e), "__nuxt_og_image__/browser-provider-not-supported.png"));
19
19
  const provider = await useProvider(options.provider);
20
20
  if (!provider) {
21
21
  throw createError({
@@ -23,9 +23,11 @@ export default defineEventHandler(async (e) => {
23
23
  statusMessage: `Provider ${options.provider} is missing.`
24
24
  });
25
25
  }
26
- const useCache = runtimeCacheStorage && !process.dev && options.cacheTtl && options.cacheTtl > 0;
27
- const cache = prefixStorage(useStorage(), "og-image-cache:images");
28
- const key = options.cacheKey || e.node.req.url;
26
+ const useCache = runtimeCacheStorage && !process.dev && options.cacheTtl && options.cacheTtl > 0 && options.cache;
27
+ const baseCacheKey = runtimeCacheStorage === "default" ? "/cache/og-image" : "/og-image";
28
+ const cache = prefixStorage(useStorage(), `${baseCacheKey}/images`);
29
+ let key = options.cacheKey || e.node.req.url.replace("/__og_image__/og.png", "");
30
+ key = key === "/" || !key ? "index" : key;
29
31
  let png;
30
32
  if (useCache && await cache.hasItem(key)) {
31
33
  const { value, expiresAt } = await cache.getItem(key);
@@ -52,7 +54,7 @@ export default defineEventHandler(async (e) => {
52
54
  }
53
55
  }
54
56
  if (png) {
55
- if (!process.dev && options.static) {
57
+ if (!process.dev && options.cache) {
56
58
  setHeader(e, "Cache-Control", "public, max-age=31536000");
57
59
  } else {
58
60
  setHeader(e, "Cache-Control", "no-cache, no-store, must-revalidate");
@@ -2,11 +2,13 @@ import { appendHeader } from "h3";
2
2
  import { joinURL } from "ufo";
3
3
  import { prefixStorage } from "unstorage";
4
4
  import { extractOgImageOptions } from "../utils-pure.mjs";
5
- import { useStorage } from "#imports";
5
+ import { useStorage, useRuntimeConfig } from "#imports";
6
6
  const OgImagePrenderNitroPlugin = (nitroApp) => {
7
7
  if (!process.env.prerender)
8
8
  return;
9
- const cache = prefixStorage(useStorage(), "og-image-cache:options");
9
+ const { runtimeCacheStorage } = useRuntimeConfig()["nuxt-og-image"];
10
+ const baseCacheKey = runtimeCacheStorage === "default" ? "/cache/og-image" : "/og-image";
11
+ const cache = prefixStorage(useStorage(), `${baseCacheKey}/options`);
10
12
  nitroApp.hooks.hook("render:html", async (ctx, { event }) => {
11
13
  const url = event.node.req.url;
12
14
  if (url.includes(".") || url.startsWith("/__nuxt_island/"))
@@ -14,12 +16,12 @@ const OgImagePrenderNitroPlugin = (nitroApp) => {
14
16
  const options = extractOgImageOptions(ctx.head.join("\n"));
15
17
  if (!options)
16
18
  return;
17
- await cache.setItem(url, {
19
+ await cache.setItem(url === "/" || !url ? "index" : url, {
18
20
  value: JSON.stringify(options),
19
21
  expiresAt: Date.now() + 60 * 60 * 1e3
20
22
  // 60 minutes to prerender
21
23
  });
22
- if (options.static && options.provider === "satori")
24
+ if (options.provider === "satori")
23
25
  appendHeader(event, "x-nitro-prerender", joinURL(url, "/__og_image__/og.png"));
24
26
  });
25
27
  };
@@ -1,4 +1,8 @@
1
1
  declare const _default: import("h3").EventHandler<{
2
+ siteConfigUrl: {
3
+ value: any;
4
+ source: any;
5
+ };
2
6
  runtimeConfig: any;
3
7
  }>;
4
8
  export default _default;
@@ -1,9 +1,14 @@
1
1
  import { defineEventHandler, setHeader } from "h3";
2
- import { useRuntimeConfig } from "#imports";
2
+ import { useRuntimeConfig, useSiteConfig } from "#imports";
3
3
  export default defineEventHandler(async (e) => {
4
4
  setHeader(e, "Content-Type", "application/json");
5
5
  const runtimeConfig = useRuntimeConfig()["nuxt-og-image"];
6
+ const siteConfig = await useSiteConfig(e);
6
7
  return {
8
+ siteConfigUrl: {
9
+ value: siteConfig.url,
10
+ source: siteConfig._context.url || "unknown"
11
+ },
7
12
  runtimeConfig
8
13
  };
9
14
  });
@@ -4,8 +4,8 @@ import { createHeadCore } from "@unhead/vue";
4
4
  import { createError, defineEventHandler, getQuery, sendRedirect } from "h3";
5
5
  import { hash } from "ohash";
6
6
  import twemoji from "twemoji";
7
- import { fetchOptions, useHostname } from "../utils.mjs";
8
- import { useRuntimeConfig } from "#imports";
7
+ import { fetchOptions } from "../utils.mjs";
8
+ import { useNitroOrigin, useRuntimeConfig } from "#imports";
9
9
  export default defineEventHandler(async (e) => {
10
10
  const { fonts, defaults, satoriOptions } = useRuntimeConfig()["nuxt-og-image"];
11
11
  const query = getQuery(e);
@@ -23,7 +23,7 @@ export default defineEventHandler(async (e) => {
23
23
  options = await fetchOptions(e, path);
24
24
  if (options.provider === "browser" && !options.component) {
25
25
  const pathWithoutBase = path.replace(new RegExp(`^${useRuntimeConfig().app.baseURL}`), "");
26
- return sendRedirect(e, withBase(pathWithoutBase, useHostname(e)));
26
+ return sendRedirect(e, withBase(pathWithoutBase, useNitroOrigin(e)));
27
27
  }
28
28
  if (!options.component) {
29
29
  throw createError({
@@ -135,7 +135,7 @@ img.emoji {
135
135
  const href = stylesheet.match(/href="(.*?)"/)[1];
136
136
  try {
137
137
  let css = await (await $fetch(href, {
138
- baseURL: useHostname(e)
138
+ baseURL: useNitroOrigin(e)
139
139
  })).text();
140
140
  if (css.includes("const __vite__css =")) {
141
141
  css = css.match(/const __vite__css = "(.*)"/)[1].replace(/\\n/g, "\n");
@@ -151,7 +151,7 @@ img.emoji {
151
151
  if (hasInlineStyles) {
152
152
  const inlineCss = await import("inline-css").then((m) => m?.default || m);
153
153
  htmlTemplate = inlineCss(htmlTemplate, {
154
- url: useHostname(e),
154
+ url: useNitroOrigin(e),
155
155
  applyLinkTags: false,
156
156
  removeLinkTags: false,
157
157
  removeStyleTags: false
@@ -2,7 +2,6 @@
2
2
  import { Buffer } from 'node:buffer';
3
3
  import type { H3Event } from 'h3';
4
4
  import type { RuntimeOgImageOptions } from '../../types';
5
- export * from './util-hostname';
6
5
  export declare function wasmLoader(asyncModuleLoad: Promise<any> | Buffer | string, fallback: string): {
7
6
  load(options: RuntimeOgImageOptions): Promise<any>;
8
7
  };
@@ -4,9 +4,7 @@ import { getQuery } from "h3";
4
4
  import { join } from "pathe";
5
5
  import { prefixStorage } from "unstorage";
6
6
  import sizeOf from "image-size";
7
- import { useHostname } from "./util-hostname.mjs";
8
- import { useRuntimeConfig, useStorage } from "#imports";
9
- export * from "./util-hostname.mjs";
7
+ import { useNitroOrigin, useRuntimeConfig, useStorage } from "#imports";
10
8
  export function wasmLoader(asyncModuleLoad, fallback) {
11
9
  let promise;
12
10
  let wasm;
@@ -40,14 +38,17 @@ export function wasmLoader(asyncModuleLoad, fallback) {
40
38
  }
41
39
  export async function fetchOptions(e, path) {
42
40
  const { runtimeCacheStorage } = useRuntimeConfig()["nuxt-og-image"];
43
- const cache = runtimeCacheStorage || process.env.prerender ? prefixStorage(useStorage(), "og-image-cache:options") : false;
41
+ const baseCacheKey = runtimeCacheStorage === "default" ? "/cache/og-image" : "/og-image";
42
+ const cache = runtimeCacheStorage || process.env.prerender ? prefixStorage(useStorage(), `${baseCacheKey}/options`) : false;
43
+ let key = e.node.req.url.replace("/__og_image__/og.png", "");
44
+ key = key === "/" || !key ? "index" : key;
44
45
  let options;
45
- if (cache && await cache.hasItem(path)) {
46
- const cachedValue = await cache.getItem(path);
46
+ if (!process.dev && cache && await cache.hasItem(key)) {
47
+ const cachedValue = await cache.getItem(key);
47
48
  if (cachedValue && cachedValue.value && cachedValue.expiresAt < Date.now())
48
49
  options = cachedValue.value;
49
50
  else
50
- await cache.removeItem(path);
51
+ await cache.removeItem(key);
51
52
  }
52
53
  if (!options) {
53
54
  options = await globalThis.$fetch("/api/og-image-options", {
@@ -57,9 +58,9 @@ export async function fetchOptions(e, path) {
57
58
  responseType: "json"
58
59
  });
59
60
  if (cache) {
60
- await cache.setItem(path, {
61
+ await cache.setItem(key, {
61
62
  value: options,
62
- expiresAt: Date.now() + (options.static ? 60 * 60 * 1e3 : 5 * 1e3)
63
+ expiresAt: Date.now() + (options.cache ? 60 * 60 * 1e3 : 5 * 1e3)
63
64
  });
64
65
  }
65
66
  }
@@ -67,7 +68,7 @@ export async function fetchOptions(e, path) {
67
68
  ...options,
68
69
  // use query data
69
70
  ...getQuery(e),
70
- requestOrigin: useHostname(e)
71
+ requestOrigin: useNitroOrigin(e)
71
72
  };
72
73
  }
73
74
  export function base64ToArrayBuffer(base64) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nuxt-og-image",
3
3
  "type": "module",
4
- "version": "2.0.0-beta.59",
4
+ "version": "2.0.0-beta.60",
5
5
  "packageManager": "pnpm@8.6.0",
6
6
  "license": "MIT",
7
7
  "funding": "https://github.com/sponsors/harlan-zw",
@@ -31,20 +31,21 @@
31
31
  "@resvg/resvg-wasm": "^2.4.1",
32
32
  "@types/fs-extra": "^11.0.1",
33
33
  "birpc": "^0.2.12",
34
- "chalk": "^5.2.0",
34
+ "chalk": "^5.3.0",
35
35
  "chrome-launcher": "^0.15.2",
36
36
  "defu": "^6.1.2",
37
37
  "execa": "^7.1.1",
38
- "fast-glob": "^3.2.12",
38
+ "fast-glob": "^3.3.0",
39
39
  "flatted": "^3.2.7",
40
40
  "fs-extra": "^11.1.1",
41
- "globby": "^13.2.0",
41
+ "globby": "^13.2.1",
42
42
  "image-size": "^1.0.2",
43
43
  "inline-css": "^4.0.2",
44
44
  "launch-editor": "^2.6.0",
45
- "nuxt-icon": "^0.4.1",
46
- "nuxt-site-config": "^0.3.1",
47
- "nypm": "^0.2.1",
45
+ "nuxt-icon": "^0.4.2",
46
+ "nuxt-site-config": "^0.7.5",
47
+ "nuxt-site-config-kit": "^0.7.5",
48
+ "nypm": "^0.2.2",
48
49
  "ofetch": "^1.1.1",
49
50
  "ohash": "^1.1.2",
50
51
  "pathe": "^1.1.1",
@@ -62,16 +63,17 @@
62
63
  "yoga-wasm-web": "^0.3.3"
63
64
  },
64
65
  "devDependencies": {
65
- "@antfu/eslint-config": "^0.39.5",
66
- "@nuxt/devtools-edge": "0.6.4-28129679.fb5a846",
66
+ "@antfu/eslint-config": "^0.39.6",
67
+ "@nuxt/devtools-edge": "0.6.6-28135918.e26a136",
67
68
  "@nuxt/module-builder": "^0.4.0",
68
69
  "@nuxt/test-utils": "3.6.1",
69
70
  "@nuxtjs/eslint-config-typescript": "^12.0.0",
70
71
  "@types/ws": "^8.5.5",
71
72
  "bumpp": "^9.1.1",
72
- "eslint": "8.43.0",
73
+ "eslint": "8.44.0",
73
74
  "jest-image-snapshot": "^6.1.0",
74
75
  "nuxt": "^3.6.1",
76
+ "playwright": "^1.35.1",
75
77
  "sass": "^1.63.6",
76
78
  "vitest": "^0.32.2"
77
79
  },
@@ -1 +0,0 @@
1
- span[data-v-46d643c4]{background-color:currentColor;display:inline-block;-webkit-mask-image:var(--243647bc);mask-image:var(--243647bc);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;vertical-align:middle}
@@ -1,97 +0,0 @@
1
- <script setup lang="ts">
2
- import { computed } from 'vue'
3
-
4
- const props = defineProps({
5
- path: String,
6
- title: {
7
- type: String,
8
- default: 'Og Image Template',
9
- },
10
- description: {
11
- type: String,
12
- default: 'Set a description to change me.',
13
- },
14
- background: {
15
- type: String,
16
- default: 'linear-gradient(to bottom, #dbf4ff, #fff1f1)',
17
- },
18
- color: {
19
- type: String,
20
- },
21
- padding: {
22
- type: String,
23
- default: '0 100px',
24
- },
25
- titleFontSize: {
26
- type: String,
27
- default: '60px',
28
- },
29
- descriptionFontSize: {
30
- type: String,
31
- default: '26px',
32
- },
33
- })
34
-
35
- // inherited attrs can mess up the satori parser
36
- defineOptions({
37
- inheritAttrs: false,
38
- })
39
-
40
- const containerAttrs = computed(() => {
41
- const isBackgroundTw = props.background?.startsWith('bg-')
42
- const isColorTw = props.color?.startsWith('text-')
43
-
44
- const classes = [
45
- 'w-full',
46
- 'h-full',
47
- 'flex',
48
- 'items-center',
49
- 'justify-center',
50
- ]
51
- const styles: Record<string, any> = {
52
- padding: props.padding,
53
- }
54
-
55
- if (isBackgroundTw)
56
- classes.push(props.background)
57
- else if (props.background)
58
- styles.background = props.background
59
-
60
- if (isColorTw)
61
- classes.push(props.color)
62
- else
63
- styles.color = props.color
64
- return { class: classes, style: styles }
65
- })
66
-
67
- const titleAttrs = computed(() => {
68
- const classes = []
69
- const styles = {
70
- fontWeight: 'bold',
71
- marginBottom: '20px',
72
- fontSize: props.titleFontSize,
73
- }
74
- return { class: classes, style: styles }
75
- })
76
-
77
- const descriptionAttrs = computed(() => {
78
- const classes = []
79
- const styles = {
80
- fontSize: props.descriptionFontSize,
81
- }
82
- return { class: classes, style: styles }
83
- })
84
- </script>
85
-
86
- <template>
87
- <div v-bind="containerAttrs">
88
- <div class="flex flex-col w-full">
89
- <div v-bind="titleAttrs">
90
- {{ title || 'Null Title' }}
91
- </div>
92
- <div v-if="description" v-bind="descriptionAttrs">
93
- {{ description }}
94
- </div>
95
- </div>
96
- </div>
97
- </template>
@@ -1,2 +0,0 @@
1
- import type { H3Event } from 'h3';
2
- export declare function useHostname(e: H3Event): string;
@@ -1,20 +0,0 @@
1
- import { getRequestHost, getRequestProtocol } from "h3";
2
- import { withBase, withoutProtocol } from "ufo";
3
- import { useRuntimeConfig } from "#imports";
4
- export function useHostname(e) {
5
- const base = useRuntimeConfig().app.baseURL;
6
- let host = getRequestHost(e, { xForwardedHost: true });
7
- if (host === "localhost")
8
- host = process.env.NITRO_HOST || process.env.HOST || host;
9
- let protocol = getRequestProtocol(e, { xForwardedProto: true });
10
- if (process.dev && process.env.NUXT_VITE_NODE_OPTIONS) {
11
- const envHost = JSON.parse(process.env.NUXT_VITE_NODE_OPTIONS).baseURL.replace("__nuxt_vite_node__", "");
12
- host = withoutProtocol(envHost);
13
- protocol = envHost.includes("https") ? "https" : "http";
14
- }
15
- const useHttp = process.dev || host.includes("127.0.0.1") || host.includes("localhost") || protocol === "http";
16
- let port = host.includes(":") ? host.split(":").pop() : false;
17
- if ((process.dev || process.env.prerender || host.includes("localhost")) && !port)
18
- port = process.env.NITRO_PORT || process.env.PORT;
19
- return withBase(base, `http${useHttp ? "" : "s"}://${host.includes(":") ? host.split(":")[0] : host}${port ? `:${port}` : ""}`);
20
- }