nuxt-og-image 3.0.0-beta.4 → 3.0.0-beta.41

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 (136) hide show
  1. package/README.md +4 -4
  2. package/dist/client/200.html +5 -5
  3. package/dist/client/404.html +5 -5
  4. package/dist/client/_nuxt/IconCSS.7e8f1f7b.css +1 -0
  5. package/dist/client/_nuxt/{IconCSS.6583687a.js → IconCSS.aa1d279a.js} +1 -1
  6. package/dist/client/_nuxt/builds/latest.json +1 -1
  7. package/dist/client/_nuxt/builds/meta/fa0d9e15-6d49-41d0-bdff-8eca0446edd7.json +1 -0
  8. package/dist/client/_nuxt/entry.16c420c7.js +137 -0
  9. package/dist/client/_nuxt/entry.47aab0b4.css +1 -0
  10. package/dist/client/_nuxt/{error-404.214d08e9.js → error-404.26fce296.js} +1 -1
  11. package/dist/client/_nuxt/{error-500.f9a9234a.js → error-500.89729d99.js} +1 -1
  12. package/dist/client/index.html +5 -5
  13. package/dist/module.d.mts +46 -27
  14. package/dist/module.d.ts +46 -27
  15. package/dist/module.json +2 -2
  16. package/dist/module.mjs +195 -103
  17. package/dist/runtime/cache.d.ts +7 -10
  18. package/dist/runtime/cache.mjs +40 -27
  19. package/dist/runtime/components/OgImage/OgImage.d.ts +5 -0
  20. package/dist/runtime/components/OgImage/{index.mjs → OgImage.mjs} +1 -1
  21. package/dist/runtime/components/OgImage/OgImageScreenshot.d.ts +5 -0
  22. package/dist/runtime/components/OgImage/{Screenshot.mjs → OgImageScreenshot.mjs} +1 -1
  23. package/dist/runtime/components/Templates/{Official → Community}/BrandedLogo.vue +3 -2
  24. package/dist/runtime/components/Templates/Community/Nuxt.vue +6 -5
  25. package/dist/runtime/components/Templates/Community/NuxtSeo.vue +137 -0
  26. package/dist/runtime/components/Templates/{Official → Community}/SimpleBlog.vue +7 -5
  27. package/dist/runtime/components/Templates/Community/UnJs.vue +108 -0
  28. package/dist/runtime/components/Templates/{Official → Community}/Wave.vue +3 -2
  29. package/dist/runtime/components/Templates/{Official → Community}/WithEmoji.vue +3 -2
  30. package/dist/runtime/composables/defineOgImage.d.ts +2 -23
  31. package/dist/runtime/composables/defineOgImage.mjs +33 -116
  32. package/dist/runtime/composables/defineOgImageComponent.d.ts +3 -0
  33. package/dist/runtime/composables/defineOgImageComponent.mjs +8 -0
  34. package/dist/runtime/composables/defineOgImageScreenshot.d.ts +2 -0
  35. package/dist/runtime/composables/defineOgImageScreenshot.mjs +14 -0
  36. package/dist/runtime/core/bindings/css-inline/node.d.ts +2 -5
  37. package/dist/runtime/core/bindings/css-inline/node.mjs +2 -10
  38. package/dist/runtime/core/bindings/resvg/stackblitz.d.ts +40 -0
  39. package/dist/runtime/core/bindings/resvg/stackblitz.mjs +6 -0
  40. package/dist/runtime/core/bindings/resvg/wasm.mjs +2 -3
  41. package/dist/runtime/core/bindings/satori/stackblitz.mjs +13 -0
  42. package/dist/runtime/core/bindings/satori/wasm.d.ts +6 -0
  43. package/dist/runtime/core/bindings/satori/wasm.mjs +14 -0
  44. package/dist/runtime/core/cache/emojis.d.ts +1 -0
  45. package/dist/runtime/core/cache/emojis.mjs +5 -0
  46. package/dist/runtime/core/cache/htmlPayload.d.ts +5 -0
  47. package/dist/runtime/core/cache/htmlPayload.mjs +6 -0
  48. package/dist/runtime/core/cache/prerender.d.ts +1 -1
  49. package/dist/runtime/core/cache/prerender.mjs +1 -1
  50. package/dist/runtime/core/env/assets.d.ts +0 -1
  51. package/dist/runtime/core/env/assets.mjs +0 -4
  52. package/dist/runtime/core/font/fetch.d.ts +2 -3
  53. package/dist/runtime/core/font/fetch.mjs +32 -15
  54. package/dist/runtime/core/html/applyEmojis.d.ts +3 -0
  55. package/dist/runtime/core/html/applyEmojis.mjs +37 -0
  56. package/dist/runtime/core/html/applyInlineCss.d.ts +3 -0
  57. package/dist/runtime/core/html/applyInlineCss.mjs +32 -0
  58. package/dist/runtime/core/html/devIframeTemplate.d.ts +2 -0
  59. package/dist/runtime/core/html/{fetch.mjs → devIframeTemplate.mjs} +33 -42
  60. package/dist/runtime/core/html/fetchIsland.d.ts +3 -0
  61. package/dist/runtime/core/html/fetchIsland.mjs +17 -0
  62. package/dist/runtime/core/options/fetch.d.ts +1 -1
  63. package/dist/runtime/core/options/fetch.mjs +10 -5
  64. package/dist/runtime/core/options/normalise.d.ts +2 -2
  65. package/dist/runtime/core/options/normalise.mjs +3 -2
  66. package/dist/runtime/core/renderers/chromium/index.mjs +6 -7
  67. package/dist/runtime/core/renderers/chromium/screenshot.d.ts +2 -3
  68. package/dist/runtime/core/renderers/chromium/screenshot.mjs +8 -8
  69. package/dist/runtime/core/renderers/satori/fonts.d.ts +2 -2
  70. package/dist/runtime/core/renderers/satori/fonts.mjs +2 -2
  71. package/dist/runtime/core/renderers/satori/index.d.ts +2 -3
  72. package/dist/runtime/core/renderers/satori/index.mjs +26 -22
  73. package/dist/runtime/core/renderers/satori/instances.d.ts +3 -0
  74. package/dist/runtime/core/renderers/satori/instances.mjs +15 -0
  75. package/dist/runtime/core/renderers/satori/plugins/emojis.mjs +15 -13
  76. package/dist/runtime/core/renderers/satori/plugins/imageSrc.mjs +23 -10
  77. package/dist/runtime/core/renderers/satori/plugins/unocss.d.ts +2 -0
  78. package/dist/runtime/core/renderers/satori/plugins/unocss.mjs +45 -0
  79. package/dist/runtime/core/renderers/satori/utils.d.ts +2 -3
  80. package/dist/runtime/core/renderers/satori/vnodes.d.ts +2 -3
  81. package/dist/runtime/core/renderers/satori/vnodes.mjs +16 -6
  82. package/dist/runtime/core/utils/resolveRendererContext.d.ts +2 -6
  83. package/dist/runtime/core/utils/resolveRendererContext.mjs +47 -29
  84. package/dist/runtime/core/utils/wasm.d.ts +3 -0
  85. package/dist/runtime/core/utils/wasm.mjs +16 -0
  86. package/dist/runtime/nitro/plugins/nuxt-content.mjs +3 -4
  87. package/dist/runtime/nitro/plugins/prerender.d.ts +1 -1
  88. package/dist/runtime/nitro/plugins/prerender.mjs +20 -12
  89. package/dist/runtime/nitro/utils.d.ts +2 -0
  90. package/dist/runtime/nitro/utils.mjs +17 -0
  91. package/dist/runtime/nuxt/plugins/og-image-canonical-urls.server.mjs +31 -0
  92. package/dist/runtime/nuxt/plugins/route-rule-og-image.server.mjs +16 -50
  93. package/dist/runtime/nuxt/utils.d.ts +2 -0
  94. package/dist/runtime/nuxt/utils.mjs +53 -0
  95. package/dist/runtime/server/routes/__og-image__/debug.json.d.ts +1 -3
  96. package/dist/runtime/server/routes/__og-image__/debug.json.mjs +4 -8
  97. package/dist/runtime/server/routes/__og-image__/image.mjs +87 -0
  98. package/dist/runtime/types.d.ts +77 -25
  99. package/dist/runtime/utils.d.ts +4 -0
  100. package/dist/runtime/utils.mjs +11 -0
  101. package/dist/runtime/utils.pure.d.ts +5 -0
  102. package/dist/runtime/utils.pure.mjs +43 -0
  103. package/package.json +28 -30
  104. package/virtual.d.ts +49 -0
  105. package/dist/client/_nuxt/IconCSS.8f429b14.css +0 -1
  106. package/dist/client/_nuxt/builds/meta/0ca67bfd-95de-4c16-8f0a-055751cdca51.json +0 -1
  107. package/dist/client/_nuxt/entry.089f6f0f.js +0 -137
  108. package/dist/client/_nuxt/entry.434c2c45.css +0 -1
  109. package/dist/client/grid.png +0 -0
  110. package/dist/runtime/components/OgImage/Cached.d.ts +0 -5
  111. package/dist/runtime/components/OgImage/Cached.mjs +0 -10
  112. package/dist/runtime/components/OgImage/Dynamic.d.ts +0 -8
  113. package/dist/runtime/components/OgImage/Dynamic.mjs +0 -10
  114. package/dist/runtime/components/OgImage/Screenshot.d.ts +0 -6
  115. package/dist/runtime/components/OgImage/Static.d.ts +0 -8
  116. package/dist/runtime/components/OgImage/Static.mjs +0 -10
  117. package/dist/runtime/components/OgImage/WithoutCache.d.ts +0 -5
  118. package/dist/runtime/components/OgImage/WithoutCache.mjs +0 -10
  119. package/dist/runtime/components/OgImage/index.d.ts +0 -5
  120. package/dist/runtime/components/Templates/Official/Fallback.vue +0 -147
  121. package/dist/runtime/core/bindings/css-inline/mock.d.ts +0 -5
  122. package/dist/runtime/core/bindings/css-inline/mock.mjs +0 -3
  123. package/dist/runtime/core/bindings/satori/yoga-wasm.mjs +0 -7
  124. package/dist/runtime/core/bindings/sharp/wasm.d.ts +0 -2
  125. package/dist/runtime/core/bindings/sharp/wasm.mjs +0 -2
  126. package/dist/runtime/core/html/fetch.d.ts +0 -3
  127. package/dist/runtime/nuxt/plugins/nuxt-content-canonical-urls.mjs +0 -29
  128. package/dist/runtime/public-assets/__nuxt_og_image__/browser-provider-not-supported.png +0 -0
  129. package/dist/runtime/server/routes/__og-image__/image-[path]-og.[extension].mjs +0 -45
  130. package/dist/runtime/utilts.d.ts +0 -2
  131. package/dist/runtime/utilts.mjs +0 -8
  132. /package/dist/runtime/core/bindings/satori/{yoga-wasm.d.ts → stackblitz.d.ts} +0 -0
  133. /package/dist/runtime/nuxt/plugins/{nuxt-content-canonical-urls.d.ts → og-image-canonical-urls.server.d.ts} +0 -0
  134. /package/dist/runtime/{public-assets-optional/inter-font → server/assets}/inter-latin-ext-400-normal.woff +0 -0
  135. /package/dist/runtime/{public-assets-optional/inter-font → server/assets}/inter-latin-ext-700-normal.woff +0 -0
  136. /package/dist/runtime/server/routes/__og-image__/{image-[path]-og.[extension].d.ts → image.d.ts} +0 -0
