nuxt-og-image 3.0.0-beta.56 → 3.0.0-beta.57
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 +4 -4
- package/dist/client/404.html +4 -4
- package/dist/client/_nuxt/{IconCSS.61e8aae5.js → IconCSS.d8005789.js} +1 -1
- package/dist/client/_nuxt/builds/latest.json +1 -1
- package/dist/client/_nuxt/builds/meta/38e9d3f8-5af7-499d-9676-18bb01183aee.json +1 -0
- package/dist/client/_nuxt/{entry.b9ee0ddb.js → entry.79f3f186.js} +3 -3
- package/dist/client/_nuxt/{error-404.98ecfc89.js → error-404.bda968de.js} +1 -1
- package/dist/client/_nuxt/{error-500.372010ac.js → error-500.174afb83.js} +1 -1
- package/dist/client/index.html +4 -4
- package/dist/module.d.mts +3 -2
- package/dist/module.d.ts +3 -2
- package/dist/module.json +1 -1
- package/dist/module.mjs +46 -20
- package/dist/runtime/core/cache/fonts.d.ts +3 -0
- package/dist/runtime/core/cache/fonts.mjs +6 -0
- package/dist/runtime/core/font/fetch.d.ts +2 -2
- package/dist/runtime/core/font/fetch.mjs +4 -14
- package/dist/runtime/core/renderers/satori/index.mjs +28 -6
- package/dist/runtime/core/renderers/satori/plugins/imageSrc.mjs +63 -46
- package/dist/runtime/core/utils/resolveRendererContext.mjs +1 -1
- package/dist/runtime/nitro/plugins/prerender.mjs +1 -1
- package/dist/runtime/types.d.ts +7 -2
- package/dist/runtime/utils.pure.d.ts +2 -1
- package/dist/runtime/utils.pure.mjs +22 -2
- package/package.json +1 -1
- package/dist/client/_nuxt/builds/meta/28b1469d-fd08-4832-8243-eb0cf430bf2b.json +0 -1
- package/dist/runtime/core/font/cache.d.ts +0 -1
- package/dist/runtime/core/font/cache.mjs +0 -1
- package/dist/runtime/core/renderers/satori/fonts.d.ts +0 -3
- package/dist/runtime/core/renderers/satori/fonts.mjs +0 -8
|
@@ -1 +1 @@
|
|
|
1
|
-
import{_ as a,u as n,o as r,c as l,a as e,t as s,b as d,w as c,d as p,e as f,p as x,f as h}from"./entry.
|
|
1
|
+
import{_ as a,u as n,o as r,c as l,a as e,t as s,b as d,w as c,d as p,e as f,p as x,f as h}from"./entry.79f3f186.js";const m=t=>(x("data-v-05a2b8a3"),t=t(),h(),t),u={class:"font-sans antialiased bg-white dark:bg-black text-black dark:text-white grid min-h-screen place-content-center overflow-hidden"},g=m(()=>e("div",{class:"fixed left-0 right-0 spotlight z-10"},null,-1)),b={class:"max-w-520px text-center z-20"},_=["textContent"],w=["textContent"],y={class:"w-full flex items-center justify-center"},S={__name:"error-404",props:{appName:{type:String,default:"Nuxt"},version:{type:String,default:""},statusCode:{type:Number,default:404},statusMessage:{type:String,default:"Not Found"},description:{type:String,default:"Sorry, the page you are looking for could not be found."},backHome:{type:String,default:"Go back home"}},setup(t){const o=t;return n({title:`${o.statusCode} - ${o.statusMessage} | ${o.appName}`,script:[],style:[{children:'*,:before,:after{-webkit-box-sizing:border-box;box-sizing:border-box;border-width:0;border-style:solid;border-color:#e0e0e0}*{--tw-ring-inset:var(--tw-empty, );--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(14, 165, 233, .5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000}:root{-moz-tab-size:4;-o-tab-size:4;tab-size:4}a{color:inherit;text-decoration:inherit}body{margin:0;font-family:inherit;line-height:inherit}html{-webkit-text-size-adjust:100%;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";line-height:1.5}h1,p{margin:0}h1{font-size:inherit;font-weight:inherit}'}]}),(k,v)=>{const i=f;return r(),l("div",u,[g,e("div",b,[e("h1",{class:"text-8xl sm:text-10xl font-medium mb-8",textContent:s(t.statusCode)},null,8,_),e("p",{class:"text-xl px-8 sm:px-0 sm:text-4xl font-light mb-16 leading-tight",textContent:s(t.description)},null,8,w),e("div",y,[d(i,{to:"/",class:"gradient-border text-md sm:text-xl py-2 px-4 sm:py-3 sm:px-6 cursor-pointer"},{default:c(()=>[p(s(t.backHome),1)]),_:1})])])])}}},z=a(S,[["__scopeId","data-v-05a2b8a3"]]);export{z as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{_ as i,u as a,o as r,c as n,a as e,t as s,p as l,f as d}from"./entry.
|
|
1
|
+
import{_ as i,u as a,o as r,c as n,a as e,t as s,p as l,f as d}from"./entry.79f3f186.js";const c=t=>(l("data-v-c967d9a9"),t=t(),d(),t),p={class:"font-sans antialiased bg-white dark:bg-black text-black dark:text-white grid min-h-screen place-content-center overflow-hidden"},h=c(()=>e("div",{class:"fixed -bottom-1/2 left-0 right-0 h-1/2 spotlight"},null,-1)),f={class:"max-w-520px text-center"},g=["textContent"],m=["textContent"],x={__name:"error-500",props:{appName:{type:String,default:"Nuxt"},version:{type:String,default:""},statusCode:{type:Number,default:500},statusMessage:{type:String,default:"Server error"},description:{type:String,default:"This page is temporarily unavailable."}},setup(t){const o=t;return a({title:`${o.statusCode} - ${o.statusMessage} | ${o.appName}`,script:[],style:[{children:'*,:before,:after{-webkit-box-sizing:border-box;box-sizing:border-box;border-width:0;border-style:solid;border-color:#e0e0e0}*{--tw-ring-inset:var(--tw-empty, );--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(14, 165, 233, .5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000}:root{-moz-tab-size:4;-o-tab-size:4;tab-size:4}body{margin:0;font-family:inherit;line-height:inherit}html{-webkit-text-size-adjust:100%;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";line-height:1.5}h1,p{margin:0}h1{font-size:inherit;font-weight:inherit}'}]}),(u,b)=>(r(),n("div",p,[h,e("div",f,[e("h1",{class:"text-8xl sm:text-10xl font-medium mb-8",textContent:s(t.statusCode)},null,8,g),e("p",{class:"text-xl px-8 sm:px-0 sm:text-4xl font-light mb-16 leading-tight",textContent:s(t.description)},null,8,m)])]))}},w=i(x,[["__scopeId","data-v-c967d9a9"]]);export{w as default};
|
package/dist/client/index.html
CHANGED
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
<head><meta charset="utf-8">
|
|
4
4
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
5
5
|
<link rel="stylesheet" href="/__nuxt-og-image/_nuxt/entry.0c999acd.css">
|
|
6
|
-
<link rel="modulepreload" as="script" crossorigin href="/__nuxt-og-image/_nuxt/entry.
|
|
6
|
+
<link rel="modulepreload" as="script" crossorigin href="/__nuxt-og-image/_nuxt/entry.79f3f186.js">
|
|
7
7
|
<link rel="prefetch" as="script" crossorigin href="/__nuxt-og-image/_nuxt/vanilla-picker-NKbIFE8h.23409a58.js">
|
|
8
8
|
<link rel="prefetch" as="style" href="/__nuxt-og-image/_nuxt/error-404.b751fa02.css">
|
|
9
|
-
<link rel="prefetch" as="script" crossorigin href="/__nuxt-og-image/_nuxt/error-404.
|
|
9
|
+
<link rel="prefetch" as="script" crossorigin href="/__nuxt-og-image/_nuxt/error-404.bda968de.js">
|
|
10
10
|
<link rel="prefetch" as="style" href="/__nuxt-og-image/_nuxt/error-500.69009e70.css">
|
|
11
|
-
<link rel="prefetch" as="script" crossorigin href="/__nuxt-og-image/_nuxt/error-500.
|
|
12
|
-
<script type="module" src="/__nuxt-og-image/_nuxt/entry.
|
|
11
|
+
<link rel="prefetch" as="script" crossorigin href="/__nuxt-og-image/_nuxt/error-500.174afb83.js">
|
|
12
|
+
<script type="module" src="/__nuxt-og-image/_nuxt/entry.79f3f186.js" crossorigin></script><script>"use strict";(()=>{const a=window,e=document.documentElement,m=["dark","light"],c=window&&window.localStorage&&window.localStorage.getItem&&window.localStorage.getItem("nuxt-color-mode")||"system";let n=c==="system"?d():c;const l=e.getAttribute("data-color-mode-forced");l&&(n=l),i(n),a["__NUXT_COLOR_MODE__"]={preference:c,value:n,getColorScheme:d,addColorScheme:i,removeColorScheme:f};function i(o){const t=""+o+"",s="";e.classList?e.classList.add(t):e.className+=" "+t,s&&e.setAttribute("data-"+s,o)}function f(o){const t=""+o+"",s="";e.classList?e.classList.remove(t):e.className=e.className.replace(new RegExp(t,"g"),""),s&&e.removeAttribute("data-"+s)}function r(o){return a.matchMedia("(prefers-color-scheme"+o+")")}function d(){if(a.matchMedia&&r("").media!=="not all"){for(const o of m)if(r(":"+o).matches)return o}return"light"}})();
|
|
13
13
|
</script></head>
|
|
14
14
|
<body ><div id="__nuxt"></div><script type="application/json" id="__NUXT_DATA__" data-ssr="false">[{"_errors":1,"serverRendered":2,"data":3,"state":4},{},false,{},{}]</script>
|
|
15
15
|
<script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-og-image",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body>
|
package/dist/module.d.mts
CHANGED
|
@@ -78,15 +78,16 @@ interface OgImageOptions<T extends keyof OgImageComponents = 'NuxtSeo'> {
|
|
|
78
78
|
satori?: SatoriOptions;
|
|
79
79
|
screenshot?: Partial<ScreenshotOptions>;
|
|
80
80
|
sharp?: SharpOptions;
|
|
81
|
+
fonts?: InputFontConfig[];
|
|
81
82
|
cacheMaxAgeSeconds?: number;
|
|
82
83
|
}
|
|
83
84
|
interface FontConfig {
|
|
84
85
|
name: string;
|
|
85
|
-
weight
|
|
86
|
+
weight?: string | number;
|
|
86
87
|
path?: string;
|
|
87
88
|
key?: string;
|
|
88
89
|
}
|
|
89
|
-
type InputFontConfig = (`${string}:${number}` | FontConfig);
|
|
90
|
+
type InputFontConfig = (`${string}:${number}` | string | FontConfig);
|
|
90
91
|
interface RuntimeCompatibilitySchema {
|
|
91
92
|
chromium: 'node' | false;
|
|
92
93
|
['css-inline']: 'node' | false;
|
package/dist/module.d.ts
CHANGED
|
@@ -78,15 +78,16 @@ interface OgImageOptions<T extends keyof OgImageComponents = 'NuxtSeo'> {
|
|
|
78
78
|
satori?: SatoriOptions;
|
|
79
79
|
screenshot?: Partial<ScreenshotOptions>;
|
|
80
80
|
sharp?: SharpOptions;
|
|
81
|
+
fonts?: InputFontConfig[];
|
|
81
82
|
cacheMaxAgeSeconds?: number;
|
|
82
83
|
}
|
|
83
84
|
interface FontConfig {
|
|
84
85
|
name: string;
|
|
85
|
-
weight
|
|
86
|
+
weight?: string | number;
|
|
86
87
|
path?: string;
|
|
87
88
|
key?: string;
|
|
88
89
|
}
|
|
89
|
-
type InputFontConfig = (`${string}:${number}` | FontConfig);
|
|
90
|
+
type InputFontConfig = (`${string}:${number}` | string | FontConfig);
|
|
90
91
|
interface RuntimeCompatibilitySchema {
|
|
91
92
|
chromium: 'node' | false;
|
|
92
93
|
['css-inline']: 'node' | false;
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -14,7 +14,7 @@ import { createHash } from 'node:crypto';
|
|
|
14
14
|
import { execa } from 'execa';
|
|
15
15
|
import terminate from 'terminate';
|
|
16
16
|
|
|
17
|
-
const version = "3.0.0-beta.
|
|
17
|
+
const version = "3.0.0-beta.57";
|
|
18
18
|
|
|
19
19
|
const autodetectableProviders = {
|
|
20
20
|
azure_static: "azure",
|
|
@@ -358,6 +358,27 @@ async function ensureChromium(logger) {
|
|
|
358
358
|
installChromeProcess.pid && terminate(installChromeProcess.pid);
|
|
359
359
|
}
|
|
360
360
|
|
|
361
|
+
function normaliseFontInput(fonts) {
|
|
362
|
+
return fonts.map((f) => {
|
|
363
|
+
if (typeof f === "string") {
|
|
364
|
+
const [name, weight] = f.split(":");
|
|
365
|
+
return {
|
|
366
|
+
cacheKey: f,
|
|
367
|
+
name,
|
|
368
|
+
weight: weight || "400",
|
|
369
|
+
style: "normal",
|
|
370
|
+
path: void 0
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
return {
|
|
374
|
+
cacheKey: f.key || `${f.name}:${f.weight}`,
|
|
375
|
+
style: "normal",
|
|
376
|
+
weight: 400,
|
|
377
|
+
...f
|
|
378
|
+
};
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
|
|
361
382
|
const module = defineNuxtModule({
|
|
362
383
|
meta: {
|
|
363
384
|
name: "nuxt-og-image",
|
|
@@ -421,13 +442,13 @@ const module = defineNuxtModule({
|
|
|
421
442
|
prerender: { sharp: false }
|
|
422
443
|
});
|
|
423
444
|
}
|
|
445
|
+
let hasChromeLocally = false;
|
|
446
|
+
try {
|
|
447
|
+
hasChromeLocally = !!Launcher.getFirstInstallation();
|
|
448
|
+
} catch {
|
|
449
|
+
}
|
|
424
450
|
const isUndefinedOrTruthy = (v) => typeof v === "undefined" || v !== false;
|
|
425
451
|
if (isUndefinedOrTruthy(config.compatibility?.prerender?.chromium) && isUndefinedOrTruthy(config.compatibility?.runtime?.chromium)) {
|
|
426
|
-
let hasChromeLocally = false;
|
|
427
|
-
try {
|
|
428
|
-
hasChromeLocally = !!Launcher.getFirstInstallation();
|
|
429
|
-
} catch {
|
|
430
|
-
}
|
|
431
452
|
if (isCI)
|
|
432
453
|
await ensureChromium(logger);
|
|
433
454
|
const hasPlaywrightDependency = !!await tryResolveModule("playwright");
|
|
@@ -444,12 +465,23 @@ const module = defineNuxtModule({
|
|
|
444
465
|
prerender: { chromium: "node" }
|
|
445
466
|
});
|
|
446
467
|
}
|
|
468
|
+
} else if (!hasChromeLocally && nuxt.options.dev && config.compatibility?.dev?.chromium === "node") {
|
|
469
|
+
await ensureChromium(logger);
|
|
447
470
|
}
|
|
448
471
|
await installNuxtSiteConfig();
|
|
449
472
|
if (hasNuxtModule("@nuxt/content"))
|
|
450
473
|
addServerPlugin(resolve("./runtime/nitro/plugins/nuxt-content"));
|
|
451
474
|
if (!config.fonts.length)
|
|
452
475
|
config.fonts = ["Inter:400", "Inter:700"];
|
|
476
|
+
if (preset === "cloudflare") {
|
|
477
|
+
config.fonts = config.fonts.filter((f) => {
|
|
478
|
+
if (typeof f !== "string" && f.path) {
|
|
479
|
+
logger.warn(`The ${f.name}:${f.weight} font was skipped because remote fonts are not available in Cloudflare Workers, please use a Google font.`);
|
|
480
|
+
return false;
|
|
481
|
+
}
|
|
482
|
+
return true;
|
|
483
|
+
});
|
|
484
|
+
}
|
|
453
485
|
if (preset === "stackblitz") {
|
|
454
486
|
config.fonts = config.fonts.map((f) => {
|
|
455
487
|
if (typeof f === "string" && f.startsWith("Inter:")) {
|
|
@@ -584,7 +616,7 @@ declare module 'nitropack' {
|
|
|
584
616
|
}
|
|
585
617
|
interface NitroRuntimeHooks {
|
|
586
618
|
'nuxt-og-image:context': (ctx: import('${typesPath}').OgImageRenderEventContext) => void | Promise<void>
|
|
587
|
-
'nuxt-og-image:satori:vnodes': (vnodes: import('${typesPath}').VNode) => void | Promise<void>
|
|
619
|
+
'nuxt-og-image:satori:vnodes': (vnodes: import('${typesPath}').VNode, ctx: ctx: import('${typesPath}').OgImageRenderEventContext) => void | Promise<void>
|
|
588
620
|
}
|
|
589
621
|
}
|
|
590
622
|
|
|
@@ -601,17 +633,7 @@ ${componentImports}
|
|
|
601
633
|
if (!cacheEnabled)
|
|
602
634
|
baseCacheKey = false;
|
|
603
635
|
nuxt.hooks.hook("modules:done", async () => {
|
|
604
|
-
const normalisedFonts = config.fonts
|
|
605
|
-
if (typeof f === "string") {
|
|
606
|
-
const [name, weight] = f.split(":");
|
|
607
|
-
return {
|
|
608
|
-
name,
|
|
609
|
-
weight,
|
|
610
|
-
path: void 0
|
|
611
|
-
};
|
|
612
|
-
}
|
|
613
|
-
return f;
|
|
614
|
-
});
|
|
636
|
+
const normalisedFonts = normaliseFontInput(config.fonts);
|
|
615
637
|
if (!nuxt.options._generate && nuxt.options.build) {
|
|
616
638
|
nuxt.options.nitro.prerender = nuxt.options.nitro.prerender || {};
|
|
617
639
|
nuxt.options.nitro.prerender.routes = nuxt.options.nitro.prerender.routes || [];
|
|
@@ -619,8 +641,12 @@ ${componentImports}
|
|
|
619
641
|
nuxt.options.nitro.prerender.routes.push(`/__og-image__/font/${name}/${weight}.ttf`);
|
|
620
642
|
});
|
|
621
643
|
}
|
|
622
|
-
|
|
623
|
-
|
|
644
|
+
const hasColorModeModule = hasNuxtModule("@nuxtjs/color-mode");
|
|
645
|
+
const colorModeOptions = hasColorModeModule ? await getNuxtModuleOptions("@nuxtjs/color-mode") : {};
|
|
646
|
+
let colorPreference = colorModeOptions.preference;
|
|
647
|
+
if (!colorPreference || colorPreference === "system")
|
|
648
|
+
colorPreference = colorModeOptions.fallback;
|
|
649
|
+
if (!colorPreference || colorPreference === "system")
|
|
624
650
|
colorPreference = "light";
|
|
625
651
|
const runtimeConfig = {
|
|
626
652
|
version,
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare function loadFont({ e }: OgImageRenderEventContext, font:
|
|
1
|
+
import type { OgImageRenderEventContext, ResolvedFontConfig } from '../../types';
|
|
2
|
+
export declare function loadFont({ e }: OgImageRenderEventContext, font: ResolvedFontConfig): Promise<ResolvedFontConfig>;
|
|
@@ -1,11 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { useNitroOrigin, useStorage } from "#imports";
|
|
1
|
+
import { useStorage } from "#internal/nitro";
|
|
2
|
+
import { useNitroOrigin } from "#imports";
|
|
4
3
|
import { assets } from "#internal/nitro/virtual/server-assets";
|
|
5
4
|
export async function loadFont({ e }, font) {
|
|
6
|
-
const fontKey = font.key || `${font.name}:${font.weight}`;
|
|
7
|
-
if (fontCache[fontKey])
|
|
8
|
-
return fontCache[fontKey];
|
|
9
5
|
const { name, weight } = font;
|
|
10
6
|
let data;
|
|
11
7
|
if (import.meta.dev || import.meta.prerender) {
|
|
@@ -35,12 +31,6 @@ export async function loadFont({ e }, font) {
|
|
|
35
31
|
});
|
|
36
32
|
}
|
|
37
33
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
return fontCache[fontKey];
|
|
41
|
-
}
|
|
42
|
-
return createError({
|
|
43
|
-
statusCode: 500,
|
|
44
|
-
statusMessage: `Failed to fetch font: ${fontKey}`
|
|
45
|
-
});
|
|
34
|
+
font.data = data;
|
|
35
|
+
return font;
|
|
46
36
|
}
|
|
@@ -1,18 +1,40 @@
|
|
|
1
1
|
import { defu } from "defu";
|
|
2
|
-
import { useOgImageRuntimeConfig } from "../../../utils.mjs";
|
|
2
|
+
import { normaliseFontInput, useOgImageRuntimeConfig } from "../../../utils.mjs";
|
|
3
|
+
import { loadFont } from "../../font/fetch.mjs";
|
|
4
|
+
import { fontCache, fontPromises } from "../../cache/fonts.mjs";
|
|
3
5
|
import { createVNodes } from "./vnodes.mjs";
|
|
4
|
-
import { loadFonts, satoriFonts } from "./fonts.mjs";
|
|
5
6
|
import { useResvg, useSatori, useSharp } from "./instances.mjs";
|
|
7
|
+
import { theme } from "#nuxt-og-image/unocss-config.mjs";
|
|
6
8
|
export async function createSvg(event) {
|
|
7
9
|
const { options } = event;
|
|
8
10
|
const { fonts, satoriOptions } = useOgImageRuntimeConfig();
|
|
9
11
|
const vnodes = await createVNodes(event);
|
|
10
|
-
await event._nitro.hooks.callHook("nuxt-og-image:satori:vnodes", vnodes);
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
await event._nitro.hooks.callHook("nuxt-og-image:satori:vnodes", vnodes, event);
|
|
13
|
+
const normalisedFonts = normaliseFontInput([...fonts, ...event.options.fonts || []]);
|
|
14
|
+
const localFontPromises = [];
|
|
15
|
+
const preloadedFonts = [];
|
|
16
|
+
for (const font of normalisedFonts) {
|
|
17
|
+
if (await fontCache.hasItem(font.cacheKey)) {
|
|
18
|
+
font.data = await fontCache.getItemRaw(font.cacheKey);
|
|
19
|
+
preloadedFonts.push(font);
|
|
20
|
+
} else {
|
|
21
|
+
if (!fontPromises[font.cacheKey]) {
|
|
22
|
+
fontPromises[font.cacheKey] = loadFont(event, font).then(async (_font) => {
|
|
23
|
+
if (_font?.data)
|
|
24
|
+
await fontCache.setItemRaw(_font.cacheKey, _font.data);
|
|
25
|
+
return _font;
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
localFontPromises.push(fontPromises[font.cacheKey]);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const awaitedFonts = await Promise.all(localFontPromises);
|
|
13
32
|
const satori = await useSatori();
|
|
14
33
|
return satori(vnodes, defu(options.satori, satoriOptions, {
|
|
15
|
-
fonts:
|
|
34
|
+
fonts: [...preloadedFonts, ...awaitedFonts].map((_f) => {
|
|
35
|
+
return { ..._f, weight: Number(_f.weight) };
|
|
36
|
+
}),
|
|
37
|
+
tailwindConfig: { theme },
|
|
16
38
|
embedFont: true,
|
|
17
39
|
width: options.width,
|
|
18
40
|
height: options.height
|
|
@@ -3,56 +3,73 @@ import { withBase } from "ufo";
|
|
|
3
3
|
import sizeOf from "image-size";
|
|
4
4
|
import { defineSatoriTransformer } from "../utils.mjs";
|
|
5
5
|
import { toBase64Image } from "../../../env/assets.mjs";
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
6
|
+
import { useStorage } from "#internal/nitro";
|
|
7
|
+
import { useNitroOrigin } from "#imports";
|
|
8
|
+
export default defineSatoriTransformer([
|
|
9
|
+
// fix <img src="">
|
|
10
|
+
{
|
|
11
|
+
filter: (node) => node.type === "img",
|
|
12
|
+
transform: async (node, { e }) => {
|
|
13
|
+
const src = node.props?.src;
|
|
14
|
+
const isRelative = src?.startsWith("/");
|
|
15
|
+
if (src) {
|
|
16
|
+
let updated = false;
|
|
17
|
+
let dimensions;
|
|
18
|
+
let imageBuffer;
|
|
19
|
+
let valid = true;
|
|
20
|
+
if (import.meta.prerender || import.meta.dev) {
|
|
21
|
+
const key = `root:public${src.replace("./", ":").replace("/", ":")}`;
|
|
22
|
+
if (await useStorage().hasItem(key)) {
|
|
23
|
+
imageBuffer = await useStorage().getItemRaw(key);
|
|
24
|
+
updated = !!imageBuffer;
|
|
25
|
+
}
|
|
22
26
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
valid = !!imageBuffer;
|
|
32
|
-
}
|
|
33
|
-
if (valid) {
|
|
34
|
-
node.props.src = toBase64Image(src, imageBuffer);
|
|
35
|
-
try {
|
|
36
|
-
const imageSize = sizeOf(Buffer.from(imageBuffer));
|
|
37
|
-
dimensions = { width: imageSize.width, height: imageSize.height };
|
|
38
|
-
} catch (e2) {
|
|
27
|
+
if (!import.meta.prerender && !updated) {
|
|
28
|
+
imageBuffer = await e.$fetch(src, {
|
|
29
|
+
baseURL: useNitroOrigin(e),
|
|
30
|
+
responseType: "arrayBuffer"
|
|
31
|
+
}).catch(() => {
|
|
32
|
+
valid = false;
|
|
33
|
+
});
|
|
34
|
+
valid = !!imageBuffer;
|
|
39
35
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
|
|
36
|
+
if (valid) {
|
|
37
|
+
node.props.src = toBase64Image(src, imageBuffer);
|
|
38
|
+
try {
|
|
39
|
+
const imageSize = sizeOf(Buffer.from(imageBuffer));
|
|
40
|
+
dimensions = { width: imageSize.width, height: imageSize.height };
|
|
41
|
+
} catch (e2) {
|
|
42
|
+
}
|
|
43
|
+
updated = true;
|
|
44
|
+
}
|
|
45
|
+
if (dimensions?.width && dimensions?.height) {
|
|
46
|
+
const naturalAspectRatio = dimensions.width / dimensions.height;
|
|
47
|
+
if (node.props.width && !node.props.height) {
|
|
48
|
+
node.props.height = Math.round(node.props.width / naturalAspectRatio);
|
|
49
|
+
} else if (node.props.height && !node.props.width) {
|
|
50
|
+
node.props.width = Math.round(node.props.height * naturalAspectRatio);
|
|
51
|
+
} else if (!node.props.width && !node.props.height) {
|
|
52
|
+
node.props.width = dimensions.width;
|
|
53
|
+
node.props.height = dimensions.height;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (!updated && isRelative) {
|
|
57
|
+
node.props.src = `${withBase(src, `${useNitroOrigin(e)}`)}?${Date.now()}`;
|
|
51
58
|
}
|
|
52
59
|
}
|
|
53
|
-
|
|
54
|
-
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
// fix style="background-image: url('')"
|
|
63
|
+
{
|
|
64
|
+
filter: (node) => node.props.style?.backgroundImage?.includes("url("),
|
|
65
|
+
transform: async (node, { e }) => {
|
|
66
|
+
const backgroundImage = node.props.style.backgroundImage;
|
|
67
|
+
if (backgroundImage) {
|
|
68
|
+
const src = backgroundImage.replace(/^url\(['"]?/, "").replace(/['"]?\)$/, "");
|
|
69
|
+
const isRelative = src?.startsWith("/");
|
|
70
|
+
if (isRelative)
|
|
71
|
+
node.props.style.backgroundImage = `url(${withBase(src, `${useNitroOrigin(e)}`)}?${Date.now()})`;
|
|
55
72
|
}
|
|
56
73
|
}
|
|
57
74
|
}
|
|
58
|
-
|
|
75
|
+
]);
|
|
@@ -7,7 +7,7 @@ import { prerenderOptionsCache } from "../cache/prerender.mjs";
|
|
|
7
7
|
import { useChromiumRenderer, useSatoriRenderer } from "../renderers/satori/instances.mjs";
|
|
8
8
|
import { separateProps, useOgImageRuntimeConfig } from "../../utils.mjs";
|
|
9
9
|
import { resolvePathCacheKey } from "../../nitro/utils.mjs";
|
|
10
|
-
import { useNitroApp, useRuntimeConfig } from "#
|
|
10
|
+
import { useNitroApp, useRuntimeConfig } from "#internal/nitro";
|
|
11
11
|
export async function resolveRendererContext(e) {
|
|
12
12
|
const runtimeConfig = useOgImageRuntimeConfig();
|
|
13
13
|
const path = parseURL(e.path).pathname;
|
|
@@ -6,7 +6,7 @@ import { extractAndNormaliseOgImageOptions } from "../../core/options/extract.mj
|
|
|
6
6
|
import { prerenderOptionsCache } from "../../core/cache/prerender.mjs";
|
|
7
7
|
import { isInternalRoute } from "../../utils.pure.mjs";
|
|
8
8
|
import { resolvePathCacheKey } from "../utils.mjs";
|
|
9
|
-
import { useRuntimeConfig } from "#
|
|
9
|
+
import { useRuntimeConfig } from "#internal/nitro";
|
|
10
10
|
export default defineNitroPlugin(async (nitro) => {
|
|
11
11
|
if (!import.meta.prerender)
|
|
12
12
|
return;
|
package/dist/runtime/types.d.ts
CHANGED
|
@@ -104,15 +104,20 @@ export interface OgImageOptions<T extends keyof OgImageComponents = 'NuxtSeo'> {
|
|
|
104
104
|
satori?: SatoriOptions;
|
|
105
105
|
screenshot?: Partial<ScreenshotOptions>;
|
|
106
106
|
sharp?: SharpOptions;
|
|
107
|
+
fonts?: InputFontConfig[];
|
|
107
108
|
cacheMaxAgeSeconds?: number;
|
|
108
109
|
}
|
|
109
110
|
export interface FontConfig {
|
|
110
111
|
name: string;
|
|
111
|
-
weight
|
|
112
|
+
weight?: string | number;
|
|
112
113
|
path?: string;
|
|
113
114
|
key?: string;
|
|
114
115
|
}
|
|
115
|
-
export
|
|
116
|
+
export interface ResolvedFontConfig extends FontConfig {
|
|
117
|
+
cacheKey: string;
|
|
118
|
+
data?: BufferSource;
|
|
119
|
+
}
|
|
120
|
+
export type InputFontConfig = (`${string}:${number}` | string | FontConfig);
|
|
116
121
|
export interface RuntimeCompatibilitySchema {
|
|
117
122
|
chromium: 'node' | false;
|
|
118
123
|
['css-inline']: 'node' | false;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type { OgImageOptions } from './types';
|
|
1
|
+
import type { InputFontConfig, OgImageOptions, ResolvedFontConfig } from './types';
|
|
2
2
|
export declare function isInternalRoute(path: string): boolean;
|
|
3
3
|
export declare function separateProps(options: OgImageOptions | undefined, ignoreKeys?: string[]): {
|
|
4
4
|
props: Record<string, any>;
|
|
5
5
|
};
|
|
6
|
+
export declare function normaliseFontInput(fonts: InputFontConfig[]): ResolvedFontConfig[];
|
|
@@ -9,6 +9,7 @@ function filterIsOgImageOption(key) {
|
|
|
9
9
|
"extension",
|
|
10
10
|
"width",
|
|
11
11
|
"height",
|
|
12
|
+
"fonts",
|
|
12
13
|
"alt",
|
|
13
14
|
"props",
|
|
14
15
|
"renderer",
|
|
@@ -20,8 +21,7 @@ function filterIsOgImageOption(key) {
|
|
|
20
21
|
"resvg",
|
|
21
22
|
"sharp",
|
|
22
23
|
"screenshot",
|
|
23
|
-
"cacheMaxAgeSeconds"
|
|
24
|
-
"componentHash"
|
|
24
|
+
"cacheMaxAgeSeconds"
|
|
25
25
|
];
|
|
26
26
|
return keys.includes(key);
|
|
27
27
|
}
|
|
@@ -41,3 +41,23 @@ export function separateProps(options, ignoreKeys = []) {
|
|
|
41
41
|
props
|
|
42
42
|
};
|
|
43
43
|
}
|
|
44
|
+
export function normaliseFontInput(fonts) {
|
|
45
|
+
return fonts.map((f) => {
|
|
46
|
+
if (typeof f === "string") {
|
|
47
|
+
const [name, weight] = f.split(":");
|
|
48
|
+
return {
|
|
49
|
+
cacheKey: f,
|
|
50
|
+
name,
|
|
51
|
+
weight: weight || "400",
|
|
52
|
+
style: "normal",
|
|
53
|
+
path: void 0
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
cacheKey: f.key || `${f.name}:${f.weight}`,
|
|
58
|
+
style: "normal",
|
|
59
|
+
weight: 400,
|
|
60
|
+
...f
|
|
61
|
+
};
|
|
62
|
+
});
|
|
63
|
+
}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"id":"28b1469d-fd08-4832-8243-eb0cf430bf2b","timestamp":1701958017527,"matcher":{"static":{},"wildcard":{},"dynamic":{}},"prerendered":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const fontCache: Record<string, any>;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const fontCache = {};
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { loadFont } from "../../font/fetch.mjs";
|
|
2
|
-
export const satoriFonts = [];
|
|
3
|
-
let fontLoadPromise = null;
|
|
4
|
-
export function loadFonts(e, fonts) {
|
|
5
|
-
if (fontLoadPromise)
|
|
6
|
-
return fontLoadPromise;
|
|
7
|
-
return fontLoadPromise = Promise.all(fonts.map((font) => loadFont(e, font)));
|
|
8
|
-
}
|