nuxt-og-image 1.0.0-beta.1 → 1.0.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/README.md +1 -0
  2. package/dist/client/200.html +2 -2
  3. package/dist/client/404.html +2 -2
  4. package/dist/client/_nuxt/{Icon.4a9650c6.js → Icon.a3c98859.js} +1 -1
  5. package/dist/client/_nuxt/entry.2a315a2c.js +4 -0
  6. package/dist/client/_nuxt/{entry.0827acf4.css → entry.dc5450bf.css} +1 -1
  7. package/dist/client/_nuxt/{error-404.556d8899.js → error-404.0c49154a.js} +1 -1
  8. package/dist/client/_nuxt/{error-500.70731718.js → error-500.f3eec0bb.js} +1 -1
  9. package/dist/client/_nuxt/{error-component.418ebd67.js → error-component.7c753c74.js} +2 -2
  10. package/dist/client/index.html +2 -2
  11. package/dist/module.d.ts +8 -8
  12. package/dist/module.json +1 -1
  13. package/dist/module.mjs +45 -29
  14. package/dist/runtime/components/{OgImageTemplate.island.vue → OgImageBasic.island.vue} +2 -2
  15. package/dist/runtime/components/OgImageDynamic.d.ts +2 -2
  16. package/dist/runtime/components/OgImageScreenshot.d.ts +2 -2
  17. package/dist/runtime/components/OgImageStatic.d.ts +2 -2
  18. package/dist/runtime/composables/defineOgImage.d.ts +5 -5
  19. package/dist/runtime/composables/defineOgImage.mjs +11 -6
  20. package/dist/runtime/nitro/providers/browser.mjs +7 -8
  21. package/dist/runtime/nitro/providers/{satori.d.ts → satori/index.d.ts} +1 -1
  22. package/dist/runtime/nitro/providers/satori/index.mjs +48 -0
  23. package/dist/runtime/nitro/providers/satori/plugins/emojis.d.ts +2 -0
  24. package/dist/runtime/nitro/providers/satori/plugins/emojis.mjs +13 -0
  25. package/dist/runtime/nitro/providers/satori/plugins/flex.d.ts +2 -0
  26. package/dist/runtime/nitro/providers/satori/plugins/flex.mjs +11 -0
  27. package/dist/runtime/nitro/providers/satori/plugins/imageSrc.d.ts +2 -0
  28. package/dist/runtime/nitro/providers/satori/plugins/imageSrc.mjs +24 -0
  29. package/dist/runtime/nitro/providers/satori/plugins/twClasses.d.ts +2 -0
  30. package/dist/runtime/nitro/providers/satori/plugins/twClasses.mjs +9 -0
  31. package/dist/runtime/nitro/providers/satori/utils.d.ts +10 -0
  32. package/dist/runtime/nitro/providers/satori/utils.mjs +33 -0
  33. package/dist/runtime/nitro/routes/__og_image__/html.mjs +42 -12
  34. package/dist/runtime/nitro/routes/__og_image__/index.mjs +4 -4
  35. package/dist/runtime/nitro/routes/__og_image__/og.png.mjs +8 -12
  36. package/dist/runtime/nitro/routes/__og_image__/options.d.ts +5 -0
  37. package/dist/runtime/nitro/routes/__og_image__/{payload.mjs → options.mjs} +21 -28
  38. package/dist/runtime/nitro/routes/__og_image__/svg.mjs +5 -5
  39. package/dist/runtime/nitro/routes/__og_image__/vnode.d.ts +2 -0
  40. package/dist/runtime/nitro/routes/__og_image__/vnode.mjs +16 -0
  41. package/dist/runtime/nitro/utils.d.ts +3 -3
  42. package/dist/runtime/nitro/utils.mjs +4 -4
  43. package/package.json +3 -2
  44. package/dist/client/_nuxt/entry.ce848650.js +0 -4
  45. package/dist/runtime/nitro/providers/satori.mjs +0 -48
  46. package/dist/runtime/nitro/routes/__og_image__/payload.d.ts +0 -5