@@ -0,0 +1,13 @@
1
+ import _satori, { init } from "satori/wasm";
2
+ import initYoga from "yoga-wasm-web";
3
+ import { readWasmFile } from "../../utils/wasm.mjs";
4
+ const wasm = readWasmFile("yoga-wasm-web/dist/yoga.wasm").then(async (yoga) => await initYoga(yoga));
5
+ export default {
6
+ initWasmPromise: new Promise((resolve) => {
7
+ wasm.then((yoga) => {
8
+ init(yoga);
9
+ resolve();
10
+ });
11
+ }),
12
+ satori: _satori
13
+ };
@@ -0,0 +1,6 @@
1
+ import _satori from 'satori/wasm';
2
+ declare const _default: {
3
+ initWasmPromise: Promise<void>;
4
+ satori: typeof _satori;
5
+ };
6
+ export default _default;
@@ -0,0 +1,14 @@
1
+ import _satori from "satori/wasm";
2
+ import initYoga from "yoga-wasm-web";
3
+ import { init } from "satori";
4
+ import { importWasm } from "../../utils/wasm.mjs";
5
+ const wasm = importWasm(import("yoga-wasm-web/dist/yoga.wasm")).then(async (yoga) => await initYoga(yoga));
6
+ export default {
7
+ initWasmPromise: new Promise((resolve) => {
8
+ wasm.then((yoga) => {
9
+ init(yoga);
10
+ resolve();
11
+ });
12
+ }),
13
+ satori: _satori
14
+ };
@@ -0,0 +1 @@
1
+ export declare const emojiCache: import("unstorage/dist/shared/unstorage.745f9650").a<string>;
@@ -0,0 +1,5 @@
1
+ import { createStorage } from "unstorage";
2
+ import lruCacheDriver from "unstorage/drivers/lru-cache";
3
+ export const emojiCache = createStorage({
4
+ driver: lruCacheDriver({ max: 1e3 })
5
+ });
@@ -0,0 +1,5 @@
1
+ import type { OgImageOptions } from '../../types';
2
+ export declare const htmlPayloadCache: import("unstorage/dist/shared/unstorage.745f9650").a<{
3
+ expiresAt: number;
4
+ value: OgImageOptions;
5
+ }>;
@@ -0,0 +1,6 @@
1
+ import { createStorage } from "unstorage";
2
+ import lruCacheDriver from "unstorage/drivers/lru-cache";
3
+ export const htmlPayloadCache = createStorage({
4
+ // short cache time so we don't need many entries at runtime
5
+ driver: lruCacheDriver({ max: import.meta.prerender ? 1e3 : 50 })
6
+ });
@@ -1,6 +1,6 @@
1
1
  import type { Browser } from 'playwright-core';
