nuxt-og-image 5.1.10 → 5.1.11
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.
- package/dist/client/200.html +1 -0
- package/dist/client/404.html +1 -0
- package/dist/client/_nuxt/B8PEiB0p.js +1 -0
- package/dist/client/_nuxt/CVO1_9PV.js +1 -0
- package/dist/client/_nuxt/Cp-IABpG.js +1 -0
- package/dist/client/_nuxt/CvR-yWOW.js +4062 -0
- package/dist/client/_nuxt/D0r3Knsf.js +1 -0
- package/dist/client/_nuxt/DEnNbrAc.js +1 -0
- package/dist/client/_nuxt/DeGaHs8e.js +1 -0
- package/dist/client/_nuxt/builds/latest.json +1 -0
- package/dist/client/_nuxt/builds/meta/fc37de2c-ce5a-4687-b9b5-2020cf8f035c.json +1 -0
- package/dist/client/_nuxt/entry.DykVEqUW.css +1 -0
- package/dist/client/_nuxt/error-404.C93MUFlo.css +1 -0
- package/dist/client/_nuxt/error-500.D-IxLaDc.css +1 -0
- package/dist/client/_nuxt/l5rcX3cq.js +8 -0
- package/dist/client/index.html +1 -0
- package/dist/content.cjs +22 -0
- package/dist/content.d.cts +46 -0
- package/dist/content.d.mts +46 -0
- package/dist/content.d.ts +46 -0
- package/dist/content.mjs +18 -0
- package/dist/module.cjs +1018 -0
- package/dist/module.d.cts +109 -0
- package/dist/module.d.mts +109 -0
- package/dist/module.d.ts +109 -0
- package/dist/module.json +12 -0
- package/dist/module.mjs +998 -0
- package/dist/runtime/app/components/OgImage/OgImage.d.ts +3 -0
- package/dist/runtime/app/components/OgImage/OgImage.js +10 -0
- package/dist/runtime/app/components/OgImage/OgImageScreenshot.d.ts +3 -0
- package/dist/runtime/app/components/OgImage/OgImageScreenshot.js +10 -0
- package/dist/runtime/app/components/Templates/Community/BrandedLogo.d.vue.ts +12 -0
- package/dist/runtime/app/components/Templates/Community/BrandedLogo.vue +22 -0
- package/dist/runtime/app/components/Templates/Community/BrandedLogo.vue.d.ts +12 -0
- package/dist/runtime/app/components/Templates/Community/Frame.d.vue.ts +20 -0
- package/dist/runtime/app/components/Templates/Community/Frame.vue +58 -0
- package/dist/runtime/app/components/Templates/Community/Frame.vue.d.ts +20 -0
- package/dist/runtime/app/components/Templates/Community/Nuxt.d.vue.ts +11 -0
- package/dist/runtime/app/components/Templates/Community/Nuxt.vue +179 -0
- package/dist/runtime/app/components/Templates/Community/Nuxt.vue.d.ts +11 -0
- package/dist/runtime/app/components/Templates/Community/NuxtSeo.d.vue.ts +14 -0
- package/dist/runtime/app/components/Templates/Community/NuxtSeo.vue +103 -0
- package/dist/runtime/app/components/Templates/Community/NuxtSeo.vue.d.ts +14 -0
- package/dist/runtime/app/components/Templates/Community/Pergel.d.vue.ts +11 -0
- package/dist/runtime/app/components/Templates/Community/Pergel.vue +98 -0
- package/dist/runtime/app/components/Templates/Community/Pergel.vue.d.ts +11 -0
- package/dist/runtime/app/components/Templates/Community/SimpleBlog.d.vue.ts +8 -0
- package/dist/runtime/app/components/Templates/Community/SimpleBlog.vue +27 -0
- package/dist/runtime/app/components/Templates/Community/SimpleBlog.vue.d.ts +8 -0
- package/dist/runtime/app/components/Templates/Community/UnJs.d.vue.ts +20 -0
- package/dist/runtime/app/components/Templates/Community/UnJs.vue +99 -0
- package/dist/runtime/app/components/Templates/Community/UnJs.vue.d.ts +20 -0
- package/dist/runtime/app/components/Templates/Community/Wave.d.vue.ts +10 -0
- package/dist/runtime/app/components/Templates/Community/Wave.vue +28 -0
- package/dist/runtime/app/components/Templates/Community/Wave.vue.d.ts +10 -0
- package/dist/runtime/app/components/Templates/Community/WithEmoji.d.vue.ts +12 -0
- package/dist/runtime/app/components/Templates/Community/WithEmoji.vue +21 -0
- package/dist/runtime/app/components/Templates/Community/WithEmoji.vue.d.ts +12 -0
- package/dist/runtime/app/composables/defineOgImage.d.ts +2 -0
- package/dist/runtime/app/composables/defineOgImage.js +43 -0
- package/dist/runtime/app/composables/defineOgImageComponent.d.ts +3 -0
- package/dist/runtime/app/composables/defineOgImageComponent.js +8 -0
- package/dist/runtime/app/composables/defineOgImageScreenshot.d.ts +2 -0
- package/dist/runtime/app/composables/defineOgImageScreenshot.js +14 -0
- package/dist/runtime/app/composables/mock.d.ts +5 -0
- package/dist/runtime/app/composables/mock.js +20 -0
- package/dist/runtime/app/plugins/__zero-runtime/og-image-canonical-urls.server.d.ts +2 -0
- package/dist/runtime/app/plugins/__zero-runtime/og-image-canonical-urls.server.js +9 -0
- package/dist/runtime/app/plugins/__zero-runtime/route-rule-og-image.server.d.ts +2 -0
- package/dist/runtime/app/plugins/__zero-runtime/route-rule-og-image.server.js +9 -0
- package/dist/runtime/app/plugins/og-image-canonical-urls.server.d.ts +2 -0
- package/dist/runtime/app/plugins/og-image-canonical-urls.server.js +7 -0
- package/dist/runtime/app/plugins/route-rule-og-image.server.d.ts +2 -0
- package/dist/runtime/app/plugins/route-rule-og-image.server.js +7 -0
- package/dist/runtime/app/utils/plugins.d.ts +3 -0
- package/dist/runtime/app/utils/plugins.js +92 -0
- package/dist/runtime/app/utils.d.ts +7 -0
- package/dist/runtime/app/utils.js +94 -0
- package/dist/runtime/assets/Inter-normal-400.ttf.base64 +1 -0
- package/dist/runtime/assets/Inter-normal-700.ttf.base64 +1 -0
- package/dist/runtime/logger.d.ts +2 -0
- package/dist/runtime/logger.js +8 -0
- package/dist/runtime/mock/empty.d.ts +2 -0
- package/dist/runtime/mock/empty.js +2 -0
- package/dist/runtime/mock/proxy-cjs.d.ts +2 -0
- package/dist/runtime/mock/proxy-cjs.js +2 -0
- package/dist/runtime/server/og-image/bindings/chromium/chrome-launcher.d.ts +2 -0
- package/dist/runtime/server/og-image/bindings/chromium/chrome-launcher.js +9 -0
- package/dist/runtime/server/og-image/bindings/chromium/on-demand.d.ts +2 -0
- package/dist/runtime/server/og-image/bindings/chromium/on-demand.js +40 -0
- package/dist/runtime/server/og-image/bindings/chromium/playwright.d.ts +2 -0
- package/dist/runtime/server/og-image/bindings/chromium/playwright.js +6 -0
- package/dist/runtime/server/og-image/bindings/css-inline/node.d.ts +8 -0
- package/dist/runtime/server/og-image/bindings/css-inline/node.js +7 -0
- package/dist/runtime/server/og-image/bindings/css-inline/wasm-fs.d.ts +7 -0
- package/dist/runtime/server/og-image/bindings/css-inline/wasm-fs.js +8 -0
- package/dist/runtime/server/og-image/bindings/css-inline/wasm.d.ts +7 -0
- package/dist/runtime/server/og-image/bindings/css-inline/wasm.js +7 -0
- package/dist/runtime/server/og-image/bindings/resvg/node.d.ts +6 -0
- package/dist/runtime/server/og-image/bindings/resvg/node.js +5 -0
- package/dist/runtime/server/og-image/bindings/resvg/wasm-fs.d.ts +40 -0
- package/dist/runtime/server/og-image/bindings/resvg/wasm-fs.js +6 -0
- package/dist/runtime/server/og-image/bindings/resvg/wasm.d.ts +40 -0
- package/dist/runtime/server/og-image/bindings/resvg/wasm.js +5 -0
- package/dist/runtime/server/og-image/bindings/satori/node.d.ts +6 -0
- package/dist/runtime/server/og-image/bindings/satori/node.js +5 -0
- package/dist/runtime/server/og-image/bindings/satori/wasm-fs.d.ts +6 -0
- package/dist/runtime/server/og-image/bindings/satori/wasm-fs.js +13 -0
- package/dist/runtime/server/og-image/bindings/satori/wasm.d.ts +6 -0
- package/dist/runtime/server/og-image/bindings/satori/wasm.js +13 -0
- package/dist/runtime/server/og-image/bindings/sharp/node.d.ts +2 -0
- package/dist/runtime/server/og-image/bindings/sharp/node.js +2 -0
- package/dist/runtime/server/og-image/cache/lru.d.ts +9 -0
- package/dist/runtime/server/og-image/cache/lru.js +15 -0
- package/dist/runtime/server/og-image/cache/mock.d.ts +9 -0
- package/dist/runtime/server/og-image/cache/mock.js +9 -0
- package/dist/runtime/server/og-image/chromium/renderer.d.ts +3 -0
- package/dist/runtime/server/og-image/chromium/renderer.js +24 -0
- package/dist/runtime/server/og-image/chromium/screenshot.d.ts +4 -0
- package/dist/runtime/server/og-image/chromium/screenshot.js +54 -0
- package/dist/runtime/server/og-image/context.d.ts +5 -0
- package/dist/runtime/server/og-image/context.js +283 -0
- package/dist/runtime/server/og-image/instances.d.ts +2 -0
- package/dist/runtime/server/og-image/instances.js +10 -0
- package/dist/runtime/server/og-image/satori/font.d.ts +3 -0
- package/dist/runtime/server/og-image/satori/font.js +40 -0
- package/dist/runtime/server/og-image/satori/instances.d.ts +41 -0
- package/dist/runtime/server/og-image/satori/instances.js +23 -0
- package/dist/runtime/server/og-image/satori/plugins/classes.d.ts +2 -0
- package/dist/runtime/server/og-image/satori/plugins/classes.js +17 -0
- package/dist/runtime/server/og-image/satori/plugins/emojis.d.ts +2 -0
- package/dist/runtime/server/og-image/satori/plugins/emojis.js +28 -0
- package/dist/runtime/server/og-image/satori/plugins/encoding.d.ts +2 -0
- package/dist/runtime/server/og-image/satori/plugins/encoding.js +17 -0
- package/dist/runtime/server/og-image/satori/plugins/flex.d.ts +2 -0
- package/dist/runtime/server/og-image/satori/plugins/flex.js +60 -0
- package/dist/runtime/server/og-image/satori/plugins/imageSrc.d.ts +2 -0
- package/dist/runtime/server/og-image/satori/plugins/imageSrc.js +107 -0
- package/dist/runtime/server/og-image/satori/plugins/nuxt-icon.d.ts +2 -0
- package/dist/runtime/server/og-image/satori/plugins/nuxt-icon.js +20 -0
- package/dist/runtime/server/og-image/satori/plugins/unocss.d.ts +2 -0
- package/dist/runtime/server/og-image/satori/plugins/unocss.js +55 -0
- package/dist/runtime/server/og-image/satori/renderer.d.ts +4 -0
- package/dist/runtime/server/og-image/satori/renderer.js +123 -0
- package/dist/runtime/server/og-image/satori/transforms/emojis.d.ts +3 -0
- package/dist/runtime/server/og-image/satori/transforms/emojis.js +3595 -0
- package/dist/runtime/server/og-image/satori/transforms/inlineCss.d.ts +3 -0
- package/dist/runtime/server/og-image/satori/transforms/inlineCss.js +51 -0
- package/dist/runtime/server/og-image/satori/utils.d.ts +3 -0
- package/dist/runtime/server/og-image/satori/utils.js +24 -0
- package/dist/runtime/server/og-image/satori/vnodes.d.ts +2 -0
- package/dist/runtime/server/og-image/satori/vnodes.js +40 -0
- package/dist/runtime/server/og-image/templates/html.d.ts +2 -0
- package/dist/runtime/server/og-image/templates/html.js +112 -0
- package/dist/runtime/server/plugins/__zero-runtime/nuxt-content-v2.d.ts +2 -0
- package/dist/runtime/server/plugins/__zero-runtime/nuxt-content-v2.js +9 -0
- package/dist/runtime/server/plugins/nuxt-content-v2.d.ts +2 -0
- package/dist/runtime/server/plugins/nuxt-content-v2.js +5 -0
- package/dist/runtime/server/plugins/prerender.d.ts +2 -0
- package/dist/runtime/server/plugins/prerender.js +38 -0
- package/dist/runtime/server/routes/__zero-runtime/font.d.ts +2 -0
- package/dist/runtime/server/routes/__zero-runtime/font.js +8 -0
- package/dist/runtime/server/routes/__zero-runtime/image.d.ts +2 -0
- package/dist/runtime/server/routes/__zero-runtime/image.js +8 -0
- package/dist/runtime/server/routes/debug.json.d.ts +7 -0
- package/dist/runtime/server/routes/debug.json.js +15 -0
- package/dist/runtime/server/routes/font.d.ts +2 -0
- package/dist/runtime/server/routes/font.js +3 -0
- package/dist/runtime/server/routes/image.d.ts +2 -0
- package/dist/runtime/server/routes/image.js +3 -0
- package/dist/runtime/server/tsconfig.json +3 -0
- package/dist/runtime/server/util/cache.d.ts +10 -0
- package/dist/runtime/server/util/cache.js +74 -0
- package/dist/runtime/server/util/encoding.d.ts +3 -0
- package/dist/runtime/server/util/encoding.js +15 -0
- package/dist/runtime/server/util/eventHandlers.d.ts +3 -0
- package/dist/runtime/server/util/eventHandlers.js +156 -0
- package/dist/runtime/server/util/kit.d.ts +6 -0
- package/dist/runtime/server/util/kit.js +32 -0
- package/dist/runtime/server/util/logger.d.ts +1 -0
- package/dist/runtime/server/util/logger.js +6 -0
- package/dist/runtime/server/util/options.d.ts +2 -0
- package/dist/runtime/server/util/options.js +18 -0
- package/dist/runtime/server/util/plugins.d.ts +2 -0
- package/dist/runtime/server/util/plugins.js +56 -0
- package/dist/runtime/server/util/wasm.d.ts +2 -0
- package/dist/runtime/server/util/wasm.js +16 -0
- package/dist/runtime/server/utils.d.ts +4 -0
- package/dist/runtime/server/utils.js +20 -0
- package/dist/runtime/shared.d.ts +15 -0
- package/dist/runtime/shared.js +132 -0
- package/dist/runtime/types.d.ts +187 -0
- package/dist/runtime/types.js +0 -0
- package/dist/types.d.mts +9 -0
- package/package.json +1 -1
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { useNitroOrigin } from "#site-config/server/composables/useNitroOrigin";
|
|
2
|
+
import { createConsola } from "consola";
|
|
3
|
+
import { useCssInline } from "../instances.js";
|
|
4
|
+
export async function applyInlineCss(ctx, island) {
|
|
5
|
+
const { e } = ctx;
|
|
6
|
+
let html = island.html;
|
|
7
|
+
let css = island.head.style?.map((s) => s.innerHTML).filter(Boolean).join("\n") || "";
|
|
8
|
+
const componentInlineStyles = island.head.link?.filter((l) => l.href.startsWith("/_nuxt/components") && l.href.replaceAll("/", "").includes(ctx.options.component)) || [];
|
|
9
|
+
if (!import.meta.prerender && !componentInlineStyles.length) {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
let linksToCss = [];
|
|
13
|
+
if (import.meta.dev) {
|
|
14
|
+
const cssResults = componentInlineStyles.length ? await Promise.all(
|
|
15
|
+
componentInlineStyles.map((l) => {
|
|
16
|
+
const url = l.href.endsWith("lang.css") ? `${l.href}&hmr=false` : l.href;
|
|
17
|
+
return e.$fetch(url, {
|
|
18
|
+
responseType: "text",
|
|
19
|
+
baseURL: useNitroOrigin(e)
|
|
20
|
+
}).then((res) => {
|
|
21
|
+
if (res.includes("__vite__css"))
|
|
22
|
+
return res.match(/__vite__css = "([^"]+)"/)?.[1] || "";
|
|
23
|
+
return res.trim().split("\n").filter((l2) => !l2.startsWith("//")).join("\n").trim();
|
|
24
|
+
}).catch(() => {
|
|
25
|
+
return "";
|
|
26
|
+
});
|
|
27
|
+
})
|
|
28
|
+
) : [];
|
|
29
|
+
linksToCss = cssResults;
|
|
30
|
+
css = [linksToCss.join("\n"), css].join("\n");
|
|
31
|
+
}
|
|
32
|
+
if (!css.trim().length)
|
|
33
|
+
return false;
|
|
34
|
+
const cssInline = await useCssInline();
|
|
35
|
+
if (!cssInline || cssInline?.__mock__) {
|
|
36
|
+
if (componentInlineStyles.length) {
|
|
37
|
+
const logger = createConsola().withTag("Nuxt OG Image");
|
|
38
|
+
logger.warn("To have inline styles applied you need to install either the `@css-inline/css-inline` or `@css-inline/css-inline-wasm` package.");
|
|
39
|
+
}
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
html = cssInline.inline(island.html, {
|
|
43
|
+
loadRemoteStylesheets: false,
|
|
44
|
+
extraCss: css
|
|
45
|
+
});
|
|
46
|
+
const classes = css.match(/\.([\w-]+)/g)?.map((c) => c.replace(".", ""));
|
|
47
|
+
if (classes)
|
|
48
|
+
html = html.replace(new RegExp(`class="(${classes.join("|")})"`, "g"), "");
|
|
49
|
+
island.html = html;
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { OgImageRenderEventContext, SatoriTransformer, VNode } from '../../../types.js';
|
|
2
|
+
export declare function walkSatoriTree(e: OgImageRenderEventContext, node: VNode, plugins: (SatoriTransformer | SatoriTransformer[])[]): (void | Promise<void>)[];
|
|
3
|
+
export declare function defineSatoriTransformer(transformer: SatoriTransformer | SatoriTransformer[]): SatoriTransformer | SatoriTransformer[];
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export function walkSatoriTree(e, node, plugins) {
|
|
2
|
+
const promises = [];
|
|
3
|
+
if (!node.props?.children || !Array.isArray(node.props.children))
|
|
4
|
+
return promises;
|
|
5
|
+
if (node.props.children.length === 0) {
|
|
6
|
+
delete node.props.children;
|
|
7
|
+
return promises;
|
|
8
|
+
}
|
|
9
|
+
for (const child of node.props.children || []) {
|
|
10
|
+
if (child) {
|
|
11
|
+
for (const plugin of plugins.flat()) {
|
|
12
|
+
if (plugin.filter(child))
|
|
13
|
+
promises.push(plugin.transform(child, e));
|
|
14
|
+
}
|
|
15
|
+
promises.push(
|
|
16
|
+
...walkSatoriTree(e, child, plugins)
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return promises;
|
|
21
|
+
}
|
|
22
|
+
export function defineSatoriTransformer(transformer) {
|
|
23
|
+
return transformer;
|
|
24
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { html as convertHtmlToSatori } from "satori-html";
|
|
2
|
+
import { htmlDecodeQuotes } from "../../util/encoding.js";
|
|
3
|
+
import { fetchIsland } from "../../util/kit.js";
|
|
4
|
+
import classes from "./plugins/classes.js";
|
|
5
|
+
import emojis from "./plugins/emojis.js";
|
|
6
|
+
import encoding from "./plugins/encoding.js";
|
|
7
|
+
import flex from "./plugins/flex.js";
|
|
8
|
+
import imageSrc from "./plugins/imageSrc.js";
|
|
9
|
+
import nuxtIcon from "./plugins/nuxt-icon.js";
|
|
10
|
+
import unocss from "./plugins/unocss.js";
|
|
11
|
+
import { applyEmojis } from "./transforms/emojis.js";
|
|
12
|
+
import { applyInlineCss } from "./transforms/inlineCss.js";
|
|
13
|
+
import { walkSatoriTree } from "./utils.js";
|
|
14
|
+
export async function createVNodes(ctx) {
|
|
15
|
+
let html = ctx.options.html;
|
|
16
|
+
if (!html) {
|
|
17
|
+
const island = await fetchIsland(ctx.e, ctx.options.component, typeof ctx.options.props !== "undefined" ? ctx.options.props : ctx.options);
|
|
18
|
+
island.html = htmlDecodeQuotes(island.html);
|
|
19
|
+
await applyInlineCss(ctx, island);
|
|
20
|
+
await applyEmojis(ctx, island);
|
|
21
|
+
html = island.html;
|
|
22
|
+
if (html?.includes("<body>")) {
|
|
23
|
+
html = html.match(/<body>([\s\S]*)<\/body>/)?.[1] || "";
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
const template = `<div style="position: relative; display: flex; margin: 0 auto; width: ${ctx.options.width}px; height: ${ctx.options.height}px; overflow: hidden;">${html}</div>`;
|
|
27
|
+
const satoriTree = convertHtmlToSatori(template);
|
|
28
|
+
walkSatoriTree(ctx, satoriTree, [
|
|
29
|
+
emojis,
|
|
30
|
+
classes,
|
|
31
|
+
flex,
|
|
32
|
+
encoding,
|
|
33
|
+
nuxtIcon
|
|
34
|
+
]);
|
|
35
|
+
await Promise.all(walkSatoriTree(ctx, satoriTree, [
|
|
36
|
+
unocss,
|
|
37
|
+
imageSrc
|
|
38
|
+
]));
|
|
39
|
+
return satoriTree;
|
|
40
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { theme } from "#og-image-virtual/unocss-config.mjs";
|
|
2
|
+
import { createHeadCore } from "@unhead/vue";
|
|
3
|
+
import { renderSSRHead } from "@unhead/vue/server";
|
|
4
|
+
import { createError } from "h3";
|
|
5
|
+
import { normaliseFontInput } from "../../../shared.js";
|
|
6
|
+
import { fetchIsland } from "../../util/kit.js";
|
|
7
|
+
import { useOgImageRuntimeConfig } from "../../utils.js";
|
|
8
|
+
import { applyEmojis } from "../satori/transforms/emojis.js";
|
|
9
|
+
export async function html(ctx) {
|
|
10
|
+
const { options } = ctx;
|
|
11
|
+
const { fonts } = useOgImageRuntimeConfig();
|
|
12
|
+
if (!options.component) {
|
|
13
|
+
throw createError({
|
|
14
|
+
statusCode: 500,
|
|
15
|
+
statusMessage: `[Nuxt OG Image] Rendering an invalid component. Received options: ${JSON.stringify(options)}.`
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
const island = await fetchIsland(ctx.e, ctx.options.component, typeof ctx.options.props !== "undefined" ? ctx.options.props : ctx.options);
|
|
19
|
+
const head = createHeadCore();
|
|
20
|
+
head.push(island.head);
|
|
21
|
+
let defaultFontFamily = "sans-serif";
|
|
22
|
+
const normalisedFonts = normaliseFontInput([...options.fonts || [], ...fonts]);
|
|
23
|
+
const firstFont = normalisedFonts[0];
|
|
24
|
+
if (firstFont)
|
|
25
|
+
defaultFontFamily = firstFont.name.replaceAll("+", " ");
|
|
26
|
+
await applyEmojis(ctx, island);
|
|
27
|
+
let html2 = island.html;
|
|
28
|
+
head.push({
|
|
29
|
+
style: [
|
|
30
|
+
{
|
|
31
|
+
// default font is the first font family
|
|
32
|
+
innerHTML: `body { font-family: '${defaultFontFamily}', sans-serif; }`
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
innerHTML: `body {
|
|
36
|
+
transform: scale(${options.props?.scale || 1});
|
|
37
|
+
transform-origin: top left;
|
|
38
|
+
max-height: 100vh;
|
|
39
|
+
position: relative;
|
|
40
|
+
width: ${options.width}px;
|
|
41
|
+
height: ${options.height}px;
|
|
42
|
+
overflow: hidden;
|
|
43
|
+
background-color: ${options.props?.colorMode === "dark" ? "#1b1b1b" : "#fff"};
|
|
44
|
+
}
|
|
45
|
+
div {
|
|
46
|
+
display: flex;
|
|
47
|
+
}
|
|
48
|
+
div:has(div, p, ul, ol, li, blockquote, pre, hr, table, dl) {
|
|
49
|
+
display: flex;
|
|
50
|
+
flex-direction: column;
|
|
51
|
+
}
|
|
52
|
+
div:not(:has(div, p, ul, ol, li, blockquote, pre, hr, table, dl)) {
|
|
53
|
+
display: flex;
|
|
54
|
+
flex-wrap: wrap;
|
|
55
|
+
gap: 12px;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
svg[data-emoji] {
|
|
59
|
+
display: inline-block;
|
|
60
|
+
}
|
|
61
|
+
`
|
|
62
|
+
},
|
|
63
|
+
...fonts.map((font) => {
|
|
64
|
+
return `
|
|
65
|
+
@font-face {
|
|
66
|
+
font-family: '${font.name.replaceAll("+", " ")}';
|
|
67
|
+
font-style: normal;
|
|
68
|
+
font-weight: ${font.weight};
|
|
69
|
+
src: url('/__og-image__/font/${font.key}') format('truetype');
|
|
70
|
+
}
|
|
71
|
+
`;
|
|
72
|
+
})
|
|
73
|
+
],
|
|
74
|
+
meta: [
|
|
75
|
+
{
|
|
76
|
+
charset: "utf-8"
|
|
77
|
+
}
|
|
78
|
+
],
|
|
79
|
+
script: [
|
|
80
|
+
{
|
|
81
|
+
src: "https://cdn.jsdelivr.net/npm/@unocss/runtime/preset-wind.global.js"
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
innerHTML: `
|
|
85
|
+
window.__unocss = {
|
|
86
|
+
theme: ${JSON.stringify(theme)},
|
|
87
|
+
presets: [
|
|
88
|
+
() => window.__unocss_runtime.presets.presetWind(),
|
|
89
|
+
],
|
|
90
|
+
}
|
|
91
|
+
`
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
src: "https://cdn.jsdelivr.net/npm/@unocss/runtime/core.global.js"
|
|
95
|
+
}
|
|
96
|
+
],
|
|
97
|
+
link: [
|
|
98
|
+
{
|
|
99
|
+
// reset css to match svg output
|
|
100
|
+
href: "https://cdn.jsdelivr.net/npm/gardevoir",
|
|
101
|
+
rel: "stylesheet"
|
|
102
|
+
}
|
|
103
|
+
]
|
|
104
|
+
});
|
|
105
|
+
html2 = html2.replaceAll(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, "");
|
|
106
|
+
const headChunk = await renderSSRHead(head);
|
|
107
|
+
return `<!DOCTYPE html>
|
|
108
|
+
<html ${headChunk.htmlAttrs}>
|
|
109
|
+
<head>${headChunk.headTags}</head>
|
|
110
|
+
<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;">${html2}</div>${headChunk.bodyTags}</body>
|
|
111
|
+
</html>`;
|
|
112
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { defineNitroPlugin } from "nitropack/runtime";
|
|
2
|
+
import { nuxtContentPlugin } from "../../util/plugins.js";
|
|
3
|
+
export default defineNitroPlugin((nitroApp) => {
|
|
4
|
+
if (import.meta.dev || import.meta.prerender) {
|
|
5
|
+
nuxtContentPlugin(nitroApp);
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
8
|
+
throw new Error("Not supported in zeroRuntime mode.");
|
|
9
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { prerenderOptionsCache } from "#og-image-cache";
|
|
2
|
+
import { createSitePathResolver } from "#site-config/server/composables/utils";
|
|
3
|
+
import { defineNitroPlugin } from "nitropack/runtime";
|
|
4
|
+
import { parseURL } from "ufo";
|
|
5
|
+
import { isInternalRoute } from "../../shared.js";
|
|
6
|
+
import { extractAndNormaliseOgImageOptions, resolvePathCacheKey } from "../og-image/context.js";
|
|
7
|
+
import { createNitroRouteRuleMatcher } from "../util/kit.js";
|
|
8
|
+
export default defineNitroPlugin(async (nitro) => {
|
|
9
|
+
if (!import.meta.prerender)
|
|
10
|
+
return;
|
|
11
|
+
const routeRuleMatcher = createNitroRouteRuleMatcher();
|
|
12
|
+
nitro.hooks.hook("render:html", async (html, ctx) => {
|
|
13
|
+
const { head, bodyAppend } = html;
|
|
14
|
+
const path = parseURL(ctx.event.path).pathname;
|
|
15
|
+
if (isInternalRoute(path))
|
|
16
|
+
return;
|
|
17
|
+
const routeRules = routeRuleMatcher(path);
|
|
18
|
+
if (routeRules.ogImage === false)
|
|
19
|
+
return;
|
|
20
|
+
const options = extractAndNormaliseOgImageOptions([
|
|
21
|
+
head.join("\n"),
|
|
22
|
+
bodyAppend.join("\n")
|
|
23
|
+
].join("\n"));
|
|
24
|
+
if (!options)
|
|
25
|
+
return;
|
|
26
|
+
const resolvePathWithBase = createSitePathResolver(ctx.event, {
|
|
27
|
+
absolute: false,
|
|
28
|
+
withBase: true
|
|
29
|
+
});
|
|
30
|
+
const key = resolvePathCacheKey(ctx.event, resolvePathWithBase(path));
|
|
31
|
+
await prerenderOptionsCache.setItem(key, options);
|
|
32
|
+
const index = html.bodyAppend.findIndex((script) => script.includes('id="nuxt-og-image-options"'));
|
|
33
|
+
if (index !== -1) {
|
|
34
|
+
html.bodyAppend[index] = String(html.bodyAppend[index]).replace(/<script id="nuxt-og-image-options" type="application\/json">[\s\S]*?<\/script>/, "");
|
|
35
|
+
html.bodyAppend[index] = html.bodyAppend[index].replace(/<script id="nuxt-og-image-overrides" type="application\/json">[\s\S]*?<\/script>/, "");
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { defineEventHandler } from "h3";
|
|
2
|
+
import { fontEventHandler } from "../../util/eventHandlers.js";
|
|
3
|
+
export default defineEventHandler(async (e) => {
|
|
4
|
+
if (import.meta.dev || import.meta.prerender) {
|
|
5
|
+
return await fontEventHandler(e);
|
|
6
|
+
}
|
|
7
|
+
throw new Error("Not supported in zeroRuntime mode.");
|
|
8
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { defineEventHandler } from "h3";
|
|
2
|
+
import { imageEventHandler } from "../../util/eventHandlers.js";
|
|
3
|
+
export default defineEventHandler(async (e) => {
|
|
4
|
+
if (import.meta.dev || import.meta.prerender) {
|
|
5
|
+
return await imageEventHandler(e);
|
|
6
|
+
}
|
|
7
|
+
throw new Error("Not supported in zeroRuntime mode.");
|
|
8
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { componentNames } from "#og-image-virtual/component-names.mjs";
|
|
2
|
+
import compatibility from "#og-image/compatibility";
|
|
3
|
+
import { useSiteConfig } from "#site-config/server/composables/useSiteConfig";
|
|
4
|
+
import { defineEventHandler, setHeader } from "h3";
|
|
5
|
+
import { useOgImageRuntimeConfig } from "../utils.js";
|
|
6
|
+
export default defineEventHandler(async (e) => {
|
|
7
|
+
setHeader(e, "Content-Type", "application/json");
|
|
8
|
+
const runtimeConfig = useOgImageRuntimeConfig();
|
|
9
|
+
return {
|
|
10
|
+
siteConfigUrl: useSiteConfig(e).url,
|
|
11
|
+
componentNames,
|
|
12
|
+
runtimeConfig,
|
|
13
|
+
compatibility
|
|
14
|
+
};
|
|
15
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { H3Error } from 'h3';
|
|
2
|
+
import type { OgImageRenderEventContext } from '../../types.js';
|
|
3
|
+
export declare function useOgImageBufferCache(ctx: OgImageRenderEventContext, options: {
|
|
4
|
+
baseCacheKey: string | false;
|
|
5
|
+
cacheMaxAgeSeconds?: number;
|
|
6
|
+
}): Promise<void | H3Error | {
|
|
7
|
+
cachedItem: false | BufferSource;
|
|
8
|
+
enabled: boolean;
|
|
9
|
+
update: (image: BufferSource | Buffer | Uint8Array) => Promise<void>;
|
|
10
|
+
}>;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { createError, getQuery, handleCacheHeaders, setHeader, setHeaders } from "h3";
|
|
2
|
+
import { useStorage } from "nitropack/runtime";
|
|
3
|
+
import { hash } from "ohash";
|
|
4
|
+
import { withTrailingSlash } from "ufo";
|
|
5
|
+
import { prefixStorage } from "unstorage";
|
|
6
|
+
export async function useOgImageBufferCache(ctx, options) {
|
|
7
|
+
const maxAge = Number(options.cacheMaxAgeSeconds);
|
|
8
|
+
let enabled = !import.meta.dev && import.meta.env?.MODE !== "test" && maxAge > 0;
|
|
9
|
+
const cache = prefixStorage(useStorage(), withTrailingSlash(options.baseCacheKey || "/"));
|
|
10
|
+
const key = ctx.key;
|
|
11
|
+
let cachedItem = false;
|
|
12
|
+
if (enabled) {
|
|
13
|
+
const hasItem = await cache.hasItem(key).catch((e) => {
|
|
14
|
+
enabled = false;
|
|
15
|
+
return createError({
|
|
16
|
+
cause: e,
|
|
17
|
+
statusCode: 500,
|
|
18
|
+
statusMessage: `[Nuxt OG Image] Failed to connect to cache ${options.baseCacheKey}. Response from cache: ${e.message}`
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
if (hasItem instanceof Error)
|
|
22
|
+
return hasItem;
|
|
23
|
+
if (hasItem) {
|
|
24
|
+
const { value, expiresAt, headers } = await cache.getItem(key).catch(() => ({
|
|
25
|
+
value: null,
|
|
26
|
+
expiresAt: Date.now()
|
|
27
|
+
}));
|
|
28
|
+
if (typeof getQuery(ctx.e).purge !== "undefined") {
|
|
29
|
+
await cache.removeItem(key).catch(() => {
|
|
30
|
+
});
|
|
31
|
+
} else if (expiresAt > Date.now()) {
|
|
32
|
+
cachedItem = Buffer.from(value, "base64");
|
|
33
|
+
if (handleCacheHeaders(ctx.e, {
|
|
34
|
+
modifiedTime: new Date(headers["last-modified"]),
|
|
35
|
+
etag: headers.etag,
|
|
36
|
+
maxAge
|
|
37
|
+
})) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
setHeaders(ctx.e, headers);
|
|
41
|
+
} else {
|
|
42
|
+
await cache.removeItem(key).catch(() => {
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (!enabled) {
|
|
48
|
+
setHeader(ctx.e, "Cache-Control", "no-cache, no-store, must-revalidate");
|
|
49
|
+
setHeader(ctx.e, "Pragma", "no-cache");
|
|
50
|
+
setHeader(ctx.e, "Expires", "0");
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
enabled,
|
|
54
|
+
cachedItem,
|
|
55
|
+
async update(item) {
|
|
56
|
+
if (!enabled)
|
|
57
|
+
return;
|
|
58
|
+
const value = Buffer.from(item).toString("base64");
|
|
59
|
+
const headers = {
|
|
60
|
+
// avoid multi-tenancy cache issues
|
|
61
|
+
"Vary": "accept-encoding, host",
|
|
62
|
+
"etag": `W/"${hash(value)}"`,
|
|
63
|
+
"last-modified": (/* @__PURE__ */ new Date()).toUTCString(),
|
|
64
|
+
"cache-control": `public, s-maxage=${maxAge}, stale-while-revalidate`
|
|
65
|
+
};
|
|
66
|
+
setHeaders(ctx.e, headers);
|
|
67
|
+
await cache.setItem(key, {
|
|
68
|
+
value,
|
|
69
|
+
headers,
|
|
70
|
+
expiresAt: Date.now() + maxAge * 1e3
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export function htmlDecodeQuotes(html) {
|
|
2
|
+
return html.replace(/"/g, '"').replace(/'/g, "'").replace(/'/g, "'");
|
|
3
|
+
}
|
|
4
|
+
export function decodeHtml(html) {
|
|
5
|
+
return html.replace(/</g, "<").replace(/>/g, ">").replace(/¢/g, "\xA2").replace(/£/g, "\xA3").replace(/¥/g, "\xA5").replace(/€/g, "\u20AC").replace(/©/g, "\xA9").replace(/®/g, "\xAE").replace(/"/g, '"').replace(/'/g, "'").replace(/'/g, "'").replace(///g, "/").replace(/&#(\d+);/g, (full, int) => {
|
|
6
|
+
return String.fromCharCode(Number.parseInt(int));
|
|
7
|
+
}).replace(/&/g, "&");
|
|
8
|
+
}
|
|
9
|
+
export function decodeObjectHtmlEntities(obj) {
|
|
10
|
+
Object.entries(obj).forEach(([key, value]) => {
|
|
11
|
+
if (typeof value === "string")
|
|
12
|
+
obj[key] = decodeHtml(value);
|
|
13
|
+
});
|
|
14
|
+
return obj;
|
|
15
|
+
}
|