@@ -0,0 +1,33 @@
1
+ import { fileURLToPath } from "node:url";
2
+ import { promises as fsp } from "node:fs";
3
+ import { dirname, resolve } from "pathe";
4
+ import { withBase } from "ufo";
5
+ import { getAsset } from "#internal/nitro/virtual/public-assets";
6
+ export async function parseFont(url, font) {
7
+ if (typeof font.publicPath === "string") {
8
+ const file = getAsset(font.publicPath);
9
+ if (file) {
10
+ const serverDir = dirname(fileURLToPath(import.meta.url));
11
+ font.data = await fsp.readFile(resolve(serverDir, file.path));
12
+ }
13
+ if (!font.data)
14
+ font.data = await (await $fetch(withBase(font.publicPath, `${url.protocol}//${url.host}`))).arrayBuffer();
15
+ }
16
+ return font;
17
+ }
18
+ export async function walkSatoriTree(url, node, plugins) {
19
+ if (!node.props?.children)
20
+ return;
21
+ for (const child of node.props.children || []) {
22
+ if (child) {
23
+ for (const plugin of plugins) {
24
+ if (plugin.filter(child))
25
+ await plugin.transform(child, url);
26
+ }
27
+ await walkSatoriTree(url, child, plugins);
28
+ }
29
+ }
30
+ }
31
+ export function defineSatoriTransformer(transformer) {
32
+ return transformer;
33
+ }
@@ -1,26 +1,56 @@
1
- import { parseURL, withoutTrailingSlash } from "ufo";
1
+ import { parseURL, withBase, withoutTrailingSlash } from "ufo";
2
2
  import { renderSSRHead } from "@unhead/ssr";
3
3
  import { createHeadCore } from "@unhead/vue";