2
2
  import type { OgImageOptions } from '../../types';
3
- export declare const prerenderCache: import("unstorage/dist/shared/unstorage.745f9650").a<OgImageOptions> | undefined;
3
+ export declare const prerenderOptionsCache: import("unstorage/dist/shared/unstorage.745f9650").a<OgImageOptions<"NuxtSeo">> | undefined;
4
4
  export declare const prerenderChromiumContext: {
5
5
  browser?: Browser;
6
6
  };
@@ -1,6 +1,6 @@
1
1
  import { createStorage } from "unstorage";
2
2
  import lruCacheDriver from "unstorage/drivers/lru-cache";
3
- export const prerenderCache = import.meta.prerender ? createStorage({
3
+ export const prerenderOptionsCache = import.meta.prerender ? createStorage({
4
4
  driver: lruCacheDriver({ max: 1e3 })
5
5
  }) : void 0;
6
6
  export const prerenderChromiumContext = { browser: void 0 };
@@ -1,2 +1 @@
1
- export declare function base64ToArrayBuffer(base64: string): ArrayBuffer;
2
1
  export declare function toBase64Image(fileName: string, data: string | ArrayBuffer): string;
@@ -1,8 +1,4 @@
1
1
  import { Buffer } from "node:buffer";
2
- export function base64ToArrayBuffer(base64) {
3
- const buffer = Buffer.from(base64, "base64");
4
- return new Uint8Array(buffer).buffer;
5
- }
6
2
  export function toBase64Image(fileName, data) {
7
3
  const base64 = typeof data === "string" ? data : Buffer.from(data).toString("base64");
8
4
  let type = "image/jpeg";
@@ -1,3 +1,2 @@
1
- import type { H3Event } from 'h3';
2
- import type { FontConfig } from '../../types';
3
- export declare function loadFont(e: H3Event, font: FontConfig): Promise<any>;
1
+ import type { FontConfig, OgImageRenderEventContext } from '../../types';
2
+ export declare function loadFont({ e }: OgImageRenderEventContext, font: FontConfig): Promise<any>;
@@ -1,29 +1,46 @@
1
- import { Buffer } from "node:buffer";
2
- import { base64ToArrayBuffer } from "../env/assets.mjs";
1
+ import { createError } from "h3";
3
2
  import { fontCache } from "./cache.mjs";
4
3
  import { useNitroOrigin, useStorage } from "#imports";
5
- export async function loadFont(e, font) {
6
- const fontKey = `${font.name}:${font.weight}`;
7
- const storageKey = `assets:nuxt-og-image:font:${fontKey}`;
4
+ import { assets } from "#internal/nitro/virtual/server-assets";
5
+ export async function loadFont({ e }, font) {
6
+ const fontKey = font.key || `${font.name}:${font.weight}`;
8
7
  if (fontCache[fontKey])
9
8
  return fontCache[fontKey];
10
- const [name, weight] = fontKey.split(":");
9
+ const { name, weight } = font;
11
10
  let data;
12
- if (await useStorage().hasItem(storageKey))
13
- data = base64ToArrayBuffer(await useStorage().getItem(storageKey));
11
+ if (import.meta.dev || import.meta.prerender) {
12
+ if (font.key && await assets.hasItem(font.key))
13
+ data = await assets.getItemRaw(font.key);
14
+ }
14
15
  if (!data) {
15
16
  if (font.path) {
16
- data = await e.$fetch(font.path, {
17
- baseURL: useNitroOrigin(e),
18
- responseType: "arrayBuffer"
19
- });
17
+ if (import.meta.dev || import.meta.prerender) {
18
+ const key = `root:public${font.path.replace("./", ":").replace("/", ":")}`;
19
+ if (await useStorage().hasItem(key))
20
+ data = await useStorage().getItemRaw(key);
21
+ if (!data) {
22
+ data = await e.$fetch(font.path, {
23
+ responseType: "arrayBuffer"
24
+ });
25
+ }
26
+ } else {
27
+ data = await e.$fetch(font.path, {
28
+ baseURL: useNitroOrigin(e),
29
+ responseType: "arrayBuffer"
30
+ });
31
+ }
20
32
  } else {
21
33
  data = await e.$fetch(`/__og-image__/font/${name}/${weight}.ttf`, {
22
34
  responseType: "arrayBuffer"
23
35
  });
24
36
  }
25
37
  }
26
- fontCache[fontKey] = { name, weight: Number(weight), data, style: "normal" };
27
- await useStorage().setItem(storageKey, Buffer.from(data).toString("base64"));
28
- return fontCache[fontKey];
38
+ if (data) {
39
+ fontCache[fontKey] = { name, weight: Number(weight), data, style: "normal" };
40
+ return fontCache[fontKey];
41
+ }
42
+ return createError({
43
+ statusCode: 500,
44
+ statusMessage: `Failed to fetch font: ${fontKey}`
45
+ });
29
46
  }
@@ -0,0 +1,3 @@
1
+ import type { NuxtIslandResponse } from 'nuxt/dist/core/runtime/nitro/renderer';
2
+ import type { OgImageRenderEventContext } from '../../types';
3
+ export declare function applyEmojis(ctx: OgImageRenderEventContext, island: NuxtIslandResponse): Promise<string | boolean>;
@@ -0,0 +1,37 @@
1
+ import defaultCharMap from "@iconify-json/noto/chars.json";
2
+ import { emojiCache } from "../cache/emojis.mjs";
3
+ const RE_MATCH_EMOJIS = /[#*0-9]\uFE0F?\u20E3|[\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23ED-\u23EF\u23F1\u23F2\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB\u25FC\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692\u2694-\u2697\u2699\u269B\u269C\u26A0\u26A7\u26AA\u26B0\u26B1\u26BD\u26BE\u26C4\u26C8\u26CF\u26D1\u26E9\u26F0-\u26F5\u26F7\u26F8\u26FA\u2702\u2708\u2709\u270F\u2712\u2714\u2716\u271D\u2721\u2733\u2734\u2744\u2747\u2757\u2763\u27A1\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B55\u3030\u303D\u3297\u3299]\uFE0F?|[\u261D\u270C\u270D](?:\uFE0F|\uD83C[\uDFFB-\uDFFF])?|[\u270A\u270B](?:\uD83C[\uDFFB-\uDFFF])?|[\u23E9-\u23EC\u23F0\u23F3\u25FD\u2693\u26A1\u26AB\u26C5\u26CE\u26D4\u26EA\u26FD\u2705\u2728\u274C\u274E\u2753-\u2755\u2795-\u2797\u27B0\u27BF\u2B50]|\u26D3\uFE0F?(?:\u200D\uD83D\uDCA5)?|\u26F9(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|\u2764\uFE0F?(?:\u200D(?:\uD83D\uDD25|\uD83E\uDE79))?|\uD83C(?:[\uDC04\uDD70\uDD71\uDD7E\uDD7F\uDE02\uDE37\uDF21\uDF24-\uDF2C\uDF36\uDF7D\uDF96\uDF97\uDF99-\uDF9B\uDF9E\uDF9F\uDFCD\uDFCE\uDFD4-\uDFDF\uDFF5\uDFF7]\uFE0F?|[\uDF85\uDFC2\uDFC7](?:\uD83C[\uDFFB-\uDFFF])?|[\uDFC4\uDFCA](?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDFCB\uDFCC](?:\uFE0F|\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDCCF\uDD8E\uDD91-\uDD9A\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF43\uDF45-\uDF4A\uDF4C-\uDF7C\uDF7E-\uDF84\uDF86-\uDF93\uDFA0-\uDFC1\uDFC5\uDFC6\uDFC8\uDFC9\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF8-\uDFFF]|\uDDE6\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF]|\uDDE7\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF]|\uDDE8\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF5\uDDF7\uDDFA-\uDDFF]|\uDDE9\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF]|\uDDEA\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA]|\uDDEB\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7]|\uDDEC\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE]|\uDDED\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA]|\uDDEE\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9]|\uDDEF\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5]|\uDDF0\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF]|\uDDF1\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE]|\uDDF2\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF]|\uDDF3\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF]|\uDDF4\uD83C\uDDF2|\uDDF5\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE]|\uDDF6\uD83C\uDDE6|\uDDF7\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC]|\uDDF8\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF]|\uDDF9\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF]|\uDDFA\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF]|\uDDFB\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA]|\uDDFC\uD83C[\uDDEB\uDDF8]|\uDDFD\uD83C\uDDF0|\uDDFE\uD83C[\uDDEA\uDDF9]|\uDDFF\uD83C[\uDDE6\uDDF2\uDDFC]|\uDF44(?:\u200D\uD83D\uDFEB)?|\uDF4B(?:\u200D\uD83D\uDFE9)?|\uDFC3(?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D(?:[\u2640\u2642]\uFE0F?(?:\u200D\u27A1\uFE0F?)?|\u27A1\uFE0F?))?|\uDFF3\uFE0F?(?:\u200D(?:\u26A7\uFE0F?|\uD83C\uDF08))?|\uDFF4(?:\u200D\u2620\uFE0F?|\uDB40\uDC67\uDB40\uDC62\uDB40(?:\uDC65\uDB40\uDC6E\uDB40\uDC67|\uDC73\uDB40\uDC63\uDB40\uDC74|\uDC77\uDB40\uDC6C\uDB40\uDC73)\uDB40\uDC7F)?)|\uD83D(?:[\uDC3F\uDCFD\uDD49\uDD4A\uDD6F\uDD70\uDD73\uDD76-\uDD79\uDD87\uDD8A-\uDD8D\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA\uDECB\uDECD-\uDECF\uDEE0-\uDEE5\uDEE9\uDEF0\uDEF3]\uFE0F?|[\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDC8F\uDC91\uDCAA\uDD7A\uDD95\uDD96\uDE4C\uDE4F\uDEC0\uDECC](?:\uD83C[\uDFFB-\uDFFF])?|[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4\uDEB5](?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDD74\uDD90](?:\uFE0F|\uD83C[\uDFFB-\uDFFF])?|[\uDC00-\uDC07\uDC09-\uDC14\uDC16-\uDC25\uDC27-\uDC3A\uDC3C-\uDC3E\uDC40\uDC44\uDC45\uDC51-\uDC65\uDC6A\uDC79-\uDC7B\uDC7D-\uDC80\uDC84\uDC88-\uDC8E\uDC90\uDC92-\uDCA9\uDCAB-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDDA4\uDDFB-\uDE2D\uDE2F-\uDE34\uDE37-\uDE41\uDE43\uDE44\uDE48-\uDE4A\uDE80-\uDEA2\uDEA4-\uDEB3\uDEB7-\uDEBF\uDEC1-\uDEC5\uDED0-\uDED2\uDED5-\uDED7\uDEDC-\uDEDF\uDEEB\uDEEC\uDEF4-\uDEFC\uDFE0-\uDFEB\uDFF0]|\uDC08(?:\u200D\u2B1B)?|\uDC15(?:\u200D\uD83E\uDDBA)?|\uDC26(?:\u200D(?:\u2B1B|\uD83D\uDD25))?|\uDC3B(?:\u200D\u2744\uFE0F?)?|\uDC41\uFE0F?(?:\u200D\uD83D\uDDE8\uFE0F?)?|\uDC68(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDC68\uDC69]\u200D\uD83D(?:\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?)|[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?)|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]))|\uD83C(?:\uDFFB(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFC-\uDFFF])))?|\uDFFC(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB\uDFFD-\uDFFF])))?|\uDFFD(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])))?|\uDFFE(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB-\uDFFD\uDFFF])))?|\uDFFF(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB-\uDFFE])))?))?|\uDC69(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?[\uDC68\uDC69]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?|\uDC69\u200D\uD83D(?:\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?))|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]))|\uD83C(?:\uDFFB(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFC-\uDFFF])))?|\uDFFC(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB\uDFFD-\uDFFF])))?|\uDFFD(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])))?|\uDFFE(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB-\uDFFD\uDFFF])))?|\uDFFF(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB-\uDFFE])))?))?|\uDC6F(?:\u200D[\u2640\u2642]\uFE0F?)?|\uDD75(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|\uDE2E(?:\u200D\uD83D\uDCA8)?|\uDE35(?:\u200D\uD83D\uDCAB)?|\uDE36(?:\u200D\uD83C\uDF2B\uFE0F?)?|\uDE42(?:\u200D[\u2194\u2195]\uFE0F?)?|\uDEB6(?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D(?:[\u2640\u2642]\uFE0F?(?:\u200D\u27A1\uFE0F?)?|\u27A1\uFE0F?))?)|\uD83E(?:[\uDD0C\uDD0F\uDD18-\uDD1F\uDD30-\uDD34\uDD36\uDD77\uDDB5\uDDB6\uDDBB\uDDD2\uDDD3\uDDD5\uDEC3-\uDEC5\uDEF0\uDEF2-\uDEF8](?:\uD83C[\uDFFB-\uDFFF])?|[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD\uDDCF\uDDD4\uDDD6-\uDDDD](?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDDDE\uDDDF](?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDD0D\uDD0E\uDD10-\uDD17\uDD20-\uDD25\uDD27-\uDD2F\uDD3A\uDD3F-\uDD45\uDD47-\uDD76\uDD78-\uDDB4\uDDB7\uDDBA\uDDBC-\uDDCC\uDDD0\uDDE0-\uDDFF\uDE70-\uDE7C\uDE80-\uDE88\uDE90-\uDEBD\uDEBF-\uDEC2\uDECE-\uDEDB\uDEE0-\uDEE8]|\uDD3C(?:\u200D[\u2640\u2642]\uFE0F?|\uD83C[\uDFFB-\uDFFF])?|\uDDCE(?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D(?:[\u2640\u2642]\uFE0F?(?:\u200D\u27A1\uFE0F?)?|\u27A1\uFE0F?))?|\uDDD1(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83E\uDDD1|\uDDD1\u200D\uD83E\uDDD2(?:\u200D\uD83E\uDDD2)?|\uDDD2(?:\u200D\uD83E\uDDD2)?))|\uD83C(?:\uDFFB(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFC-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?|\uDFFC(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB\uDFFD-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?|\uDFFD(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?|\uDFFE(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB-\uDFFD\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?|\uDFFF(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB-\uDFFE]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?))?|\uDEF1(?:\uD83C(?:\uDFFB(?:\u200D\uD83E\uDEF2\uD83C[\uDFFC-\uDFFF])?|\uDFFC(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB\uDFFD-\uDFFF])?|\uDFFD(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])?|\uDFFE(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB-\uDFFD\uDFFF])?|\uDFFF(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB-\uDFFE])?))?)/g;
4
+ export async function applyEmojis(ctx, island) {
5
+ const html = island.html;
6
+ const matches = html.match(RE_MATCH_EMOJIS);
7
+ if (!matches)
8
+ return html;
9
+ const replacements = await Promise.all(matches.map(async (match) => {
10
+ const unicode = match.codePointAt(0).toString(16);
11
+ const emoji = defaultCharMap[unicode];
12
+ if (emoji) {
13
+ const key = ["1", ctx.options.emojis, emoji].join(":");
14
+ let svg;
15
+ if (await emojiCache.hasItem(key))
16
+ svg = await emojiCache.getItem(key);
17
+ if (!svg) {
18
+ svg = await ctx.e.$fetch(`https://api.iconify.design/${ctx.options.emojis}/${emoji}.svg`, {
19
+ responseType: "text"
20
+ });
21
+ if (svg === "404")
22
+ svg = void 0;
23
+ if (svg)
24
+ await emojiCache.setItem(key, svg);
25
+ }
26
+ if (svg)
27
+ return `
28
+ ${svg.replace("<svg ", '<svg data-emoji style="margin: 0 .05em 0 .15em; vertical-align: -0.1em;" ')}
29
+ `;
30
+ return match;
31
+ }
32
+ }));
33
+ const finalHtml = html.replace(RE_MATCH_EMOJIS, () => replacements.shift());
34
+ const modified = finalHtml !== island.html;
35
+ island.html = finalHtml;
36
+ return modified;
37
+ }
@@ -0,0 +1,3 @@
1
+ import type { NuxtIslandResponse } from 'nuxt/dist/core/runtime/nitro/renderer';
2
+ import type { OgImageRenderEventContext } from '../../types';
3
+ export declare function applyInlineCss({ e }: OgImageRenderEventContext, island: NuxtIslandResponse): Promise<boolean>;
@@ -0,0 +1,32 @@
1
+ import { useCssInline } from "../renderers/satori/instances.mjs";
2
+ import { useNitroOrigin } from "#imports";
3
+ import cssInline from "#nuxt-og-image/bindings/css-inline";
4
+ export async function applyInlineCss({ e }, island) {
5
+ let html = island.html;
6
+ const componentInlineStyles = island.head.link.filter((l) => l.href.startsWith("/_nuxt/components"));
7
+ const usingInlineCss = !!componentInlineStyles.length;
8
+ if (!cssInline.__unenv__ && componentInlineStyles.length) {
9
+ const css = island.head.style.map((s) => s.innerHTML).join("\n");
10
+ const linksToCss = (await Promise.all(
11
+ componentInlineStyles.map((l) => {
12
+ return e.$fetch(`${l.href}&hmr=false`, {
13
+ responseType: "text",
14
+ baseURL: useNitroOrigin(e)
15
+ }).then((res) => {
16
+ return res.trim().split("\n").filter((l2) => !l2.startsWith("//")).join("\n").trim();
17
+ });
18
+ })
19
+ )).join("\n");
20
+ const cssToInline = `${linksToCss}${css}`;
21
+ const cssInline2 = await useCssInline();
22
+ html = cssInline2.inline(island.html, {
23
+ load_remote_stylesheets: false,
24
+ extra_css: cssToInline
25
+ });
26
+ const classes = cssToInline.match(/\.([a-zA-Z0-9-_]+)/g)?.map((c) => c.replace(".", ""));
27
+ if (classes)
28
+ html = html.replace(new RegExp(`class="(${classes.join("|")})"`, "g"), "");
29
+ island.html = html;
30
+ }
31
+ return usingInlineCss;
32
+ }
@@ -0,0 +1,2 @@
1
+ import type { OgImageRenderEventContext } from '../../types';
2
+ export declare function devIframeTemplate(ctx: OgImageRenderEventContext): Promise<string>;
@@ -1,37 +1,21 @@
1
- import { createError } from "h3";
2
- import { hash } from "ohash";
3
1
  import { createHeadCore } from "@unhead/vue";
4
- import twemoji from "twemoji";
5
2
  import { renderSSRHead } from "@unhead/ssr";
6
- import { useRuntimeConfig } from "#imports";
7
- export async function fetchHTML(e, options) {
8
- const { fonts, satoriOptions } = useRuntimeConfig()["nuxt-og-image"];
9
- if (!options.component) {
10
- throw createError({
11
- statusCode: 500,
12
- statusMessage: `Nuxt OG Image trying to render an invalid component. Received options ${JSON.stringify(options)}`
13
- });
14
- }
15
- const hashId = hash([options.component, options, Math.random() * 100]);
16
- const island = await e.$fetch(`/__nuxt_island/${options.component}_${hashId}.json`, {
17
- params: {
18
- props: JSON.stringify(options)
19
- }
20
- });
3
+ import { useOgImageRuntimeConfig } from "../../utils.mjs";
4
+ import { applyEmojis } from "./applyEmojis.mjs";
5
+ import { fetchIsland } from "./fetchIsland.mjs";
6
+ import { theme } from "#nuxt-og-image/unocss-config.mjs";
7
+ export async function devIframeTemplate(ctx) {
8
+ const { options } = ctx;
9
+ const { fonts } = useOgImageRuntimeConfig();
10
+ const island = await fetchIsland(ctx);
21
11
  const head = createHeadCore();
22
12
  head.push(island.head);
23
13
  let defaultFontFamily = "sans-serif";
24
14
  const firstFont = fonts[0];
25
15
  if (firstFont)
26
16
  defaultFontFamily = firstFont.name;
17
+ await applyEmojis(ctx, island);
27
18
  let html = island.html;
28
- try {
29
- html = twemoji.parse(html, {
30
- folder: "svg",
31
- ext: ".svg"
32
- });
33
- } catch (e2) {
34
- }
35
19
  const googleFonts = {};
36
20
  fonts.filter((font) => !font.path).forEach((font) => {
37
21
  if (!googleFonts[font.name])
@@ -46,21 +30,23 @@ export async function fetchHTML(e, options) {
46
30
  },
47
31
  {
48
32
  innerHTML: `body {
49
- transform: scale(${options.scale || 1});
33
+ transform: scale(${options.props.scale || 1});
50
34
  transform-origin: top left;
51
35
  max-height: 100vh;
52
36
  position: relative;
53
37
  width: ${options.width}px;
54
38
  height: ${options.height}px;
55
39
  overflow: hidden;
56
- background-color: ${options.mode === "dark" ? "#1b1b1b" : "#fff"};
40
+ background-color: ${options.props.colorMode === "dark" ? "#1b1b1b" : "#fff"};
41
+ }
42
+ div {
43
+ display: flex;
44
+ flex-direction: column;
45
+ }
46
+ svg[data-emoji] {
47
+ display: inline-block;
57
48
  }
58
- img.emoji {
59
- height: 1em;
60
- width: 1em;
61
- margin: 0 .05em 0 .1em;
62
- vertical-align: -0.1em;
63
- }`
49
+ `
64
50
  },
65
51
  ...fonts.filter((font) => font.path).map((font) => {
66
52
  return `
@@ -80,15 +66,20 @@ img.emoji {
80
66
  ],
81
67
  script: [
82
68
  {
83
- src: "https://cdn.tailwindcss.com"
69
+ src: "https://cdn.jsdelivr.net/npm/@unocss/runtime/preset-wind.global.js"
70
+ },
71
+ {
72
+ innerHTML: `
73
+ window.__unocss = {
74
+ theme: ${JSON.stringify(theme)},
75
+ presets: [
76
+ () => window.__unocss_runtime.presets.presetWind(),
77
+ ],
78
+ }
79
+ `
84
80
  },
85
81
  {
86
- innerHTML: `tailwind.config = {
87
- corePlugins: {
88
- preflight: false,
89
- },
90
- theme: ${JSON.stringify(satoriOptions?.tailwindConfig?.theme || {})}
91
- }`
82
+ src: "https://cdn.jsdelivr.net/npm/@unocss/runtime/core.global.js"
92
83
  }
93
84
  ],
94
85
  link: [
@@ -98,6 +89,7 @@ img.emoji {
98
89
  rel: "stylesheet"
99
90
  },
100
91
  // have to add each weight as their own stylesheet
92
+ // we should use the local font file no?
101
93
  ...Object.entries(googleFonts).map(([name, fonts2]) => {
102
94
  return {
103
95
  href: `https://fonts.googleapis.com/css2?family=${name}:wght@${fonts2.map((f) => f.weight).join(";")}&display=swap`,
@@ -108,10 +100,9 @@ img.emoji {
108
100
  });
109
101
  html = html.replaceAll(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, "");
110
102
  const headChunk = await renderSSRHead(head);
111
- const htmlTemplate = `<!DOCTYPE html>
103
+ return `<!DOCTYPE html>
112
104
  <html ${headChunk.htmlAttrs}>
113
105
  <head>${headChunk.headTags}</head>
114
106
  <body ${headChunk.bodyAttrs}>${headChunk.bodyTagsOpen}<div data-v-inspector-ignore="true" style="position: relative; display: flex; margin: 0 auto; width: ${options.width}px; height: ${options.height}px; overflow: hidden;">${html}</div>${headChunk.bodyTags}</body>
115
107
  </html>`;
116
- return htmlTemplate;
117
108
  }
@@ -0,0 +1,3 @@
1
+ import type { NuxtIslandResponse } from 'nuxt/dist/core/runtime/nitro/renderer';
2
+ import type { OgImageRenderEventContext } from '../../types';
3
+ export declare function fetchIsland({ options, e }: OgImageRenderEventContext): Promise<NuxtIslandResponse>;
@@ -0,0 +1,17 @@
1
+ import { createError } from "h3";
2
+ import { hash } from "ohash";
3
+ export function fetchIsland({ options, e }) {
4
+ if (!options.component) {
5
+ throw createError({
6
+ statusCode: 500,
7
+ statusMessage: `Nuxt OG Image trying to render an invalid component. Received options ${JSON.stringify(options)}`
8
+ });
9
+ }
10
+ const hashId = hash([options.component, options]);
11
+ const props = typeof options.props !== "undefined" ? options.props : options;
12
+ return e.$fetch(`/__nuxt_island/${options.component}_${hashId}.json`, {
13
+ params: {
14
+ props: JSON.stringify(props)
15
+ }
16
+ });
17
+ }
@@ -1,3 +1,3 @@
1
1
  import { type H3Error, type H3Event } from 'h3';
2
2
  import type { OgImageOptions } from '../../types';
3
- export declare function fetchPathHtmlAndExtractOptions(e: H3Event, path: string): Promise<H3Error | OgImageOptions>;
3
+ export declare function fetchPathHtmlAndExtractOptions(e: H3Event, path: string, key: string): Promise<H3Error | OgImageOptions>;
@@ -1,6 +1,10 @@
1
1
  import { createError } from "h3";
2
+ import { htmlPayloadCache } from "../cache/htmlPayload.mjs";
2
3
  import { extractAndNormaliseOgImageOptions } from "./extract.mjs";
3
- export async function fetchPathHtmlAndExtractOptions(e, path) {
4
+ export async function fetchPathHtmlAndExtractOptions(e, path, key) {
5
+ const cachedHtmlPayload = await htmlPayloadCache.getItem(key);
6
+ if (cachedHtmlPayload && cachedHtmlPayload.expiresAt < Date.now())
7
+ return cachedHtmlPayload.value;
4
8
  let html;
5
9
  try {
6
10
  html = await e.$fetch(path);
@@ -11,10 +15,11 @@ export async function fetchPathHtmlAndExtractOptions(e, path) {
11
15
  });
12
16
  }
13
17
  const payload = extractAndNormaliseOgImageOptions(html);
14
- if (!payload) {
15
- return createError({
16
- statusCode: 400,
17
- statusMessage: `The path is missing the Nuxt OG Image payload. Did you forget to use defineOgImage()?`
18
+ if (payload) {
19
+ await htmlPayloadCache.setItem(key, {
20
+ // 60 minutes for prerender, 10 seconds for runtime
21
+ expiresAt: Date.now() + 1e3 * (import.meta.prerender ? 60 * 60 : 10),
22
+ value: payload
18
23
  });
19
24
  }
20
25
  return payload;
@@ -1,2 +1,2 @@
1
- import type { OgImageOptions } from '../../types';
2
- export declare function normaliseOptions(_options: OgImageOptions): any;
1
+ import type { DefineOgImageInput, OgImageOptions, OgImagePrebuilt } from '../../types';
2
+ export declare function normaliseOptions(_options: DefineOgImageInput): OgImageOptions | OgImagePrebuilt;
@@ -1,7 +1,8 @@
1
- import { unref, useRuntimeConfig } from "#imports";
1
+ import { useOgImageRuntimeConfig } from "../../utils.mjs";
2
+ import { unref } from "#imports";
2
3
  import { componentNames } from "#build/og-image-component-names.mjs";
3
4
  export function normaliseOptions(_options) {
4
- const { runtimeSatori } = useRuntimeConfig()["nuxt-og-image"];
5
+ const { runtimeSatori } = useOgImageRuntimeConfig();
5
6
  const options = { ...unref(_options) };
6
7
  if (options.static)
7
8
  options.cache = options.cache || options.static;
@@ -1,11 +1,13 @@
1
- import { getOgImagePath } from "../../../utilts.mjs";
2
1
  import { prerenderChromiumContext } from "../../cache/prerender.mjs";
3
2
  import { createScreenshot } from "./screenshot.mjs";
4
3
  import { createBrowser } from "#nuxt-og-image/bindings/chromium";
5
4
  const ChromiumRenderer = {
6
5
  name: "chromium",
7
- supportedFormats: ["png", "jpeg"],
8
- async createImage(e, options) {
6
+ supportedFormats: ["png", "jpeg", "jpg"],
7
+ async debug() {
8
+ return {};
9
+ },
10
+ async createImage(ctx) {
9
11
  const browser = (import.meta.prerender ? prerenderChromiumContext.browser : null) || await createBrowser();
10
12
  if (!browser) {
11
13
  return createError({
@@ -15,10 +17,7 @@ const ChromiumRenderer = {
15
17
  }
16
18
  if (import.meta.prerender)
17
19
  prerenderChromiumContext.browser = browser;
18
- return createScreenshot(e, browser, {
19
- ...options,
20
- path: options.component === "PageScreenshot" ? options.path : getOgImagePath(options.path, "html")
21
- }).finally(async () => {
20
+ return createScreenshot(ctx, browser).finally(async () => {
22
21
  await browser.close();
23
22
  });
24
23
  }
@@ -1,6 +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 { H3Event } from 'h3';
5
- import type { RendererOptions } from '../../../types';
6
- export declare function createScreenshot(e: H3Event, browser: Browser, options: RendererOptions): Promise<Buffer>;
4
+ import type { OgImageRenderEventContext } from '../../../types';
5
+ export declare function createScreenshot({ basePath, e, options, extension }: OgImageRenderEventContext, browser: Browser): Promise<Buffer>;
@@ -1,21 +1,21 @@
1
- import { withQuery } from "ufo";
1
+ import { joinURL, withQuery } from "ufo";
2
2
  import { useNitroOrigin } from "#imports";
3
- export async function createScreenshot(e, browser, options) {
3
+ export async function createScreenshot({ basePath, e, options, extension }, browser) {
4
+ const path = options.component === "PageScreenshot" ? basePath : joinURL("/__og-image__/image", basePath, `og.html`);
4
5
  const page = await browser.newPage({
5
6
  colorScheme: options.colorScheme,
6
7
  baseURL: useNitroOrigin(e)
7
8
  });
8
9
  if (import.meta.prerender && !options.html) {
9
- options.html = await e.$fetch(options.path);
10
+ options.html = await e.$fetch(path);
10
11
  }
11
12
  try {
12
13
  await page.setViewportSize({
13
14
  width: options.width || 1200,
14
15
  height: options.height || 630
15
16
  });
16
- const isHtml = options.html || options.path?.startsWith("html:");
17
- if (isHtml) {
18
- const html = options.html || options.path?.substring(5);
17
+ if (options.html) {
18
+ const html = options.html;
19
19
  await page.evaluate((html2) => {
20
20
  document.open("text/html");
21
21
  document.write(html2);
@@ -23,7 +23,7 @@ export async function createScreenshot(e, browser, options) {
23
23
  }, html);
24
24
  await page.waitForLoadState("networkidle");
25
25
  } else {
26
- await page.goto(withQuery(options.path, options), {
26
+ await page.goto(withQuery(path, options.props), {
27
27
  timeout: 1e4,
28
28
  waitUntil: "networkidle"
29
29
  });
@@ -31,7 +31,7 @@ export async function createScreenshot(e, browser, options) {
31
31
  const screenshotOptions = {
32
32
  timeout: 1e4,
33
33
  animations: "disabled",
34
- type: options.extension
34
+ type: extension === "png" ? "png" : "jpeg"
35
35
  };
36
36
  if (options.mask) {
37
37
  await page.evaluate((mask) => {
@@ -1,3 +1,3 @@
1
- import type { FontConfig } from '../../../types';
1
+ import type { FontConfig, OgImageRenderEventContext } from '../../../types';
2
2
  export declare const satoriFonts: any[];
3
- export declare function loadFonts(baseURL: string, fonts: FontConfig[]): Promise<any>;
3
+ export declare function loadFonts(e: OgImageRenderEventContext, fonts: FontConfig[]): Promise<any>;
@@ -1,8 +1,8 @@
1
1
  import { loadFont } from "../../font/fetch.mjs";
2
2
  export const satoriFonts = [];
3
3
  let fontLoadPromise = null;
4
- export function loadFonts(baseURL, fonts) {
4
+ export function loadFonts(e, fonts) {
5
5
  if (fontLoadPromise)
6
6
  return fontLoadPromise;
7
- return fontLoadPromise = Promise.all(fonts.map((font) => loadFont(baseURL, font)));
7
+ return fontLoadPromise = Promise.all(fonts.map((font) => loadFont(e, font)));
8
8
  }
@@ -1,5 +1,4 @@
1
- import type { H3Event } from 'h3';
2
- import type { Renderer, RendererOptions } from '../../../types';
3
- export declare function createSvg(e: H3Event, options: RendererOptions): Promise<string>;
1
+ import type { OgImageRenderEventContext, Renderer } from '../../../types';
2
+ export declare function createSvg(event: OgImageRenderEventContext): Promise<string>;
4
3
  declare const SatoriRenderer: Renderer;
5
4
  export default SatoriRenderer;