nuxt-og-image 5.1.10 → 5.1.12
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/CD9VIl4i.js +4062 -0
- package/dist/client/_nuxt/CI_lqgv7.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/D0r3Knsf.js +1 -0
- package/dist/client/_nuxt/Dz8kdfgF.js +1 -0
- package/dist/client/_nuxt/builds/latest.json +1 -0
- package/dist/client/_nuxt/builds/meta/71b0f7ea-9aae-4c28-bbd9-8eea71b82dfb.json +1 -0
- package/dist/client/_nuxt/entry.DNM8P-MU.css +1 -0
- package/dist/client/_nuxt/error-404.C2mGI6Vt.css +1 -0
- package/dist/client/_nuxt/error-500.ClHbVBiL.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 +1027 -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 +1007 -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 +13 -0
- package/dist/runtime/app/components/Templates/Community/BrandedLogo.vue +22 -0
- package/dist/runtime/app/components/Templates/Community/BrandedLogo.vue.d.ts +13 -0
- package/dist/runtime/app/components/Templates/Community/Frame.d.vue.ts +21 -0
- package/dist/runtime/app/components/Templates/Community/Frame.vue +58 -0
- package/dist/runtime/app/components/Templates/Community/Frame.vue.d.ts +21 -0
- package/dist/runtime/app/components/Templates/Community/Nuxt.d.vue.ts +12 -0
- package/dist/runtime/app/components/Templates/Community/Nuxt.vue +179 -0
- package/dist/runtime/app/components/Templates/Community/Nuxt.vue.d.ts +12 -0
- package/dist/runtime/app/components/Templates/Community/NuxtSeo.d.vue.ts +15 -0
- package/dist/runtime/app/components/Templates/Community/NuxtSeo.vue +103 -0
- package/dist/runtime/app/components/Templates/Community/NuxtSeo.vue.d.ts +15 -0
- package/dist/runtime/app/components/Templates/Community/Pergel.d.vue.ts +12 -0
- package/dist/runtime/app/components/Templates/Community/Pergel.vue +98 -0
- package/dist/runtime/app/components/Templates/Community/Pergel.vue.d.ts +12 -0
- package/dist/runtime/app/components/Templates/Community/SimpleBlog.d.vue.ts +9 -0
- package/dist/runtime/app/components/Templates/Community/SimpleBlog.vue +27 -0
- package/dist/runtime/app/components/Templates/Community/SimpleBlog.vue.d.ts +9 -0
- package/dist/runtime/app/components/Templates/Community/UnJs.d.vue.ts +21 -0
- package/dist/runtime/app/components/Templates/Community/UnJs.vue +99 -0
- package/dist/runtime/app/components/Templates/Community/UnJs.vue.d.ts +21 -0
- package/dist/runtime/app/components/Templates/Community/Wave.d.vue.ts +11 -0
- package/dist/runtime/app/components/Templates/Community/Wave.vue +28 -0
- package/dist/runtime/app/components/Templates/Community/Wave.vue.d.ts +11 -0
- package/dist/runtime/app/components/Templates/Community/WithEmoji.d.vue.ts +13 -0
- package/dist/runtime/app/components/Templates/Community/WithEmoji.vue +21 -0
- package/dist/runtime/app/components/Templates/Community/WithEmoji.vue.d.ts +13 -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 +32 -32
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
import { htmlPayloadCache, prerenderOptionsCache } from "#og-image-cache";
|
|
2
|
+
import { theme } from "#og-image-virtual/unocss-config.mjs";
|
|
3
|
+
import { useSiteConfig } from "#site-config/server/composables/useSiteConfig";
|
|
4
|
+
import { createSitePathResolver } from "#site-config/server/composables/utils";
|
|
5
|
+
import { createGenerator } from "@unocss/core";
|
|
6
|
+
import presetWind from "@unocss/preset-wind3";
|
|
7
|
+
import { defu } from "defu";
|
|
8
|
+
import { parse } from "devalue";
|
|
9
|
+
import { createError, getQuery } from "h3";
|
|
10
|
+
import { useNitroApp } from "nitropack/runtime";
|
|
11
|
+
import { hash } from "ohash";
|
|
12
|
+
import { parseURL, withoutLeadingSlash, withoutTrailingSlash, withQuery } from "ufo";
|
|
13
|
+
import { normalizeKey } from "unstorage";
|
|
14
|
+
import { separateProps } from "../../shared.js";
|
|
15
|
+
import { decodeObjectHtmlEntities } from "../util/encoding.js";
|
|
16
|
+
import { createNitroRouteRuleMatcher } from "../util/kit.js";
|
|
17
|
+
import { logger } from "../util/logger.js";
|
|
18
|
+
import { normaliseOptions } from "../util/options.js";
|
|
19
|
+
import { useOgImageRuntimeConfig } from "../utils.js";
|
|
20
|
+
import { useChromiumRenderer, useSatoriRenderer } from "./instances.js";
|
|
21
|
+
export function resolvePathCacheKey(e, path) {
|
|
22
|
+
const siteConfig = useSiteConfig(e, {
|
|
23
|
+
resolveRefs: true
|
|
24
|
+
});
|
|
25
|
+
const basePath = withoutTrailingSlash(withoutLeadingSlash(normalizeKey(path)));
|
|
26
|
+
return [
|
|
27
|
+
!basePath || basePath === "/" ? "index" : basePath,
|
|
28
|
+
hash([
|
|
29
|
+
basePath,
|
|
30
|
+
import.meta.prerender ? "" : siteConfig.url,
|
|
31
|
+
hash(getQuery(e))
|
|
32
|
+
])
|
|
33
|
+
].join(":");
|
|
34
|
+
}
|
|
35
|
+
export async function resolveContext(e) {
|
|
36
|
+
const runtimeConfig = useOgImageRuntimeConfig();
|
|
37
|
+
const resolvePathWithBase = createSitePathResolver(e, {
|
|
38
|
+
absolute: false,
|
|
39
|
+
withBase: true
|
|
40
|
+
});
|
|
41
|
+
const path = resolvePathWithBase(parseURL(e.path).pathname);
|
|
42
|
+
const extension = path.split(".").pop();
|
|
43
|
+
if (!extension) {
|
|
44
|
+
return createError({
|
|
45
|
+
statusCode: 400,
|
|
46
|
+
statusMessage: `[Nuxt OG Image] Missing OG Image type.`
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
if (!["png", "jpeg", "jpg", "svg", "html", "json"].includes(extension)) {
|
|
50
|
+
return createError({
|
|
51
|
+
statusCode: 400,
|
|
52
|
+
statusMessage: `[Nuxt OG Image] Unknown OG Image type ${extension}.`
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
const query = getQuery(e);
|
|
56
|
+
let queryParams = {};
|
|
57
|
+
for (const k in query) {
|
|
58
|
+
const v = String(query[k]);
|
|
59
|
+
if (!v)
|
|
60
|
+
continue;
|
|
61
|
+
if (v.startsWith("{")) {
|
|
62
|
+
try {
|
|
63
|
+
queryParams[k] = JSON.parse(v);
|
|
64
|
+
} catch (error) {
|
|
65
|
+
if (import.meta.dev) {
|
|
66
|
+
logger.error(`[Nuxt OG Image] Invalid JSON in ${k} parameter: ${error.message}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
} else {
|
|
70
|
+
queryParams[k] = v;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
queryParams = separateProps(queryParams);
|
|
74
|
+
let basePath = withoutTrailingSlash(
|
|
75
|
+
path.replace(`/__og-image__/image`, "").replace(`/__og-image__/static`, "").replace(`/og.${extension}`, "")
|
|
76
|
+
);
|
|
77
|
+
if (queryParams._query && typeof queryParams._query === "object")
|
|
78
|
+
basePath = withQuery(basePath, queryParams._query);
|
|
79
|
+
const isDebugJsonPayload = extension === "json" && runtimeConfig.debug;
|
|
80
|
+
const key = resolvePathCacheKey(e, basePath);
|
|
81
|
+
let options = queryParams.options;
|
|
82
|
+
if (!options) {
|
|
83
|
+
if (import.meta.prerender) {
|
|
84
|
+
options = await prerenderOptionsCache.getItem(key);
|
|
85
|
+
}
|
|
86
|
+
if (!options) {
|
|
87
|
+
const payload = await fetchPathHtmlAndExtractOptions(e, basePath, key);
|
|
88
|
+
if (payload instanceof Error)
|
|
89
|
+
return payload;
|
|
90
|
+
options = payload;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
delete queryParams.options;
|
|
94
|
+
const routeRuleMatcher = createNitroRouteRuleMatcher();
|
|
95
|
+
const routeRules = routeRuleMatcher(basePath);
|
|
96
|
+
if (typeof routeRules.ogImage === "undefined" && !options) {
|
|
97
|
+
return createError({
|
|
98
|
+
statusCode: 400,
|
|
99
|
+
statusMessage: "The route is missing the Nuxt OG Image payload or route rules."
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
const ogImageRouteRules = separateProps(routeRules.ogImage);
|
|
103
|
+
options = defu(queryParams, options, ogImageRouteRules, runtimeConfig.defaults);
|
|
104
|
+
if (!options) {
|
|
105
|
+
return createError({
|
|
106
|
+
statusCode: 404,
|
|
107
|
+
statusMessage: "[Nuxt OG Image] OG Image not found."
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
let renderer;
|
|
111
|
+
switch (options.renderer) {
|
|
112
|
+
case "satori":
|
|
113
|
+
renderer = await useSatoriRenderer();
|
|
114
|
+
break;
|
|
115
|
+
case "chromium":
|
|
116
|
+
renderer = await useChromiumRenderer();
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
if (!renderer || renderer.__mock__) {
|
|
120
|
+
throw createError({
|
|
121
|
+
statusCode: 400,
|
|
122
|
+
statusMessage: `[Nuxt OG Image] Renderer ${options.renderer} is not enabled.`
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
const unocss = await createGenerator({ theme }, {
|
|
126
|
+
presets: [
|
|
127
|
+
presetWind()
|
|
128
|
+
]
|
|
129
|
+
});
|
|
130
|
+
const ctx = {
|
|
131
|
+
unocss,
|
|
132
|
+
e,
|
|
133
|
+
key,
|
|
134
|
+
renderer,
|
|
135
|
+
isDebugJsonPayload,
|
|
136
|
+
runtimeConfig,
|
|
137
|
+
publicStoragePath: runtimeConfig.publicStoragePath,
|
|
138
|
+
extension,
|
|
139
|
+
basePath,
|
|
140
|
+
options: normaliseOptions(options),
|
|
141
|
+
_nitro: useNitroApp()
|
|
142
|
+
};
|
|
143
|
+
await ctx._nitro.hooks.callHook("nuxt-og-image:context", ctx);
|
|
144
|
+
return ctx;
|
|
145
|
+
}
|
|
146
|
+
const PAYLOAD_REGEX = /<script.+id="nuxt-og-image-options"[^>]*>(.+?)<\/script>/;
|
|
147
|
+
function getPayloadFromHtml(html) {
|
|
148
|
+
const match = String(html).match(PAYLOAD_REGEX);
|
|
149
|
+
return match ? String(match[1]) : null;
|
|
150
|
+
}
|
|
151
|
+
export function extractAndNormaliseOgImageOptions(html) {
|
|
152
|
+
const _payload = getPayloadFromHtml(html);
|
|
153
|
+
let options = false;
|
|
154
|
+
try {
|
|
155
|
+
const payload2 = parse(_payload || "{}");
|
|
156
|
+
Object.entries(payload2).forEach(([key, value]) => {
|
|
157
|
+
if (!value && value !== 0)
|
|
158
|
+
delete payload2[key];
|
|
159
|
+
});
|
|
160
|
+
options = payload2;
|
|
161
|
+
} catch (e) {
|
|
162
|
+
if (import.meta.dev)
|
|
163
|
+
console.warn("Failed to parse #nuxt-og-image-options", e, options);
|
|
164
|
+
}
|
|
165
|
+
if (options && typeof options?.props?.description === "undefined") {
|
|
166
|
+
const description = html.match(/<meta[^>]+name="description"[^>]*>/)?.[0];
|
|
167
|
+
if (description) {
|
|
168
|
+
const [, content] = description.match(/content="([^"]+)"/) || [];
|
|
169
|
+
if (content && !options.props.description)
|
|
170
|
+
options.props.description = content;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
const payload = decodeObjectHtmlEntities(options || {});
|
|
174
|
+
if (import.meta.dev) {
|
|
175
|
+
const socialPreview = {};
|
|
176
|
+
const socialMetaTags = html.match(/<meta[^>]+(property|name)="(twitter|og):([^"]+)"[^>]*>/g);
|
|
177
|
+
if (socialMetaTags) {
|
|
178
|
+
socialMetaTags.forEach((tag) => {
|
|
179
|
+
const [, , type, key] = tag.match(/(property|name)="(twitter|og):([^"]+)"/);
|
|
180
|
+
const value = tag.match(/content="([^"]+)"/)?.[1];
|
|
181
|
+
if (!value)
|
|
182
|
+
return;
|
|
183
|
+
if (!socialPreview[type])
|
|
184
|
+
socialPreview[type] = {};
|
|
185
|
+
socialPreview[type][key] = value;
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
payload.socialPreview = socialPreview;
|
|
189
|
+
}
|
|
190
|
+
return payload;
|
|
191
|
+
}
|
|
192
|
+
async function doFetchWithErrorHandling(fetch, path) {
|
|
193
|
+
const res = await fetch(path, {
|
|
194
|
+
redirect: "follow",
|
|
195
|
+
headers: {
|
|
196
|
+
accept: "text/html"
|
|
197
|
+
}
|
|
198
|
+
}).catch((err) => {
|
|
199
|
+
return err;
|
|
200
|
+
});
|
|
201
|
+
let errorDescription;
|
|
202
|
+
if (res.status >= 300 && res.status < 400) {
|
|
203
|
+
if (res.headers.has("location")) {
|
|
204
|
+
return await doFetchWithErrorHandling(fetch, res.headers.get("location") || "");
|
|
205
|
+
}
|
|
206
|
+
errorDescription = `${res.status} redirected to ${res.headers.get("location") || "unknown"}`;
|
|
207
|
+
} else if (res.status >= 500) {
|
|
208
|
+
errorDescription = `${res.status} error: ${res.statusText}`;
|
|
209
|
+
}
|
|
210
|
+
if (errorDescription) {
|
|
211
|
+
return [null, createError({
|
|
212
|
+
statusCode: 500,
|
|
213
|
+
statusMessage: `[Nuxt OG Image] Failed to parse \`${path}\` for og-image extraction. ${errorDescription}`
|
|
214
|
+
})];
|
|
215
|
+
}
|
|
216
|
+
if (res._data) {
|
|
217
|
+
return [res._data, null];
|
|
218
|
+
} else if (res.text) {
|
|
219
|
+
return [await res.text(), null];
|
|
220
|
+
}
|
|
221
|
+
return ["", null];
|
|
222
|
+
}
|
|
223
|
+
async function fetchPathHtmlAndExtractOptions(e, path, key) {
|
|
224
|
+
const cachedHtmlPayload = await htmlPayloadCache.getItem(key);
|
|
225
|
+
if (!import.meta.dev && cachedHtmlPayload && cachedHtmlPayload.expiresAt < Date.now())
|
|
226
|
+
return cachedHtmlPayload.value;
|
|
227
|
+
let _payload = null;
|
|
228
|
+
let [html, err] = await doFetchWithErrorHandling(e.fetch, path);
|
|
229
|
+
if (err) {
|
|
230
|
+
logger.warn(err);
|
|
231
|
+
} else {
|
|
232
|
+
_payload = getPayloadFromHtml(html);
|
|
233
|
+
}
|
|
234
|
+
if (!_payload) {
|
|
235
|
+
const [fallbackHtml, err2] = await doFetchWithErrorHandling(globalThis.$fetch.raw, path);
|
|
236
|
+
if (err2) {
|
|
237
|
+
return err2;
|
|
238
|
+
}
|
|
239
|
+
_payload = getPayloadFromHtml(fallbackHtml);
|
|
240
|
+
if (_payload) {
|
|
241
|
+
html = fallbackHtml;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
if (!html) {
|
|
245
|
+
return createError({
|
|
246
|
+
statusCode: 500,
|
|
247
|
+
statusMessage: `[Nuxt OG Image] Failed to read the path ${path} for og-image extraction, returning no HTML.`
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
if (!_payload) {
|
|
251
|
+
const payload2 = extractAndNormaliseOgImageOptions(html);
|
|
252
|
+
if (payload2 && typeof payload2 === "object" && payload2.socialPreview?.og?.image) {
|
|
253
|
+
const image = payload2.socialPreview.og.image;
|
|
254
|
+
const p = {
|
|
255
|
+
custom: true,
|
|
256
|
+
url: typeof image === "string" ? image : image
|
|
257
|
+
};
|
|
258
|
+
if (typeof image === "object" && image["image:width"]) {
|
|
259
|
+
p.width = image["image:width"];
|
|
260
|
+
}
|
|
261
|
+
if (typeof image === "object" && image["image:height"]) {
|
|
262
|
+
p.height = image["image:height"];
|
|
263
|
+
}
|
|
264
|
+
return p;
|
|
265
|
+
}
|
|
266
|
+
return createError({
|
|
267
|
+
statusCode: 500,
|
|
268
|
+
statusMessage: `[Nuxt OG Image] HTML response from ${path} is missing the #nuxt-og-image-options script tag. Make sure you have defined an og image for this page.`
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
const payload = extractAndNormaliseOgImageOptions(html);
|
|
272
|
+
if (!import.meta.dev && payload) {
|
|
273
|
+
await htmlPayloadCache.setItem(key, {
|
|
274
|
+
// 60 minutes for prerender, 10 seconds for runtime
|
|
275
|
+
expiresAt: Date.now() + 1e3 * (import.meta.prerender ? 60 * 60 : 10),
|
|
276
|
+
value: payload
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
return typeof payload === "object" ? payload : createError({
|
|
280
|
+
statusCode: 500,
|
|
281
|
+
statusMessage: "[Nuxt OG Image] Invalid payload type."
|
|
282
|
+
});
|
|
283
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const satoriRendererInstance = { instance: void 0 };
|
|
2
|
+
const chromiumRendererInstance = { instance: void 0 };
|
|
3
|
+
export async function useSatoriRenderer() {
|
|
4
|
+
satoriRendererInstance.instance = satoriRendererInstance.instance || await import("#og-image/renderers/satori").then((m) => m.default);
|
|
5
|
+
return satoriRendererInstance.instance;
|
|
6
|
+
}
|
|
7
|
+
export async function useChromiumRenderer() {
|
|
8
|
+
chromiumRendererInstance.instance = chromiumRendererInstance.instance || await import("#og-image/renderers/chromium").then((m) => m.default);
|
|
9
|
+
return chromiumRendererInstance.instance;
|
|
10
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { OgImageRenderEventContext, ResolvedFontConfig } from '../../../types.js';
|
|
2
|
+
export declare const assets: import("unstorage").Storage<any>;
|
|
3
|
+
export declare function loadFont({ e, publicStoragePath }: OgImageRenderEventContext, font: ResolvedFontConfig): Promise<ResolvedFontConfig>;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { useNitroOrigin } from "#site-config/server/composables";
|
|
2
|
+
import { useStorage } from "nitropack/runtime";
|
|
3
|
+
import { prefixStorage } from "unstorage";
|
|
4
|
+
export const assets = prefixStorage(useStorage(), "/assets");
|
|
5
|
+
export async function loadFont({ e, publicStoragePath }, font) {
|
|
6
|
+
const { name, weight } = font;
|
|
7
|
+
if (font.data)
|
|
8
|
+
return font;
|
|
9
|
+
if (font.key && await assets.hasItem(font.key)) {
|
|
10
|
+
let fontData = await assets.getItem(font.key);
|
|
11
|
+
if (fontData instanceof Uint8Array) {
|
|
12
|
+
const decoder = new TextDecoder();
|
|
13
|
+
fontData = decoder.decode(fontData);
|
|
14
|
+
}
|
|
15
|
+
font.data = Buffer.from(String(fontData), "base64");
|
|
16
|
+
return font;
|
|
17
|
+
}
|
|
18
|
+
let data;
|
|
19
|
+
if (font.path) {
|
|
20
|
+
if (import.meta.dev || import.meta.prerender) {
|
|
21
|
+
const key = `${publicStoragePath}${font.path.replace("./", ":").replace("/", ":")}`;
|
|
22
|
+
if (await useStorage().hasItem(key))
|
|
23
|
+
data = await useStorage().getItemRaw(key) || void 0;
|
|
24
|
+
} else {
|
|
25
|
+
data = await e.$fetch(font.path, {
|
|
26
|
+
baseURL: useNitroOrigin(e),
|
|
27
|
+
responseType: "arrayBuffer"
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
} else {
|
|
31
|
+
data = await e.$fetch(`/__og-image__/font/${name}/${weight}.ttf`, {
|
|
32
|
+
responseType: "arrayBuffer",
|
|
33
|
+
query: {
|
|
34
|
+
font
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
font.data = data;
|
|
39
|
+
return font;
|
|
40
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type _satori from 'satori';
|
|
2
|
+
import type _sharp from 'sharp';
|
|
3
|
+
export declare function useResvg(): Promise<new (svg: Uint8Array | string, options?: import("@resvg/resvg-wasm").ResvgRenderOptions) => {
|
|
4
|
+
free(): void;
|
|
5
|
+
render(): {
|
|
6
|
+
free(): void;
|
|
7
|
+
asPng(): Uint8Array;
|
|
8
|
+
readonly height: number;
|
|
9
|
+
readonly pixels: Uint8Array;
|
|
10
|
+
readonly width: number;
|
|
11
|
+
};
|
|
12
|
+
toString(): string;
|
|
13
|
+
innerBBox(): {
|
|
14
|
+
free(): void;
|
|
15
|
+
height: number;
|
|
16
|
+
width: number;
|
|
17
|
+
x: number;
|
|
18
|
+
y: number;
|
|
19
|
+
} | undefined;
|
|
20
|
+
getBBox(): {
|
|
21
|
+
free(): void;
|
|
22
|
+
height: number;
|
|
23
|
+
width: number;
|
|
24
|
+
x: number;
|
|
25
|
+
y: number;
|
|
26
|
+
} | undefined;
|
|
27
|
+
cropByBBox(bbox: {
|
|
28
|
+
free(): void;
|
|
29
|
+
height: number;
|
|
30
|
+
width: number;
|
|
31
|
+
x: number;
|
|
32
|
+
y: number;
|
|
33
|
+
}): void;
|
|
34
|
+
imagesToResolve(): any[];
|
|
35
|
+
resolveImage(href: string, buffer: Uint8Array): void;
|
|
36
|
+
readonly height: number;
|
|
37
|
+
readonly width: number;
|
|
38
|
+
}>;
|
|
39
|
+
export declare function useSatori(): Promise<typeof _satori>;
|
|
40
|
+
export declare function useSharp(): Promise<typeof _sharp>;
|
|
41
|
+
export declare function useCssInline(): Promise<any>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const cssInlineInstance = { instance: void 0 };
|
|
2
|
+
const sharpInstance = { instance: void 0 };
|
|
3
|
+
const resvgInstance = { instance: void 0 };
|
|
4
|
+
const satoriInstance = { instance: void 0 };
|
|
5
|
+
export async function useResvg() {
|
|
6
|
+
resvgInstance.instance = resvgInstance.instance || await import("#og-image/bindings/resvg").then((m) => m.default);
|
|
7
|
+
await resvgInstance.instance.initWasmPromise;
|
|
8
|
+
return resvgInstance.instance.Resvg;
|
|
9
|
+
}
|
|
10
|
+
export async function useSatori() {
|
|
11
|
+
satoriInstance.instance = satoriInstance.instance || await import("#og-image/bindings/satori").then((m) => m.default);
|
|
12
|
+
await satoriInstance.instance.initWasmPromise;
|
|
13
|
+
return satoriInstance.instance.satori;
|
|
14
|
+
}
|
|
15
|
+
export async function useSharp() {
|
|
16
|
+
sharpInstance.instance = sharpInstance.instance || await import("#og-image/bindings/sharp").then((m) => m.default);
|
|
17
|
+
return sharpInstance.instance;
|
|
18
|
+
}
|
|
19
|
+
export async function useCssInline() {
|
|
20
|
+
cssInlineInstance.instance = cssInlineInstance.instance || await import("#og-image/bindings/css-inline").then((m) => m.default);
|
|
21
|
+
await cssInlineInstance.instance.initWasmPromise;
|
|
22
|
+
return cssInlineInstance.instance.cssInline;
|
|
23
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { defineSatoriTransformer } from "../utils.js";
|
|
2
|
+
export default defineSatoriTransformer([
|
|
3
|
+
{
|
|
4
|
+
filter: (node) => !!node.props?.class && !node.props?.tw,
|
|
5
|
+
transform(node) {
|
|
6
|
+
node.props.tw = node.props.class;
|
|
7
|
+
node.props.tw = node.props.tw.replace(/icon|inline-style/g, "");
|
|
8
|
+
}
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
filter: (node) => !!node.props?.style?.display,
|
|
12
|
+
transform(node) {
|
|
13
|
+
if (["inline-block", "inline"].includes(node.props.style.display))
|
|
14
|
+
delete node.props.style.display;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
]);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { defineSatoriTransformer } from "../utils.js";
|
|
2
|
+
function isEmojiFilter(node) {
|
|
3
|
+
return node.type === "svg" && typeof node.props?.["data-emoji"] !== "undefined";
|
|
4
|
+
}
|
|
5
|
+
export default defineSatoriTransformer([
|
|
6
|
+
// need to make sure parent div has flex for the emoji to render inline
|
|
7
|
+
{
|
|
8
|
+
filter: (node) => ["div", "p"].includes(node.type) && Array.isArray(node.props?.children) && node.props.children.some(isEmojiFilter),
|
|
9
|
+
transform: (node) => {
|
|
10
|
+
node.props.style = node.props.style || {};
|
|
11
|
+
node.props.style.display = "flex";
|
|
12
|
+
node.props.style.alignItems = "center";
|
|
13
|
+
node.props.children = node.props.children.map((child) => {
|
|
14
|
+
if (typeof child === "string") {
|
|
15
|
+
return {
|
|
16
|
+
type: "div",
|
|
17
|
+
props: {
|
|
18
|
+
children: child
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
if (child.props.class?.includes("emoji"))
|
|
23
|
+
delete child.props.class;
|
|
24
|
+
return child;
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
]);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { decodeHtml } from "../../../util/encoding.js";
|
|
2
|
+
import { defineSatoriTransformer } from "../utils.js";
|
|
3
|
+
export default defineSatoriTransformer([
|
|
4
|
+
// clean up
|
|
5
|
+
{
|
|
6
|
+
filter: (node) => node.props?.["data-v-inspector"],
|
|
7
|
+
transform: (node) => {
|
|
8
|
+
delete node.props["data-v-inspector"];
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
filter: (node) => typeof node.props?.children === "string",
|
|
13
|
+
transform: (node) => {
|
|
14
|
+
node.props.children = decodeHtml(node.props.children);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
]);
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { defineSatoriTransformer } from "../utils.js";
|
|
2
|
+
const BLOCK_ELEMENTS = [
|
|
3
|
+
"div",
|
|
4
|
+
"p",
|
|
5
|
+
"ul",
|
|
6
|
+
"ol",
|
|
7
|
+
"li",
|
|
8
|
+
"blockquote",
|
|
9
|
+
"pre",
|
|
10
|
+
"hr",
|
|
11
|
+
"table",
|
|
12
|
+
"dl"
|
|
13
|
+
];
|
|
14
|
+
const INLINE_ELEMENTS = [
|
|
15
|
+
"span",
|
|
16
|
+
"a",
|
|
17
|
+
"b",
|
|
18
|
+
"i",
|
|
19
|
+
"u",
|
|
20
|
+
"em",
|
|
21
|
+
"strong",
|
|
22
|
+
"code",
|
|
23
|
+
"abbr",
|
|
24
|
+
"del",
|
|
25
|
+
"ins",
|
|
26
|
+
"mark",
|
|
27
|
+
"sub",
|
|
28
|
+
"sup",
|
|
29
|
+
"small",
|
|
30
|
+
"p",
|
|
31
|
+
"h1",
|
|
32
|
+
"h2",
|
|
33
|
+
"h3",
|
|
34
|
+
"h4",
|
|
35
|
+
"h5"
|
|
36
|
+
];
|
|
37
|
+
export default defineSatoriTransformer({
|
|
38
|
+
filter: (node) => [...INLINE_ELEMENTS, "div"].includes(node.type) && (Array.isArray(node.props?.children) && node.props?.children.length >= 1) && !node.props?.class?.includes("hidden"),
|
|
39
|
+
transform: (node) => {
|
|
40
|
+
node.props.style = node.props.style || {};
|
|
41
|
+
if (node.props.style?.display && node.props.style?.display !== "flex") {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (node.type === "div") {
|
|
45
|
+
node.props.style.display = "flex";
|
|
46
|
+
if (!node.props?.class?.includes("flex-") && Array.isArray(node.props.children) && node.props.children.some((child) => BLOCK_ELEMENTS.includes(child.type))) {
|
|
47
|
+
node.props.style.flexDirection = "column";
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
let flexWrap = node.props?.class?.includes("flex-wrap");
|
|
52
|
+
if (!node.props?.class?.includes("flex-")) {
|
|
53
|
+
node.props.style.flexWrap = "wrap";
|
|
54
|
+
flexWrap = true;
|
|
55
|
+
}
|
|
56
|
+
if (flexWrap && !node.props?.class?.includes("gap")) {
|
|
57
|
+
node.props.style.gap = "0.2em";
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
});
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { useNitroOrigin } from "#site-config/server/composables/useNitroOrigin";
|
|
2
|
+
import sizeOf from "image-size";
|
|
3
|
+
import { useStorage } from "nitropack/runtime";
|
|
4
|
+
import { withBase, withoutLeadingSlash } from "ufo";
|
|
5
|
+
import { toBase64Image } from "../../../../shared.js";
|
|
6
|
+
import { decodeHtml } from "../../../util/encoding.js";
|
|
7
|
+
import { logger } from "../../../util/logger.js";
|
|
8
|
+
import { defineSatoriTransformer } from "../utils.js";
|
|
9
|
+
async function resolveLocalFilePathImage(publicStoragePath, src) {
|
|
10
|
+
const normalizedSrc = withoutLeadingSlash(
|
|
11
|
+
src.replace("_nuxt/@fs/", "").replace("_nuxt/", "").replace("./", "")
|
|
12
|
+
);
|
|
13
|
+
const key = `${publicStoragePath}:${normalizedSrc}`;
|
|
14
|
+
if (await useStorage().hasItem(key))
|
|
15
|
+
return await useStorage().getItemRaw(key);
|
|
16
|
+
}
|
|
17
|
+
export default defineSatoriTransformer([
|
|
18
|
+
// fix <img src="">
|
|
19
|
+
{
|
|
20
|
+
filter: (node) => node.type === "img" && node.props?.src,
|
|
21
|
+
transform: async (node, { e, publicStoragePath, runtimeConfig }) => {
|
|
22
|
+
let src = node.props.src;
|
|
23
|
+
const isRelative = src.startsWith("/");
|
|
24
|
+
let dimensions;
|
|
25
|
+
let imageBuffer;
|
|
26
|
+
if (src.endsWith(".webp")) {
|
|
27
|
+
logger.warn("Using WebP images with Satori is not supported. Please consider switching image format or use the chromium renderer.", src);
|
|
28
|
+
}
|
|
29
|
+
if (isRelative) {
|
|
30
|
+
if (import.meta.prerender || import.meta.dev) {
|
|
31
|
+
const srcWithoutBase = src.replace(runtimeConfig.app.baseURL, "");
|
|
32
|
+
imageBuffer = await resolveLocalFilePathImage(publicStoragePath, srcWithoutBase);
|
|
33
|
+
}
|
|
34
|
+
if (!imageBuffer) {
|
|
35
|
+
imageBuffer = await e.$fetch(src, { responseType: "arrayBuffer" }).catch(() => {
|
|
36
|
+
});
|
|
37
|
+
if (!imageBuffer && !import.meta.prerender) {
|
|
38
|
+
imageBuffer = await e.$fetch(src, {
|
|
39
|
+
baseURL: useNitroOrigin(e),
|
|
40
|
+
responseType: "arrayBuffer"
|
|
41
|
+
}).catch(() => {
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (imageBuffer) {
|
|
46
|
+
const buffer = imageBuffer instanceof ArrayBuffer ? imageBuffer : imageBuffer.buffer;
|
|
47
|
+
node.props.src = toBase64Image(buffer);
|
|
48
|
+
}
|
|
49
|
+
} else if (!src.startsWith("data:")) {
|
|
50
|
+
src = decodeHtml(src);
|
|
51
|
+
node.props.src = src;
|
|
52
|
+
imageBuffer = await $fetch(src, {
|
|
53
|
+
responseType: "arrayBuffer"
|
|
54
|
+
}).catch(() => {
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
if (imageBuffer && (!node.props.width || !node.props.height)) {
|
|
58
|
+
try {
|
|
59
|
+
const imageSize = sizeOf(imageBuffer);
|
|
60
|
+
dimensions = { width: imageSize.width, height: imageSize.height };
|
|
61
|
+
} catch {
|
|
62
|
+
}
|
|
63
|
+
if (dimensions?.width && dimensions?.height) {
|
|
64
|
+
const naturalAspectRatio = dimensions.width / dimensions.height;
|
|
65
|
+
if (node.props.width && !node.props.height) {
|
|
66
|
+
node.props.height = Math.round(node.props.width / naturalAspectRatio);
|
|
67
|
+
} else if (node.props.height && !node.props.width) {
|
|
68
|
+
node.props.width = Math.round(node.props.height * naturalAspectRatio);
|
|
69
|
+
} else if (!node.props.width && !node.props.height) {
|
|
70
|
+
node.props.width = dimensions.width;
|
|
71
|
+
node.props.height = dimensions.height;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (typeof node.props.src === "string" && node.props.src.startsWith("/")) {
|
|
76
|
+
if (imageBuffer) {
|
|
77
|
+
const buffer = imageBuffer instanceof ArrayBuffer ? imageBuffer : imageBuffer.buffer;
|
|
78
|
+
node.props.src = toBase64Image(buffer);
|
|
79
|
+
} else {
|
|
80
|
+
node.props.src = `${withBase(src, `${useNitroOrigin(e)}`)}?${Date.now()}`;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
// fix style="background-image: url('')"
|
|
86
|
+
{
|
|
87
|
+
filter: (node) => node.props?.style?.backgroundImage?.includes("url("),
|
|
88
|
+
transform: async (node, { e, publicStoragePath, runtimeConfig }) => {
|
|
89
|
+
const backgroundImage = node.props.style.backgroundImage;
|
|
90
|
+
const src = backgroundImage.replace(/^url\(['"]?/, "").replace(/['"]?\)$/, "");
|
|
91
|
+
const isRelative = src?.startsWith("/");
|
|
92
|
+
if (isRelative) {
|
|
93
|
+
if (import.meta.prerender || import.meta.dev) {
|
|
94
|
+
const srcWithoutBase = src.replace(runtimeConfig.app.baseURL, "/");
|
|
95
|
+
const imageBuffer = await resolveLocalFilePathImage(publicStoragePath, srcWithoutBase);
|
|
96
|
+
if (imageBuffer) {
|
|
97
|
+
const buffer = imageBuffer instanceof ArrayBuffer ? imageBuffer : imageBuffer.buffer;
|
|
98
|
+
const base64 = toBase64Image(buffer);
|
|
99
|
+
node.props.style.backgroundImage = `url(${base64})`;
|
|
100
|
+
}
|
|
101
|
+
} else {
|
|
102
|
+
node.props.style.backgroundImage = `url(${withBase(src, `${useNitroOrigin(e)}`)}?${Date.now()})`;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
]);
|