4
- import { defineEventHandler, sendRedirect } from "h3";
5
- import { fetchPayload, renderIsland, useHostname } from "../../utils.mjs";
6
- import { height, width } from "#nuxt-og-image/config";
4
+ import { defineEventHandler, getQuery, sendRedirect } from "h3";
5
+ import { fetchOptions, renderIsland, useHostname } from "../../utils.mjs";
6
+ import { defaults } from "#nuxt-og-image/config";
7
7
  export default defineEventHandler(async (e) => {
8
8
  const path = parseURL(e.path).pathname;
9
9
  if (!path.endsWith("__og_image__/html"))
10
10
  return;
11
11
  const basePath = withoutTrailingSlash(path.replace("__og_image__/html", ""));
12
- const payload = await fetchPayload(basePath);
13
- if (payload.provider === "browser")
14
- return sendRedirect(e, useHostname(e) + basePath);
15
- const component = payload.component || "OgImageTemplate";
16
- delete payload.component;
17
- const island = await renderIsland(component, payload);
12
+ const scale = getQuery(e).scale;
13
+ const options = await fetchOptions(basePath);
14
+ if (options.provider === "browser")
15
+ return sendRedirect(e, withBase(basePath, useHostname(e)));
16
+ const island = await renderIsland(options);
18
17
  const head = createHeadCore();
19
18
  head.push(island.head);
20
19
  head.push({
21
20
  style: [
22
21
  {
23
- innerHTML: "body { font-family: 'Inter', sans-serif; }"
22
+ innerHTML: "body { font-family: 'Inter', sans-serif; }"
23
+ },
24
+ scale ? {
25
+ innerHTML: `body {
26
+ transform: scale(${scale});
27
+ transform-origin: top left;
28
+ max-height: 100vh;
29
+ }
30
+ img.emoji {
31
+ height: 1em;
32
+ width: 1em;
33
+ margin: 0 .05em 0 .1em;
34
+ vertical-align: -0.1em;
35
+ }
36
+ `
37
+ } : {}
38
+ ],
39
+ meta: [
40
+ {
41
+ charset: "utf-8"
42
+ }
43
+ ],
44
+ script: [
45
+ {
46
+ src: "https://cdn.tailwindcss.com"
47
+ },
48
+ {
49
+ innerHTML: `tailwind.config = {
50
+ corePlugins: {
51
+ preflight: false,
52
+ }
53
+ }`
24
54
  }
25
55
  ],
26
56
  link: [
@@ -38,6 +68,6 @@ export default defineEventHandler(async (e) => {
38
68
  return `<!DOCTYPE html>
39
69
  <html ${headChunk.htmlAttrs}>
40
70
  <head>${headChunk.headTags}</head>
41
- <body ${headChunk.bodyAttrs}>${headChunk.bodyTagsOpen}<div style="width: ${width}px; height: ${height}px; display: flex; margin: 0 auto;">${island.html}</div>${headChunk.bodyTags}</body>
71
+ <body ${headChunk.bodyAttrs}>${headChunk.bodyTagsOpen}<div style="width: ${defaults.width}px; height: ${defaults.height}px; display: flex; margin: 0 auto;">${island.html}</div>${headChunk.bodyTags}</body>
42
72
  </html>`;
43
73
  });
@@ -1,13 +1,13 @@
1
1
  import { defineEventHandler } from "h3";
2
2
  import { parseURL, withoutTrailingSlash } from "ufo";
3
- import { fetchPayload, useHostname } from "../../utils.mjs";
3
+ import { fetchOptions, useHostname } from "../../utils.mjs";
4
4
  export default defineEventHandler(async (e) => {
5
5
  const path = parseURL(e.path).pathname;
6
6
  if (!path.endsWith("/__og_image__"))
7
7
  return;
8
8
  const basePath = withoutTrailingSlash(path.replace("__og_image__", ""));
9
- const payload = await fetchPayload(basePath);
10
- if (!payload)
9
+ const options = await fetchOptions(basePath);
10
+ if (!options)
11
11
  return `The route ${basePath} has not been set up for og:image generation.`;
12
12
  return `
13
13
  <style>
@@ -21,6 +21,6 @@ export default defineEventHandler(async (e) => {
21
21
  height: 100%;
22
22
  }
23
23
  </style>
24
- <title>Og Image Playground</title>
24
+ <title>OG Image Playground</title>
25
25
  <iframe src="${useHostname(e)}/__nuxt_og_image__/client/?&path=${withoutTrailingSlash(path.replace("__og_image__", ""))}"></iframe>`;
26
26
  });
@@ -1,6 +1,6 @@
1
1
  import { defineEventHandler, setHeader } from "h3";
2
- import { parseURL, withBase, withoutTrailingSlash } from "ufo";
3
- import { fetchPayload, useHostname } from "../../utils.mjs";
2
+ import { joinURL, parseURL, withBase, withoutTrailingSlash } from "ufo";
3
+ import { fetchOptions, useHostname } from "../../utils.mjs";
4
4
  import { useProvider } from "#nuxt-og-image/provider";
5
5
  export default defineEventHandler(async (e) => {
6
6
  const path = parseURL(e.path).pathname;
@@ -9,15 +9,11 @@ export default defineEventHandler(async (e) => {
9
9
  const basePath = withoutTrailingSlash(
10
10
  path.replace("__og_image__/og.png", "")
11
11
  );
12
- const { provider: providerName, prerender } = await fetchPayload(basePath);
12
+ const options = await fetchOptions(basePath);
13
13
  setHeader(e, "Content-Type", "image/png");
14
- if (prerender && !process.dev) {
15
- setHeader(e, "Cache-Control", "public, max-age=86400");
16
- } else {
17
- setHeader(e, "Cache-Control", "no-cache, no-store, must-revalidate");
18
- setHeader(e, "Pragma", "no-cache");
19
- setHeader(e, "Expires", "0");
20
- }
21
- const provider = await useProvider(providerName);
22
- return provider.createPng(withBase(`${basePath}/__og_image__/html`, useHostname(e)));
14
+ setHeader(e, "Cache-Control", "no-cache, no-store, must-revalidate");
15
+ setHeader(e, "Pragma", "no-cache");
16
+ setHeader(e, "Expires", "0");
17
+ const provider = await useProvider(options.provider);
18
+ return provider.createPng(withBase(joinURL(basePath, "/__og_image__/html"), useHostname(e)), options);
23
19
  });
@@ -0,0 +1,5 @@
1
+ import type { OgImageOptions } from '../../../../types';
2
+ export declare function extractOgImageOptions(html: string): any;
3
+ export declare const inferOgImageOptions: (html: string) => OgImageOptions;
4
+ declare const _default: import("h3").EventHandler<false | OgImageOptions | undefined>;
5
+ export default _default;
@@ -1,31 +1,32 @@
1
1
  import { parseURL, withoutTrailingSlash } from "ufo";
2
2
  import { defineEventHandler, getQuery } from "h3";
3
- import { PayloadScriptId } from "#nuxt-og-image/constants";
4
3
  import { getRouteRules } from "#internal/nitro";
5
- export const extractOgPayload = (html) => {
6
- const payload = html.match(new RegExp(`<script id="${PayloadScriptId}" type="application/json">(.+?)<\/script>`))?.[1];
7
- if (payload) {
8
- return JSON.parse(payload);
9
- }
10
- return false;
11
- };
12
- export const inferOgPayload = (html) => {
13
- const payload = {};
4
+ import { defaults } from "#nuxt-og-image/config";
5
+ export function extractOgImageOptions(html) {
6
+ const options = html.match(/<script id="nuxt-og-image-options" type="application\/json">(.+?)<\/script>/)?.[1];
7
+ return options ? JSON.parse(options) : false;
8
+ }
9
+ export const inferOgImageOptions = (html) => {
10
+ const options = {};
14
11
  const title = html.match(/<meta property="og:title" content="(.*?)">/)?.[1];
15
12
  if (title)
16
- payload.title = title;
13
+ options.title = title;
14
+ else
15
+ options.title = html.match(/<title>(.*?)<\/title>/)?.[1];
17
16
  const description = html.match(/<meta property="og:description" content="(.*?)">/)?.[1];
18
17
  if (description)
19
- payload.description = description;
20
- return payload;
18
+ options.description = description;
19
+ else
20
+ options.description = html.match(/<meta name="description" content="(.*?)">/)?.[1];
21
+ return options;
21
22
  };
22
23
  export default defineEventHandler(async (e) => {
23
24
  const path = parseURL(e.path).pathname;
24
- if (!path.endsWith("__og_image__/payload"))
25
+ if (!path.endsWith("__og_image__/options"))
25
26
  return;
26
- const basePath = withoutTrailingSlash(path.replace("__og_image__/payload", ""));
27
+ const basePath = withoutTrailingSlash(path.replace("__og_image__/options", ""));
27
28
  const html = await $fetch(basePath);
28
- const extractedPayload = extractOgPayload(html);
29
+ const extractedPayload = extractOgImageOptions(html);
29
30
  if (!extractedPayload)
30
31
  return false;
31
32
  e.node.req.url = basePath;
@@ -34,20 +35,12 @@ export default defineEventHandler(async (e) => {
34
35
  e.node.req.url = e.path;
35
36
  if (routeRules === false)
36
37
  return false;
37
- let payload = {
38
+ return {
38
39
  path: basePath,
39
- ...extractOgPayload(html),
40
- ...inferOgPayload(html),
40
+ ...defaults,
41
+ ...inferOgImageOptions(html),
41
42
  ...routeRules || {},
43
+ ...extractedPayload,
42
44
  ...getQuery(e)
43
45
  };
44
- if (payload.provider === "satori") {
45
- payload = {
46
- title: "Hello World",
47
- description: "Example description",
48
- image: "https://example.com/image.png",
49
- ...payload
50
- };
51
- }
52
- return payload;
53
46
  });
@@ -1,6 +1,6 @@
1
1
  import { defineEventHandler, setHeader } from "h3";
2
- import { parseURL, withBase, withoutTrailingSlash } from "ufo";
3
- import { fetchPayload, useHostname } from "../../utils.mjs";
2
+ import { joinURL, parseURL, withBase, withoutTrailingSlash } from "ufo";
3
+ import { fetchOptions, useHostname } from "../../utils.mjs";
4
4
  import { useProvider } from "#nuxt-og-image/provider";
5
5
  export default defineEventHandler(async (e) => {
6
6
  const path = parseURL(e.path).pathname;
@@ -9,8 +9,8 @@ export default defineEventHandler(async (e) => {
9
9
  const basePath = withoutTrailingSlash(
10
10
  path.replace("__og_image__/svg", "")
11
11
  );
12
- const { provider: providerName } = await fetchPayload(basePath);
12
+ const options = await fetchOptions(basePath);
13
13
  setHeader(e, "Content-Type", "image/svg+xml");
14
- const provider = await useProvider(providerName);
15
- return provider.createSvg(withBase(`${basePath}/__og_image__/html`, useHostname(e)));
14
+ const provider = await useProvider(options.provider);
15
+ return provider.createSvg(withBase(joinURL(basePath, "/__og_image__/html"), useHostname(e)), options);
16
16
  });
@@ -0,0 +1,2 @@
1
+ declare const _default: import("h3").EventHandler<any>;
2
+ export default _default;
@@ -0,0 +1,16 @@
1
+ import { defineEventHandler, setHeader } from "h3";
2
+ import { joinURL, parseURL, withBase, withoutTrailingSlash } from "ufo";
3
+ import { fetchOptions, useHostname } from "../../utils.mjs";
4
+ import { useProvider } from "#nuxt-og-image/provider";
5
+ export default defineEventHandler(async (e) => {
6
+ const path = parseURL(e.path).pathname;
7
+ if (!path.endsWith("__og_image__/vnode"))
8
+ return;
9
+ const basePath = withoutTrailingSlash(
10
+ path.replace("__og_image__/vnode", "")
11
+ );
12
+ const options = await fetchOptions(basePath);
13
+ setHeader(e, "Content-Type", "application/json");
14
+ const provider = await useProvider(options.provider);
15
+ return provider.createVNode(withBase(joinURL(basePath, "/__og_image__/html"), useHostname(e)), options);
16
+ });
@@ -1,7 +1,7 @@
1
1
  import type { H3Event } from 'h3';
2
- import type { OgImagePayload } from '../../types';
3
- export declare function fetchPayload(path: string): Promise<OgImagePayload>;
4
- export declare function renderIsland(island: string, payload: Record<string, any>): Promise<{
2
+ import type { OgImageOptions } from '../../types';
3
+ export declare function fetchOptions(path: string): Promise<OgImageOptions>;
4
+ export declare function renderIsland(payload: OgImageOptions): Promise<{
5
5
  html: string;
6
6
  head: any;
7
7
  }>;
@@ -1,10 +1,10 @@
1
1
  import { joinURL, withQuery } from "ufo";
2
2
  import { getRequestHeader } from "h3";
3
- export function fetchPayload(path) {
4
- return $fetch(joinURL(path, "__og_image__/payload"));
3
+ export function fetchOptions(path) {
4
+ return $fetch(joinURL(path, "__og_image__/options"));
5
5
  }
6
- export function renderIsland(island, payload) {
7
- return $fetch(withQuery(`/__nuxt_island/${island}`, {
6
+ export function renderIsland(payload) {
7
+ return $fetch(withQuery(`/__nuxt_island/${payload.component}`, {
8
8
  props: JSON.stringify(payload)
9
9
  }));
10
10
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nuxt-og-image",
3
3
  "type": "module",
4
- "version": "1.0.0-beta.1",
4
+ "version": "1.0.0-beta.10",
5
5
  "packageManager": "pnpm@7.8.0",
6
6
  "license": "MIT",
7
7
  "funding": "https://github.com/sponsors/harlan-zw",
@@ -44,6 +44,7 @@
44
44
  "satori-html": "^0.3.2",
45
45
  "sirv": "^2.0.2",
46
46
  "tinyws": "^0.1.0",
47
+ "twemoji": "^14.0.2",
47
48
  "ufo": "^1.0.1"
48
49
  },
49
50
  "devDependencies": {
@@ -63,7 +64,7 @@
63
64
  "build": "pnpm dev:prepare && pnpm build:module && pnpm build:client",
64
65
  "build:client": "nuxi generate client",
65
66
  "build:module": "nuxt-build-module",
66
- "lint": "eslint \"**/*.{ts,vue,json,yml}\"",
67
+ "lint": "eslint \"**/*.{ts,vue,json,yml}\" --fix",
67
68
  "dev": "nuxi dev .playground",
68
69
  "dev:build": "nuxi build .playground",
69
70
  "dev:prepare": "nuxt-module-build --stub && nuxi prepare .playground",