nuxt-og-image 1.0.0-beta.4 → 1.0.0-beta.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. package/dist/client/200.html +2 -2
  2. package/dist/client/404.html +2 -2
  3. package/dist/client/_nuxt/{Icon.881857b6.js → Icon.95e417ea.js} +1 -1
  4. package/dist/client/_nuxt/{entry.db5a4449.js → entry.4892d138.js} +2 -2
  5. package/dist/client/_nuxt/{error-404.1c1c2700.js → error-404.c11fbc81.js} +1 -1
  6. package/dist/client/_nuxt/{error-500.6a615525.js → error-500.9fe646ba.js} +1 -1
  7. package/dist/client/_nuxt/{error-component.834f3c34.js → error-component.f0759900.js} +2 -2
  8. package/dist/client/index.html +2 -2
  9. package/dist/module.json +1 -1
  10. package/dist/module.mjs +2 -5
  11. package/dist/runtime/nitro/providers/browser.mjs +5 -2
  12. package/dist/runtime/nitro/providers/{satori.d.ts → satori/index.d.ts} +1 -1
  13. package/dist/runtime/nitro/providers/{satori.mjs → satori/index.mjs} +15 -20
  14. package/dist/runtime/nitro/providers/satori/plugins/imageSrc.d.ts +2 -0
  15. package/dist/runtime/nitro/providers/satori/plugins/imageSrc.mjs +24 -0
  16. package/dist/runtime/nitro/providers/satori/plugins/twClasses.d.ts +2 -0
  17. package/dist/runtime/nitro/providers/satori/plugins/twClasses.mjs +9 -0
  18. package/dist/runtime/nitro/providers/satori/utils.d.ts +10 -0
  19. package/dist/runtime/nitro/providers/satori/utils.mjs +31 -0
  20. package/dist/runtime/nitro/routes/__og_image__/html.mjs +12 -0
  21. package/dist/runtime/nitro/routes/__og_image__/options.d.ts +1 -0
  22. package/dist/runtime/nitro/routes/__og_image__/options.mjs +4 -1
  23. package/dist/runtime/nitro/routes/__og_image__/vnode.d.ts +2 -0
  24. package/dist/runtime/nitro/routes/__og_image__/vnode.mjs +16 -0
  25. package/package.json +1 -1
@@ -1 +1 @@
1
- import{s as n,v as a,o as r,l,x as e,t as s,y as d,z as c,A as p,B as f,C as x,D as h}from"./entry.db5a4449.js";const m=t=>(x("data-v-18337f8d"),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)),_={class:"max-w-520px text-center z-20"},b=["textContent"],y=["textContent"],w={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 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}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=p;return r(),l("div",u,[g,e("div",_,[e("h1",{class:"text-8xl sm:text-10xl font-medium mb-8",textContent:s(t.statusCode)},null,8,b),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,y),e("div",w,[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(()=>[f(s(t.backHome),1)]),_:1})])])])}}},z=n(S,[["__scopeId","data-v-18337f8d"]]);export{z as default};
1
+ import{s as n,v as a,o as r,l,x as e,t as s,y as d,z as c,A as p,B as f,C as x,D as h}from"./entry.4892d138.js";const m=t=>(x("data-v-18337f8d"),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)),_={class:"max-w-520px text-center z-20"},b=["textContent"],y=["textContent"],w={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 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}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=p;return r(),l("div",u,[g,e("div",_,[e("h1",{class:"text-8xl sm:text-10xl font-medium mb-8",textContent:s(t.statusCode)},null,8,b),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,y),e("div",w,[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(()=>[f(s(t.backHome),1)]),_:1})])])])}}},z=n(S,[["__scopeId","data-v-18337f8d"]]);export{z as default};
@@ -1 +1 @@
1
- import{s as i,v as a,o as r,l as n,x as e,t as s,C as l,D as d}from"./entry.db5a4449.js";const c=t=>(l("data-v-428e244b"),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}'}]}),(b,u)=>(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-428e244b"]]);export{w as default};
1
+ import{s as i,v as a,o as r,l as n,x as e,t as s,C as l,D as d}from"./entry.4892d138.js";const c=t=>(l("data-v-428e244b"),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}'}]}),(b,u)=>(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-428e244b"]]);export{w as default};
@@ -1,3 +1,3 @@
1
- import{d as n,_ as o,o as _,c as f,n as g,g as E,u as r}from"./entry.db5a4449.js";const k={__name:"nuxt-error-page",props:{error:Object},setup(t){(t.error.stack||"").split(`
1
+ import{d as n,_ as o,o as _,c as f,n as g,g as E,u as r}from"./entry.4892d138.js";const k={__name:"nuxt-error-page",props:{error:Object},setup(t){(t.error.stack||"").split(`
2
2
  `).splice(1).map(e=>({text:e.replace("webpack:/","").replace(".vue",".js").trim(),internal:e.includes("node_modules")&&!e.includes(".cache")||e.includes("internal")||e.includes("new Promise")})).map(e=>`<span class="stack${e.internal?" internal":""}">${e.text}</span>`).join(`
3
- `);const s=Number(t.error.statusCode||500),a=s===404,c=t.error.statusMessage??(a?"Page Not Found":"Internal Server Error"),u=t.error.message||t.error.toString(),i=void 0,d=n(()=>o(()=>import("./error-404.1c1c2700.js"),["./error-404.1c1c2700.js","./entry.db5a4449.js","./entry.0827acf4.css","./error-404.68aa58b4.css"],import.meta.url).then(e=>e.default||e)),l=n(()=>o(()=>import("./error-500.6a615525.js"),["./error-500.6a615525.js","./entry.db5a4449.js","./entry.0827acf4.css","./error-500.dc5710d1.css"],import.meta.url).then(e=>e.default||e)),m=a?d:l;return(e,p)=>(_(),f(r(m),g(E({statusCode:r(s),statusMessage:r(c),description:r(u),stack:r(i)})),null,16))}},v=k;export{v as default};
3
+ `);const s=Number(t.error.statusCode||500),a=s===404,c=t.error.statusMessage??(a?"Page Not Found":"Internal Server Error"),u=t.error.message||t.error.toString(),i=void 0,d=n(()=>o(()=>import("./error-404.c11fbc81.js"),["./error-404.c11fbc81.js","./entry.4892d138.js","./entry.0827acf4.css","./error-404.68aa58b4.css"],import.meta.url).then(e=>e.default||e)),l=n(()=>o(()=>import("./error-500.9fe646ba.js"),["./error-500.9fe646ba.js","./entry.4892d138.js","./entry.0827acf4.css","./error-500.dc5710d1.css"],import.meta.url).then(e=>e.default||e)),m=a?d:l;return(e,p)=>(_(),f(r(m),g(E({statusCode:r(s),statusMessage:r(c),description:r(u),stack:r(i)})),null,16))}},v=k;export{v as default};
@@ -1,7 +1,7 @@
1
1
  <!DOCTYPE html>
2
2
  <html >
3
3
  <head><meta charset="utf-8">
4
- <meta name="viewport" content="width=device-width, initial-scale=1"><link rel="modulepreload" as="script" crossorigin href="/__nuxt_og_image__/client/_nuxt/entry.db5a4449.js"><link rel="preload" as="style" href="/__nuxt_og_image__/client/_nuxt/entry.0827acf4.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt_og_image__/client/_nuxt/error-component.834f3c34.js"><link rel="stylesheet" href="/__nuxt_og_image__/client/_nuxt/entry.0827acf4.css"><script>"use strict";const w=window,de=document.documentElement,knownColorSchemes=["dark","light"],preference=window.localStorage.getItem("nuxt-color-mode")||"system";let value=preference==="system"?getColorScheme():preference;const forcedColorMode=de.getAttribute("data-color-mode-forced");forcedColorMode&&(value=forcedColorMode),addColorScheme(value),w["__NUXT_COLOR_MODE__"]={preference,value,getColorScheme,addColorScheme,removeColorScheme};function addColorScheme(e){const o=""+e+"",t="";de.classList?de.classList.add(o):de.className+=" "+o,t&&de.setAttribute("data-"+t,e)}function removeColorScheme(e){const o=""+e+"",t="";de.classList?de.classList.remove(o):de.className=de.className.replace(new RegExp(o,"g"),""),t&&de.removeAttribute("data-"+t)}function prefersColorScheme(e){return w.matchMedia("(prefers-color-scheme"+e+")")}function getColorScheme(){if(w.matchMedia&&prefersColorScheme("").media!=="not all"){for(const e of knownColorSchemes)if(prefersColorScheme(":"+e).matches)return e}return"light"}
4
+ <meta name="viewport" content="width=device-width, initial-scale=1"><link rel="modulepreload" as="script" crossorigin href="/__nuxt_og_image__/client/_nuxt/entry.4892d138.js"><link rel="preload" as="style" href="/__nuxt_og_image__/client/_nuxt/entry.0827acf4.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt_og_image__/client/_nuxt/error-component.f0759900.js"><link rel="stylesheet" href="/__nuxt_og_image__/client/_nuxt/entry.0827acf4.css"><script>"use strict";const w=window,de=document.documentElement,knownColorSchemes=["dark","light"],preference=window.localStorage.getItem("nuxt-color-mode")||"system";let value=preference==="system"?getColorScheme():preference;const forcedColorMode=de.getAttribute("data-color-mode-forced");forcedColorMode&&(value=forcedColorMode),addColorScheme(value),w["__NUXT_COLOR_MODE__"]={preference,value,getColorScheme,addColorScheme,removeColorScheme};function addColorScheme(e){const o=""+e+"",t="";de.classList?de.classList.add(o):de.className+=" "+o,t&&de.setAttribute("data-"+t,e)}function removeColorScheme(e){const o=""+e+"",t="";de.classList?de.classList.remove(o):de.className=de.className.replace(new RegExp(o,"g"),""),t&&de.removeAttribute("data-"+t)}function prefersColorScheme(e){return w.matchMedia("(prefers-color-scheme"+e+")")}function getColorScheme(){if(w.matchMedia&&prefersColorScheme("").media!=="not all"){for(const e of knownColorSchemes)if(prefersColorScheme(":"+e).matches)return e}return"light"}
5
5
  </script></head>
6
- <body ><div id="__nuxt"></div><script>window.__NUXT__={serverRendered:false,config:{public:{},app:{baseURL:"\u002F__nuxt_og_image__\u002Fclient",buildAssetsDir:"\u002F_nuxt\u002F",cdnURL:""}},data:{},state:{}}</script><script type="module" src="/__nuxt_og_image__/client/_nuxt/entry.db5a4449.js" crossorigin></script></body>
6
+ <body ><div id="__nuxt"></div><script>window.__NUXT__={serverRendered:false,config:{public:{},app:{baseURL:"\u002F__nuxt_og_image__\u002Fclient",buildAssetsDir:"\u002F_nuxt\u002F",cdnURL:""}},data:{},state:{}}</script><script type="module" src="/__nuxt_og_image__/client/_nuxt/entry.4892d138.js" crossorigin></script></body>
7
7
  </html>
package/dist/module.json CHANGED
@@ -5,5 +5,5 @@
5
5
  "bridge": false
6
6
  },
7
7
  "configKey": "ogImage",
8
- "version": "1.0.0-beta.4"
8
+ "version": "1.0.0-beta.6"
9
9
  }
package/dist/module.mjs CHANGED
@@ -69,10 +69,7 @@ function exposeConfig(alias, filename, config) {
69
69
  }
70
70
  function extractOgImageOptions(html) {
71
71
  const options = html.match(/<script id="nuxt-og-image-options" type="application\/json">(.+?)<\/script>/)?.[1];
72
- if (options) {
73
- return JSON.parse(options);
74
- }
75
- return false;
72
+ return options ? JSON.parse(options) : false;
76
73
  }
77
74
  function stripOgImageOptions(html) {
78
75
  return html.replace(/<script id="nuxt-og-image-options" type="application\/json">(.*?)<\/script>/, "");
@@ -231,7 +228,7 @@ export {}
231
228
  nuxt.hooks.hook("prepare:types", ({ references }) => {
232
229
  references.push({ path: resolve(nuxt.options.buildDir, "nuxt-og-image.d.ts") });
233
230
  });
234
- ["html", "options", "svg", "og.png"].forEach((type) => {
231
+ ["html", "options", "svg", "vnode", "og.png"].forEach((type) => {
235
232
  addServerHandler({
236
233
  handler: resolve(`./runtime/nitro/routes/__og_image__/${type}`)
237
234
  });
@@ -2,8 +2,11 @@ import { screenshot } from "../../browserUtil.mjs";
2
2
  import { createBrowser } from "#nuxt-og-image/browser";
3
3
  export default {
4
4
  name: "browser",
5
- createSvg: function createSvg() {
6
- throw new Error("Browser provider isn't able to create SVGs.");
5
+ createSvg: async function createSvg() {
6
+ throw new Error("Browser provider can't create SVGs.");
7
+ },
8
+ createVNode: async function createVNode() {
9
+ throw new Error("Browser provider can't create VNodes.");
7
10
  },
8
11
  createPng: async function createPng(basePath, options) {
9
12
  const browser = await createBrowser();
@@ -1,3 +1,3 @@
1
- import type { Provider } from '../../../types';
1
+ import type { Provider } from '../../../../types';
2
2
  declare const _default: Provider;
3
3
  export default _default;
@@ -1,11 +1,10 @@
1
- import { fileURLToPath } from "node:url";
2
- import { promises as fsp } from "node:fs";
3
1
  import { html as convertHtmlToSatori } from "satori-html";
4
2
  import satori from "satori";
5
- import { parseURL, withBase } from "ufo";
3
+ import { parseURL } from "ufo";
6
4
  import { Resvg } from "@resvg/resvg-js";
7
- import { dirname, resolve } from "pathe";
8
- import { getAsset } from "#internal/nitro/virtual/public-assets";
5
+ import { parseFont, walkSatoriTree } from "./utils.mjs";
6
+ import imageSrc from "./plugins/imageSrc.mjs";
7
+ import twClasses from "./plugins/twClasses.mjs";
9
8
  import { satoriFonts, satoriOptions } from "#nuxt-og-image/config";
10
9
  export default {
11
10
  name: "satori",
@@ -15,27 +14,23 @@ export default {
15
14
  const pngData = resvg.render();
16
15
  return pngData.asPng();
17
16
  },
18
- createSvg: async function createSvg(baseUrl, options) {
17
+ createVNode: async function createVNode(baseUrl, options) {
19
18
  const url = parseURL(baseUrl);
20
19
  const html = await $fetch(url.pathname);
21
20
  const body = html.match(/<body[^>]*>([\s\S]*)<\/body>/)?.[1];
22
- const parseFont = async (font) => {
23
- if (typeof font.publicPath === "string") {
24
- const file = getAsset(font.publicPath);
25
- if (file) {
26
- const serverDir = dirname(fileURLToPath(import.meta.url));
27
- font.data = await fsp.readFile(resolve(serverDir, file.path));
28
- }
29
- if (!font.data)
30
- font.data = await (await $fetch(withBase(font.publicPath, `${url.protocol}//${url.host}`))).arrayBuffer();
31
- }
32
- return font;
33
- };
34
21
  satoriOptions.fonts = satoriOptions.fonts || [];
35
22
  for (const font of satoriFonts)
36
- satoriOptions.fonts.push(await parseFont(font));
23
+ satoriOptions.fonts.push(await parseFont(url, font));
37
24
  const satoriTree = convertHtmlToSatori(body);
38
- return await satori(satoriTree, {
25
+ await walkSatoriTree(url, satoriTree, [
26
+ twClasses(url),
27
+ imageSrc(url)
28
+ ]);
29
+ return satoriTree;
30
+ },
31
+ createSvg: async function createSvg(baseUrl, options) {
32
+ const vnodes = await this.createVNode(baseUrl, options);
33
+ return await satori(vnodes, {
39
34
  ...satoriOptions,
40
35
  width: options.width,
41
36
  height: options.height
@@ -0,0 +1,2 @@
1
+ declare const _default: (url: import("ufo").ParsedURL) => import("../../../../../types").SatoriTransformer;
2
+ export default _default;
@@ -0,0 +1,24 @@
1
+ import { fileURLToPath } from "node:url";
2
+ import { promises as fsp } from "node:fs";
3
+ import { withBase } from "ufo";
4
+ import { dirname, resolve } from "pathe";
5
+ import { defineSatoriTransformer } from "../utils.mjs";
6
+ import { getAsset } from "#internal/nitro/virtual/public-assets";
7
+ export default defineSatoriTransformer((url) => {
8
+ return {
9
+ filter: (node) => node.type === "img",
10
+ transform: async (node) => {
11
+ const src = node.props?.src;
12
+ if (src && src.startsWith("/")) {
13
+ const file = getAsset(src);
14
+ if (file) {
15
+ const serverDir = dirname(fileURLToPath(import.meta.url));
16
+ const path = resolve(serverDir, file.path);
17
+ node.props.src = `data:${file.type};base64,${await fsp.readFile(path, { encoding: "base64" })}`;
18
+ } else {
19
+ node.props.src = withBase(src, `${url.protocol}//${url.host}`);
20
+ }
21
+ }
22
+ }
23
+ };
24
+ });
@@ -0,0 +1,2 @@
1
+ declare const _default: (url: import("ufo").ParsedURL) => import("../../../../../types").SatoriTransformer;
2
+ export default _default;
@@ -0,0 +1,9 @@
1
+ import { defineSatoriTransformer } from "../utils.mjs";
2
+ export default defineSatoriTransformer(() => {
3
+ return {
4
+ filter: (node) => !!node.props?.class && !node.props?.tw,
5
+ transform: async (node) => {
6
+ node.props.tw = node.props.class;
7
+ }
8
+ };
9
+ });
@@ -0,0 +1,10 @@
1
+ import type { SatoriOptions } from 'satori';
2
+ import type { ParsedURL } from 'ufo';
3
+ import type { SatoriTransformer, VNode } from '../../../../types';
4
+ export declare function parseFont(url: ParsedURL, font: SatoriOptions['fonts'][number] & {
5
+ publicPath?: string;
6
+ }): Promise<import("satori").Font & {
7
+ publicPath?: string | undefined;
8
+ }>;
9
+ export declare function walkSatoriTree(url: ParsedURL, node: VNode, plugins: SatoriTransformer[]): Promise<void>;
10
+ export declare function defineSatoriTransformer(transformer: (url: ParsedURL) => SatoriTransformer): (url: ParsedURL) => SatoriTransformer;
@@ -0,0 +1,31 @@
1
+ import { fileURLToPath } from "node:url";
2
+ import { promises as fsp } from "node:fs";
3
+ import { dirname, resolve } from "pathe";
4
+ import { withBase } from "ufo";
5
+ import { getAsset } from "#internal/nitro/virtual/public-assets";
6
+ export async function parseFont(url, font) {
7
+ if (typeof font.publicPath === "string") {
8
+ const file = getAsset(font.publicPath);
9
+ if (file) {
10
+ const serverDir = dirname(fileURLToPath(import.meta.url));
11
+ font.data = await fsp.readFile(resolve(serverDir, file.path));
12
+ }
13
+ if (!font.data)
14
+ font.data = await (await $fetch(withBase(font.publicPath, `${url.protocol}//${url.host}`))).arrayBuffer();
15
+ }
16
+ return font;
17
+ }
18
+ export async function walkSatoriTree(url, node, plugins) {
19
+ if (!node.props?.children)
20
+ return;
21
+ for (const child of node.props.children || []) {
22
+ for (const plugin of plugins) {
23
+ if (plugin.filter(child))
24
+ await plugin.transform(child, url);
25
+ }
26
+ await walkSatoriTree(url, child, plugins);
27
+ }
28
+ }
29
+ export function defineSatoriTransformer(transformer) {
30
+ return transformer;
31
+ }
@@ -21,6 +21,18 @@ export default defineEventHandler(async (e) => {
21
21
  innerHTML: "body { font-family: 'Inter', sans-serif; }"
22
22
  }
23
23
  ],
24
+ script: [
25
+ {
26
+ src: "https://cdn.tailwindcss.com"
27
+ },
28
+ {
29
+ innerHTML: `tailwind.config = {
30
+ corePlugins: {
31
+ preflight: false,
32
+ }
33
+ }`
34
+ }
35
+ ],
24
36
  link: [
25
37
  {
26
38
  href: "https://cdn.jsdelivr.net/npm/gardevoir",
@@ -1,4 +1,5 @@
1
1
  import type { OgImageOptions } from '../../../../types';
2
+ export declare function extractOgImageOptions(html: string): any;
2
3
  export declare const inferOgImageOptions: (html: string) => OgImageOptions;
3
4
  declare const _default: import("h3").EventHandler<false | OgImageOptions | undefined>;
4
5
  export default _default;
@@ -1,8 +1,11 @@
1
1
  import { parseURL, withoutTrailingSlash } from "ufo";
2
2
  import { defineEventHandler, getQuery } from "h3";
3
- import { extractOgImageOptions } from "../../../../utils";
4
3
  import { getRouteRules } from "#internal/nitro";
5
4
  import { defaults } from "#nuxt-og-image/config";
5
+ export function extractOgImageOptions(html) {
6
+ const options = html.match(/<script id="nuxt-og-image-options" type="application\/json">(.+?)<\/script>/)?.[1];
7
+ return options ? JSON.parse(options) : false;
8
+ }
6
9
  export const inferOgImageOptions = (html) => {
7
10
  const options = {};
8
11
  const title = html.match(/<meta property="og:title" content="(.*?)">/)?.[1];
@@ -0,0 +1,2 @@
1
+ declare const _default: import("h3").EventHandler<any>;
2
+ export default _default;
@@ -0,0 +1,16 @@
1
+ import { defineEventHandler, setHeader } from "h3";
2
+ import { joinURL, parseURL, withBase, withoutTrailingSlash } from "ufo";
3
+ import { fetchOptions, useHostname } from "../../utils.mjs";
4
+ import { useProvider } from "#nuxt-og-image/provider";
5
+ export default defineEventHandler(async (e) => {
6
+ const path = parseURL(e.path).pathname;
7
+ if (!path.endsWith("__og_image__/vnode"))
8
+ return;
9
+ const basePath = withoutTrailingSlash(
10
+ path.replace("__og_image__/vnode", "")
11
+ );
12
+ const options = await fetchOptions(basePath);
13
+ setHeader(e, "Content-Type", "application/json");
14
+ const provider = await useProvider(options.provider);
15
+ return provider.createVNode(withBase(joinURL(basePath, "/__og_image__/html"), useHostname(e)), options);
16
+ });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nuxt-og-image",
3
3
  "type": "module",
4
- "version": "1.0.0-beta.4",
4
+ "version": "1.0.0-beta.6",
5
5
  "packageManager": "pnpm@7.8.0",
6
6
  "license": "MIT",
7
7
  "funding": "https://github.com/sponsors/harlan-zw",