nuxt-og-image 2.2.4 → 3.0.0-beta.1
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/README.md +2 -2
- package/dist/client/200.html +8 -8
- package/dist/client/404.html +8 -8
- package/dist/client/_nuxt/IconCSS.8f429b14.css +1 -0
- package/dist/client/_nuxt/IconCSS.ac398b56.js +1 -0
- package/dist/client/_nuxt/builds/latest.json +1 -1
- package/dist/client/_nuxt/builds/meta/d1d517c3-4927-4803-bbb0-d94e9d3e9581.json +1 -0
- package/dist/client/_nuxt/entry.434c2c45.css +1 -0
- package/dist/client/_nuxt/entry.bdb8a8d5.js +137 -0
- package/dist/client/_nuxt/{error-404.407d76a3.js → error-404.f37119e7.js} +1 -1
- package/dist/client/_nuxt/{error-500.531c4147.js → error-500.74b0a30f.js} +1 -1
- package/dist/client/grid.png +0 -0
- package/dist/client/index.html +8 -8
- package/dist/module.d.mts +43 -39
- package/dist/module.d.ts +43 -39
- package/dist/module.json +1 -1
- package/dist/module.mjs +341 -667
- package/dist/runtime/cache.d.ts +4 -4
- package/dist/runtime/cache.mjs +2 -1
- package/dist/runtime/components/OgImage/Cached.mjs +1 -1
- package/dist/runtime/components/OgImage/Dynamic.mjs +1 -1
- package/dist/runtime/components/OgImage/Screenshot.mjs +1 -1
- package/dist/runtime/components/OgImage/Static.mjs +1 -1
- package/dist/runtime/components/OgImage/WithoutCache.mjs +1 -1
- package/dist/runtime/components/OgImage/index.mjs +1 -1
- package/dist/runtime/components/Templates/Community/Nuxt.vue +183 -0
- package/dist/runtime/components/Templates/Official/BrandedLogo.vue +28 -0
- package/dist/runtime/components/Templates/Official/Fallback.vue +147 -0
- package/dist/runtime/components/Templates/Official/SimpleBlog.vue +33 -0
- package/dist/runtime/components/Templates/Official/Wave.vue +33 -0
- package/dist/runtime/components/Templates/Official/WithEmoji.vue +27 -0
- package/dist/runtime/composables/defineOgImage.d.ts +10 -6
- package/dist/runtime/composables/defineOgImage.mjs +21 -9
- package/dist/runtime/core/bindings/chromium/node.d.ts +2 -0
- package/dist/runtime/{nitro/providers/browser/universal.mjs → core/bindings/chromium/node.mjs} +3 -3
- package/dist/runtime/core/bindings/resvg/node.d.ts +6 -0
- package/dist/runtime/core/bindings/resvg/node.mjs +5 -0
- package/dist/runtime/core/bindings/resvg/wasm.d.ts +40 -0
- package/dist/runtime/core/bindings/resvg/wasm.mjs +7 -0
- package/dist/runtime/core/bindings/satori/node.d.ts +6 -0
- package/dist/runtime/core/bindings/satori/node.mjs +5 -0
- package/dist/runtime/core/bindings/satori/yoga-wasm.d.ts +6 -0
- package/dist/runtime/core/bindings/satori/yoga-wasm.mjs +7 -0
- package/dist/runtime/core/bindings/sharp/node.d.ts +2 -0
- package/dist/runtime/core/bindings/sharp/node.mjs +2 -0
- package/dist/runtime/core/bindings/sharp/wasm.d.ts +2 -0
- package/dist/runtime/core/bindings/sharp/wasm.mjs +2 -0
- package/dist/runtime/core/cache/prerender.d.ts +6 -0
- package/dist/runtime/core/cache/prerender.mjs +6 -0
- package/dist/runtime/core/env/assets.d.ts +2 -0
- package/dist/runtime/core/env/assets.mjs +15 -0
- package/dist/runtime/core/font/cache.d.ts +1 -0
- package/dist/runtime/core/font/cache.mjs +1 -0
- package/dist/runtime/core/font/fetch.d.ts +3 -0
- package/dist/runtime/core/font/fetch.mjs +29 -0
- package/dist/runtime/core/html/fetch.d.ts +3 -0
- package/dist/runtime/core/html/fetch.mjs +117 -0
- package/dist/runtime/core/options/extract.d.ts +3 -0
- package/dist/runtime/{nitro/utils-pure.mjs → core/options/extract.mjs} +23 -21
- package/dist/runtime/core/options/fetch.d.ts +3 -0
- package/dist/runtime/core/options/fetch.mjs +21 -0
- package/dist/runtime/core/options/normalise.d.ts +2 -0
- package/dist/runtime/{composables/util.mjs → core/options/normalise.mjs} +9 -6
- package/dist/runtime/core/renderers/chromium/index.d.ts +3 -0
- package/dist/runtime/core/renderers/chromium/index.mjs +26 -0
- package/dist/runtime/core/renderers/chromium/screenshot.d.ts +6 -0
- package/dist/runtime/core/renderers/chromium/screenshot.mjs +47 -0
- package/dist/runtime/core/renderers/satori/fonts.d.ts +3 -0
- package/dist/runtime/core/renderers/satori/fonts.mjs +8 -0
- package/dist/runtime/core/renderers/satori/index.d.ts +5 -0
- package/dist/runtime/core/renderers/satori/index.mjs +53 -0
- package/dist/runtime/core/renderers/satori/instances.d.ts +39 -0
- package/dist/runtime/core/renderers/satori/instances.mjs +17 -0
- package/dist/runtime/{nitro → core}/renderers/satori/plugins/encoding.mjs +1 -1
- package/dist/runtime/{nitro → core}/renderers/satori/plugins/imageSrc.mjs +9 -14
- package/dist/runtime/{nitro → core}/renderers/satori/plugins/twClasses.mjs +1 -0
- package/dist/runtime/core/renderers/satori/utils.d.ts +4 -0
- package/dist/runtime/core/renderers/satori/utils.mjs +20 -0
- package/dist/runtime/core/renderers/satori/vnodes.d.ts +3 -0
- package/dist/runtime/core/renderers/satori/vnodes.mjs +21 -0
- package/dist/runtime/core/utils/resolveRendererContext.d.ts +7 -0
- package/dist/runtime/core/utils/resolveRendererContext.mjs +76 -0
- package/dist/runtime/nitro/plugins/nuxt-content.d.ts +2 -0
- package/dist/runtime/nitro/plugins/nuxt-content.mjs +50 -0
- package/dist/runtime/nitro/plugins/prerender.d.ts +2 -3
- package/dist/runtime/nitro/plugins/prerender.mjs +25 -33
- package/dist/runtime/nuxt/plugins/nuxt-content-canonical-urls.mjs +29 -0
- package/dist/runtime/nuxt/plugins/route-rule-og-image.server.d.ts +2 -0
- package/dist/runtime/nuxt/plugins/route-rule-og-image.server.mjs +72 -0
- package/dist/runtime/{nitro/routes/debug.d.ts → server/routes/__og-image__/debug.json.d.ts} +1 -1
- package/dist/runtime/{nitro/routes/debug.mjs → server/routes/__og-image__/debug.json.mjs} +3 -2
- package/dist/runtime/server/routes/__og-image__/font-[name]-[weight].[extension].mjs +30 -0
- package/dist/runtime/server/routes/__og-image__/image-[path]-og.[extension].mjs +44 -0
- package/dist/runtime/types.d.ts +29 -24
- package/dist/runtime/utilts.d.ts +2 -0
- package/dist/runtime/utilts.mjs +8 -0
- package/dist/types.d.mts +3 -2
- package/dist/types.d.ts +3 -2
- package/package.json +37 -22
- package/dist/client/_nuxt/IconCSS.4a9d43d0.css +0 -1
- package/dist/client/_nuxt/IconCSS.9c30257a.js +0 -1
- package/dist/client/_nuxt/ImageLoader.752b0c7a.js +0 -1
- package/dist/client/_nuxt/ImageLoader.7571516f.css +0 -1
- package/dist/client/_nuxt/builds/meta/bb64bb30-cf6f-4625-97ba-06e6a0d3f8d1.json +0 -1
- package/dist/client/_nuxt/entry.39e39f51.css +0 -1
- package/dist/client/_nuxt/entry.ac864471.js +0 -135
- package/dist/client/_nuxt/index.dc1538d5.js +0 -1
- package/dist/client/_nuxt/index.ffbea0a9.css +0 -1
- package/dist/client/_nuxt/options.a77f5921.js +0 -1
- package/dist/client/_nuxt/png.41e0b446.js +0 -1
- package/dist/client/_nuxt/shiki.d4e62362.js +0 -7
- package/dist/client/_nuxt/svg.b8198280.js +0 -1
- package/dist/client/_nuxt/vnodes.67720126.js +0 -1
- package/dist/client/options/index.html +0 -15
- package/dist/client/png/index.html +0 -15
- package/dist/client/svg/index.html +0 -15
- package/dist/client/vnodes/index.html +0 -15
- package/dist/runtime/browserUtil.d.ts +0 -5
- package/dist/runtime/browserUtil.mjs +0 -41
- package/dist/runtime/components/OgImageTemplate/Fallback.vue +0 -161
- package/dist/runtime/composables/util.d.ts +0 -2
- package/dist/runtime/nitro/middleware/og.png.mjs +0 -69
- package/dist/runtime/nitro/middleware/playground.d.ts +0 -2
- package/dist/runtime/nitro/middleware/playground.mjs +0 -27
- package/dist/runtime/nitro/providers/browser/lambda.d.ts +0 -1
- package/dist/runtime/nitro/providers/browser/lambda.mjs +0 -9
- package/dist/runtime/nitro/providers/browser/playwright.d.ts +0 -1
- package/dist/runtime/nitro/providers/browser/playwright.mjs +0 -22
- package/dist/runtime/nitro/providers/browser/universal.d.ts +0 -2
- package/dist/runtime/nitro/providers/png/resvg-node.d.ts +0 -4
- package/dist/runtime/nitro/providers/png/resvg-node.mjs +0 -6
- package/dist/runtime/nitro/providers/png/resvg-wasm.d.ts +0 -3
- package/dist/runtime/nitro/providers/png/resvg-wasm.mjs +0 -11
- package/dist/runtime/nitro/providers/png/svg2png.d.ts +0 -3
- package/dist/runtime/nitro/providers/png/svg2png.mjs +0 -11
- package/dist/runtime/nitro/providers/satori/default.d.ts +0 -2
- package/dist/runtime/nitro/providers/satori/default.mjs +0 -4
- package/dist/runtime/nitro/providers/satori/yoga-wasm.d.ts +0 -3
- package/dist/runtime/nitro/providers/satori/yoga-wasm.mjs +0 -10
- package/dist/runtime/nitro/renderers/browser.d.ts +0 -3
- package/dist/runtime/nitro/renderers/browser.mjs +0 -36
- package/dist/runtime/nitro/renderers/satori/index.d.ts +0 -3
- package/dist/runtime/nitro/renderers/satori/index.mjs +0 -58
- package/dist/runtime/nitro/renderers/satori/utils.d.ts +0 -4
- package/dist/runtime/nitro/renderers/satori/utils.mjs +0 -60
- package/dist/runtime/nitro/routes/font.mjs +0 -22
- package/dist/runtime/nitro/routes/html.d.ts +0 -2
- package/dist/runtime/nitro/routes/html.mjs +0 -178
- package/dist/runtime/nitro/routes/options.d.ts +0 -3
- package/dist/runtime/nitro/routes/options.mjs +0 -35
- package/dist/runtime/nitro/routes/svg.mjs +0 -19
- package/dist/runtime/nitro/routes/vnode.d.ts +0 -2
- package/dist/runtime/nitro/routes/vnode.mjs +0 -19
- package/dist/runtime/nitro/utils-pure.d.ts +0 -3
- package/dist/runtime/nitro/utils.d.ts +0 -18
- package/dist/runtime/nitro/utils.mjs +0 -108
- package/dist/runtime/public-assets-optional/resvg/resvg.wasm +0 -0
- package/dist/runtime/public-assets-optional/svg2png/svg2png.wasm +0 -0
- package/dist/runtime/public-assets-optional/yoga/yoga.wasm +0 -0
- /package/dist/runtime/{nitro/providers → core/bindings}/css-inline/mock.d.ts +0 -0
- /package/dist/runtime/{nitro/providers → core/bindings}/css-inline/mock.mjs +0 -0
- /package/dist/runtime/{nitro/providers/css-inline/css-inline.d.ts → core/bindings/css-inline/node.d.ts} +0 -0
- /package/dist/runtime/{nitro/providers/css-inline/css-inline.mjs → core/bindings/css-inline/node.mjs} +0 -0
- /package/dist/runtime/{nitro → core}/renderers/satori/plugins/emojis.d.ts +0 -0
- /package/dist/runtime/{nitro → core}/renderers/satori/plugins/emojis.mjs +0 -0
- /package/dist/runtime/{nitro → core}/renderers/satori/plugins/encoding.d.ts +0 -0
- /package/dist/runtime/{nitro → core}/renderers/satori/plugins/flex.d.ts +0 -0
- /package/dist/runtime/{nitro → core}/renderers/satori/plugins/flex.mjs +0 -0
- /package/dist/runtime/{nitro → core}/renderers/satori/plugins/imageSrc.d.ts +0 -0
- /package/dist/runtime/{nitro → core}/renderers/satori/plugins/twClasses.d.ts +0 -0
- /package/dist/runtime/{nitro/routes/font.d.ts → nuxt/plugins/nuxt-content-canonical-urls.d.ts} +0 -0
- /package/dist/runtime/{nitro/middleware/og.png.d.ts → server/routes/__og-image__/font-[name]-[weight].[extension].d.ts} +0 -0
- /package/dist/runtime/{nitro/routes/svg.d.ts → server/routes/__og-image__/image-[path]-og.[extension].d.ts} +0 -0
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import { computed, resolveComponent } from 'vue'
|
|
3
|
-
import { useSiteConfig } from '#imports'
|
|
4
|
-
|
|
5
|
-
// inherited attrs can mess up the satori parser
|
|
6
|
-
defineOptions({
|
|
7
|
-
inheritAttrs: false,
|
|
8
|
-
})
|
|
9
|
-
|
|
10
|
-
const props = defineProps({
|
|
11
|
-
path: String,
|
|
12
|
-
title: {
|
|
13
|
-
type: String,
|
|
14
|
-
default: 'Og Image Template',
|
|
15
|
-
},
|
|
16
|
-
description: {
|
|
17
|
-
type: String,
|
|
18
|
-
default: 'Set a description to change me.',
|
|
19
|
-
},
|
|
20
|
-
color: {
|
|
21
|
-
type: String,
|
|
22
|
-
},
|
|
23
|
-
padding: {
|
|
24
|
-
type: String,
|
|
25
|
-
default: '0 100px',
|
|
26
|
-
},
|
|
27
|
-
titleFontSize: {
|
|
28
|
-
type: String,
|
|
29
|
-
default: '75px',
|
|
30
|
-
},
|
|
31
|
-
descriptionFontSize: {
|
|
32
|
-
type: String,
|
|
33
|
-
default: '35px',
|
|
34
|
-
},
|
|
35
|
-
icon: {
|
|
36
|
-
type: [String, Boolean],
|
|
37
|
-
default: false,
|
|
38
|
-
},
|
|
39
|
-
siteName: {
|
|
40
|
-
type: String,
|
|
41
|
-
required: false,
|
|
42
|
-
},
|
|
43
|
-
siteLogo: {
|
|
44
|
-
type: String,
|
|
45
|
-
required: false,
|
|
46
|
-
},
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
const backgroundAttrs = computed(() => {
|
|
50
|
-
// we want to make a
|
|
51
|
-
// const isBackgroundTw = props.background?.startsWith('bg-')
|
|
52
|
-
return {
|
|
53
|
-
style: {
|
|
54
|
-
display: 'flex',
|
|
55
|
-
position: 'absolute',
|
|
56
|
-
width: '100%',
|
|
57
|
-
height: '100%',
|
|
58
|
-
background: 'rgba(5, 5, 5,1)',
|
|
59
|
-
},
|
|
60
|
-
}
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
const backgroundFlareAttrs = computed(() => {
|
|
64
|
-
// we want to make a
|
|
65
|
-
// const isBackgroundTw = props.background?.startsWith('bg-')
|
|
66
|
-
return {
|
|
67
|
-
style: {
|
|
68
|
-
display: 'flex',
|
|
69
|
-
position: 'absolute',
|
|
70
|
-
right: '-100%',
|
|
71
|
-
top: '10%',
|
|
72
|
-
width: '200%',
|
|
73
|
-
height: '200%',
|
|
74
|
-
backgroundImage: 'radial-gradient(circle, rgba(0,220,130, 0.5) 0%, rgba(5, 5, 5,0.3) 50%, rgba(5, 5, 5,0) 70%)',
|
|
75
|
-
},
|
|
76
|
-
}
|
|
77
|
-
})
|
|
78
|
-
|
|
79
|
-
const containerAttrs = computed(() => {
|
|
80
|
-
const isColorTw = props.color?.startsWith('text-')
|
|
81
|
-
|
|
82
|
-
const classes = [
|
|
83
|
-
'w-full',
|
|
84
|
-
'h-full',
|
|
85
|
-
'flex',
|
|
86
|
-
'text-gray-100',
|
|
87
|
-
'relative',
|
|
88
|
-
'items-center',
|
|
89
|
-
'justify-center',
|
|
90
|
-
]
|
|
91
|
-
const styles: Record<string, any> = {
|
|
92
|
-
padding: props.padding,
|
|
93
|
-
}
|
|
94
|
-
if (isColorTw)
|
|
95
|
-
classes.push(props.color)
|
|
96
|
-
else
|
|
97
|
-
styles.color = props.color
|
|
98
|
-
return { class: classes, style: styles }
|
|
99
|
-
})
|
|
100
|
-
|
|
101
|
-
const titleAttrs = computed(() => {
|
|
102
|
-
const classes = []
|
|
103
|
-
const styles = {
|
|
104
|
-
fontWeight: 'bold',
|
|
105
|
-
marginBottom: '50px',
|
|
106
|
-
fontSize: props.titleFontSize,
|
|
107
|
-
}
|
|
108
|
-
return { class: classes, style: styles }
|
|
109
|
-
})
|
|
110
|
-
|
|
111
|
-
const descriptionAttrs = computed(() => {
|
|
112
|
-
const classes = []
|
|
113
|
-
const styles = {
|
|
114
|
-
fontSize: props.descriptionFontSize,
|
|
115
|
-
lineHeight: `${props.descriptionFontSize.replace('px', '') * 1.5}px`,
|
|
116
|
-
opacity: '0.8',
|
|
117
|
-
}
|
|
118
|
-
return { class: classes, style: styles }
|
|
119
|
-
})
|
|
120
|
-
|
|
121
|
-
const siteConfig = useSiteConfig()
|
|
122
|
-
const siteName = computed(() => {
|
|
123
|
-
return props.siteName || siteConfig.name
|
|
124
|
-
})
|
|
125
|
-
const siteLogo = computed(() => {
|
|
126
|
-
return props.siteLogo || siteConfig.logo
|
|
127
|
-
})
|
|
128
|
-
|
|
129
|
-
const MaybeIconComponent = resolveComponent('Icon')
|
|
130
|
-
if (typeof props.icon === 'string' && typeof MaybeIconComponent === 'string' && process.dev) {
|
|
131
|
-
console.warn('Please install `nuxt-icon` to use icons with the fallback OG Image component.')
|
|
132
|
-
// eslint-disable-next-line no-console
|
|
133
|
-
console.log('npm add -D nuxt-icon')
|
|
134
|
-
}
|
|
135
|
-
</script>
|
|
136
|
-
|
|
137
|
-
<template>
|
|
138
|
-
<div v-bind="backgroundAttrs" />
|
|
139
|
-
<div v-bind="backgroundFlareAttrs" />
|
|
140
|
-
<div v-bind="containerAttrs">
|
|
141
|
-
<div class="flex flex-row justify-between items-center" style="margin-bottom: 100px;">
|
|
142
|
-
<div class="flex flex-col w-full" :style="icon ? { width: '65%' } : {}">
|
|
143
|
-
<div v-bind="titleAttrs">
|
|
144
|
-
{{ title || 'Null Title' }}
|
|
145
|
-
</div>
|
|
146
|
-
<div v-if="description" v-bind="descriptionAttrs">
|
|
147
|
-
{{ description }}
|
|
148
|
-
</div>
|
|
149
|
-
</div>
|
|
150
|
-
<div v-if="typeof icon === 'string' && typeof MaybeIconComponent !== 'string'" style="width: 30%;" class="flex justify-end">
|
|
151
|
-
<MaybeIconComponent :name="icon" size="250px" style="margin: 0 auto 0 100px;opacity: 0.9;" />
|
|
152
|
-
</div>
|
|
153
|
-
</div>
|
|
154
|
-
<div class="flex flex-row absolute bottom-10 text-left items-start">
|
|
155
|
-
<img v-if="siteLogo" :src="siteLogo" height="30">
|
|
156
|
-
<div v-else-if="siteName" style="font-size: 25px;" class="font-bold">
|
|
157
|
-
{{ siteName }}
|
|
158
|
-
</div>
|
|
159
|
-
</div>
|
|
160
|
-
</div>
|
|
161
|
-
</template>
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import { Buffer } from "node:buffer";
|
|
2
|
-
import { createError, defineEventHandler, sendRedirect, setHeader } from "h3";
|
|
3
|
-
import { joinURL, parseURL, withoutLeadingSlash, withoutTrailingSlash } from "ufo";
|
|
4
|
-
import { hash } from "ohash";
|
|
5
|
-
import { fetchOptionsCached } from "../utils.mjs";
|
|
6
|
-
import { useNitroCache } from "../../cache.mjs";
|
|
7
|
-
import { useProvider } from "#nuxt-og-image/provider";
|
|
8
|
-
import { useNitroOrigin, useRuntimeConfig } from "#imports";
|
|
9
|
-
export default defineEventHandler(async (e) => {
|
|
10
|
-
const { runtimeBrowser } = useRuntimeConfig()["nuxt-og-image"];
|
|
11
|
-
const path = parseURL(e.path).pathname;
|
|
12
|
-
if (!path.endsWith("__og_image__/og.png"))
|
|
13
|
-
return;
|
|
14
|
-
const basePath = withoutTrailingSlash(
|
|
15
|
-
path.replace("__og_image__/og.png", "")
|
|
16
|
-
);
|
|
17
|
-
const options = await fetchOptionsCached(e, basePath);
|
|
18
|
-
if (process.env.NODE_ENV === "production" && !process.env.prerender && !runtimeBrowser && options.provider === "browser")
|
|
19
|
-
return sendRedirect(e, joinURL(useNitroOrigin(e), "__nuxt_og_image__/browser-provider-not-supported.png"));
|
|
20
|
-
const provider = await useProvider(options.provider);
|
|
21
|
-
if (!provider) {
|
|
22
|
-
throw createError({
|
|
23
|
-
statusCode: 500,
|
|
24
|
-
statusMessage: `Provider ${options.provider} is missing.`
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
const key = [
|
|
28
|
-
withoutLeadingSlash(options.path === "/" || !options.path ? "index" : options.path).replaceAll("/", "-"),
|
|
29
|
-
`og-${hash(options)}`
|
|
30
|
-
].join(":");
|
|
31
|
-
const { enabled: cacheEnabled, cachedItem, update } = await useNitroCache(e, "nuxt-og-image", {
|
|
32
|
-
key,
|
|
33
|
-
cacheTtl: options.cacheTtl || 0,
|
|
34
|
-
cache: !process.dev && options.cache,
|
|
35
|
-
headers: true
|
|
36
|
-
});
|
|
37
|
-
let png;
|
|
38
|
-
if (cachedItem)
|
|
39
|
-
png = Buffer.from(cachedItem, "base64");
|
|
40
|
-
if (!png) {
|
|
41
|
-
try {
|
|
42
|
-
png = await provider.createPng(options);
|
|
43
|
-
if (png) {
|
|
44
|
-
const base64png = Buffer.from(png).toString("base64");
|
|
45
|
-
await update(base64png);
|
|
46
|
-
}
|
|
47
|
-
} catch (err) {
|
|
48
|
-
throw createError({
|
|
49
|
-
statusCode: 500,
|
|
50
|
-
statusMessage: `Failed to create og image: ${err.message}`
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
if (png) {
|
|
55
|
-
if (cacheEnabled && options.cacheTtl) {
|
|
56
|
-
setHeader(e, "Cache-Control", `public, max-age=${Math.round(options.cacheTtl / 1e3)}`);
|
|
57
|
-
} else {
|
|
58
|
-
setHeader(e, "Cache-Control", "no-cache, no-store, must-revalidate");
|
|
59
|
-
setHeader(e, "Pragma", "no-cache");
|
|
60
|
-
setHeader(e, "Expires", "0");
|
|
61
|
-
}
|
|
62
|
-
setHeader(e, "Content-Type", "image/png");
|
|
63
|
-
return png;
|
|
64
|
-
}
|
|
65
|
-
throw createError({
|
|
66
|
-
statusCode: 500,
|
|
67
|
-
statusMessage: "Failed to create og image, unknown error."
|
|
68
|
-
});
|
|
69
|
-
});
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { defineEventHandler } from "h3";
|
|
2
|
-
import { parseURL, withBase, withoutTrailingSlash } from "ufo";
|
|
3
|
-
import { fetchOptionsCached } from "../utils.mjs";
|
|
4
|
-
import { useRuntimeConfig } from "#imports";
|
|
5
|
-
export default defineEventHandler(async (e) => {
|
|
6
|
-
const path = withoutTrailingSlash(parseURL(e.path).pathname);
|
|
7
|
-
if (!path.endsWith("/__og_image__"))
|
|
8
|
-
return;
|
|
9
|
-
const basePath = withBase(path.replace("/__og_image__", ""), useRuntimeConfig().app.baseURL);
|
|
10
|
-
const options = await fetchOptionsCached(e, basePath === "" ? "/" : basePath);
|
|
11
|
-
if (!options)
|
|
12
|
-
return `The route ${basePath} has not been set up for og:image generation.`;
|
|
13
|
-
return `
|
|
14
|
-
<style>
|
|
15
|
-
body {
|
|
16
|
-
margin: 0;
|
|
17
|
-
padding: 0;
|
|
18
|
-
}
|
|
19
|
-
iframe {
|
|
20
|
-
border: none;
|
|
21
|
-
width: 100%;
|
|
22
|
-
height: 100%;
|
|
23
|
-
}
|
|
24
|
-
</style>
|
|
25
|
-
<title>OG Image Playground</title>
|
|
26
|
-
<iframe src="/__nuxt_og_image__/client?&path=${basePath}&base=${useRuntimeConfig().app.baseURL}"></iframe>`;
|
|
27
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export default function createBrowser(): Promise<any>;
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import edgeChromium from "@sparticuz/chrome-aws-lambda";
|
|
2
|
-
import puppeteer from "puppeteer-core";
|
|
3
|
-
export default async function createBrowser() {
|
|
4
|
-
return await puppeteer.launch({
|
|
5
|
-
executablePath: await edgeChromium.executablePath,
|
|
6
|
-
args: edgeChromium.args,
|
|
7
|
-
headless: true
|
|
8
|
-
});
|
|
9
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export default function createBrowser(): Promise<any>;
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import playwrightCore from "playwright-core";
|
|
2
|
-
export default async function createBrowser() {
|
|
3
|
-
try {
|
|
4
|
-
return await playwrightCore.chromium.launch({
|
|
5
|
-
headless: true
|
|
6
|
-
});
|
|
7
|
-
} catch (e) {
|
|
8
|
-
}
|
|
9
|
-
try {
|
|
10
|
-
const playwright = await import(String("playwright"));
|
|
11
|
-
return await playwright.chromium.launch({
|
|
12
|
-
headless: true
|
|
13
|
-
});
|
|
14
|
-
} catch (e) {
|
|
15
|
-
if (process.dev) {
|
|
16
|
-
console.warn("Failed to load chromium instance. Ensure you have chrome installed, otherwise add the dependency: `npm add -D playwright`.");
|
|
17
|
-
} else {
|
|
18
|
-
console.error("Failed to load browser instance. Please open an issue with the exception: https://github.com/harlan-zw/nuxt-og-image/issues.");
|
|
19
|
-
throw e;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { Resvg, initWasm } from "@resvg/resvg-wasm";
|
|
2
|
-
import { wasmLoader } from "../../utils.mjs";
|
|
3
|
-
const ReSvgLoader = wasmLoader("/* NUXT_OG_IMAGE_RESVG_WASM */", "/resvg.wasm");
|
|
4
|
-
export default async function(svg, options) {
|
|
5
|
-
const ReSvgWasm = await ReSvgLoader.load(options);
|
|
6
|
-
await initWasm(ReSvgWasm).catch(() => {
|
|
7
|
-
});
|
|
8
|
-
const resvgJS = new Resvg(svg, options);
|
|
9
|
-
const pngData = resvgJS.render();
|
|
10
|
-
return pngData.asPng();
|
|
11
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { initialize, svg2png } from "svg2png-wasm";
|
|
2
|
-
import { wasmLoader } from "../../utils.mjs";
|
|
3
|
-
const Svg2PngLoader = wasmLoader("/* NUXT_OG_IMAGE_SVG2PNG_WASM */", "/svg2png.wasm");
|
|
4
|
-
export default async function(svg, options) {
|
|
5
|
-
const Svg2PngWasm = await Svg2PngLoader.load(options);
|
|
6
|
-
await initialize(Svg2PngWasm).catch((e) => {
|
|
7
|
-
if (!e.message.trim().endsWith("function can be used only once."))
|
|
8
|
-
throw e;
|
|
9
|
-
});
|
|
10
|
-
return await svg2png(svg, options);
|
|
11
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import satori, { init } from "satori/wasm";
|
|
2
|
-
import initYoga from "yoga-wasm-web";
|
|
3
|
-
import { wasmLoader } from "../../utils.mjs";
|
|
4
|
-
const YogaLoader = wasmLoader("/* NUXT_OG_IMAGE_YOGA_WASM */", "/yoga.wasm");
|
|
5
|
-
export default async function(nodes, options) {
|
|
6
|
-
const yogaWasm = await YogaLoader.load(options);
|
|
7
|
-
const yoga = await initYoga(yogaWasm);
|
|
8
|
-
init(yoga);
|
|
9
|
-
return await satori(nodes, options);
|
|
10
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { screenshot } from "../../browserUtil.mjs";
|
|
2
|
-
import loadBrowserLauncherChunk from "#nuxt-og-image/browser";
|
|
3
|
-
const BrowserRenderer = {
|
|
4
|
-
name: "browser",
|
|
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.");
|
|
10
|
-
},
|
|
11
|
-
createPng: async function createPng(options) {
|
|
12
|
-
const launchBrowser = await loadBrowserLauncherChunk();
|
|
13
|
-
if (!launchBrowser) {
|
|
14
|
-
throw new Error("Failed to load browser. Is the `browserProvider` enabled?");
|
|
15
|
-
}
|
|
16
|
-
const browser = await launchBrowser();
|
|
17
|
-
let res = null;
|
|
18
|
-
if (browser) {
|
|
19
|
-
try {
|
|
20
|
-
if (options.html) {
|
|
21
|
-
res = await screenshot(browser, options);
|
|
22
|
-
} else {
|
|
23
|
-
res = await screenshot(browser, {
|
|
24
|
-
...options,
|
|
25
|
-
host: options.requestOrigin,
|
|
26
|
-
path: `/api/og-image-html?path=${options.path}`
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
} finally {
|
|
30
|
-
await browser.close();
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
return res;
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
export default BrowserRenderer;
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { html as convertHtmlToSatori } from "satori-html";
|
|
2
|
-
import { loadFont, walkSatoriTree } from "./utils.mjs";
|
|
3
|
-
import imageSrc from "./plugins/imageSrc.mjs";
|
|
4
|
-
import twClasses from "./plugins/twClasses.mjs";
|
|
5
|
-
import flex from "./plugins/flex.mjs";
|
|
6
|
-
import emojis from "./plugins/emojis.mjs";
|
|
7
|
-
import encoding from "./plugins/encoding.mjs";
|
|
8
|
-
import loadPngCreator from "#nuxt-og-image/png";
|
|
9
|
-
import loadSatori from "#nuxt-og-image/satori";
|
|
10
|
-
import { useRuntimeConfig } from "#imports";
|
|
11
|
-
const satoriFonts = [];
|
|
12
|
-
let fontLoadPromise = null;
|
|
13
|
-
function loadFonts(baseURL, fonts) {
|
|
14
|
-
if (fontLoadPromise)
|
|
15
|
-
return fontLoadPromise;
|
|
16
|
-
return fontLoadPromise = Promise.all(fonts.map((font) => loadFont(baseURL, font)));
|
|
17
|
-
}
|
|
18
|
-
const SatoriRenderer = {
|
|
19
|
-
name: "satori",
|
|
20
|
-
createPng: async function createPng(options) {
|
|
21
|
-
const svg = await this.createSvg(options);
|
|
22
|
-
const pngCreator = await loadPngCreator();
|
|
23
|
-
return pngCreator(svg, options);
|
|
24
|
-
},
|
|
25
|
-
createVNode: async function createVNode(options) {
|
|
26
|
-
const html = options.html || await globalThis.$fetch("/api/og-image-html", {
|
|
27
|
-
params: {
|
|
28
|
-
path: options.path,
|
|
29
|
-
options: JSON.stringify(options)
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
|
-
const body = html.match(/<body[^>]*>([\s\S]*)<\/body>/)?.[1] || html;
|
|
33
|
-
const satoriTree = convertHtmlToSatori(body);
|
|
34
|
-
await walkSatoriTree(satoriTree, [
|
|
35
|
-
emojis,
|
|
36
|
-
twClasses,
|
|
37
|
-
imageSrc,
|
|
38
|
-
flex,
|
|
39
|
-
encoding
|
|
40
|
-
], options);
|
|
41
|
-
return satoriTree;
|
|
42
|
-
},
|
|
43
|
-
createSvg: async function createSvg(options) {
|
|
44
|
-
const { fonts, satoriOptions } = useRuntimeConfig()["nuxt-og-image"];
|
|
45
|
-
const vnodes = await this.createVNode(options);
|
|
46
|
-
if (!satoriFonts.length)
|
|
47
|
-
satoriFonts.push(...await loadFonts(options.requestOrigin, fonts));
|
|
48
|
-
const satori = await loadSatori();
|
|
49
|
-
return await satori(vnodes, {
|
|
50
|
-
...satoriOptions,
|
|
51
|
-
fonts: satoriFonts,
|
|
52
|
-
embedFont: true,
|
|
53
|
-
width: options.width,
|
|
54
|
-
height: options.height
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
export default SatoriRenderer;
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import type { FontConfig, RuntimeOgImageOptions, SatoriTransformer, VNode } from '../../../types';
|
|
2
|
-
export declare function loadFont(requestOrigin: string, font: FontConfig): Promise<any>;
|
|
3
|
-
export declare function walkSatoriTree(node: VNode, plugins: (SatoriTransformer | SatoriTransformer[])[], props: RuntimeOgImageOptions): Promise<void>;
|
|
4
|
-
export declare function defineSatoriTransformer(transformer: SatoriTransformer | SatoriTransformer[]): SatoriTransformer | SatoriTransformer[];
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { Buffer } from "node:buffer";
|
|
2
|
-
import { base64ToArrayBuffer, readPublicAsset } from "../../utils.mjs";
|
|
3
|
-
import { useStorage } from "#imports";
|
|
4
|
-
const cachedFonts = {};
|
|
5
|
-
export async function loadFont(requestOrigin, font) {
|
|
6
|
-
const fontKey = `${font.name}:${font.weight}`;
|
|
7
|
-
const storageKey = `assets:nuxt-og-image:font:${fontKey}`;
|
|
8
|
-
if (cachedFonts[fontKey])
|
|
9
|
-
return cachedFonts[fontKey];
|
|
10
|
-
const [name, weight] = fontKey.split(":");
|
|
11
|
-
let data;
|
|
12
|
-
if (await useStorage().hasItem(storageKey))
|
|
13
|
-
data = base64ToArrayBuffer(await useStorage().getItem(storageKey));
|
|
14
|
-
if (!data && name === "Inter" && ["400", "700"].includes(weight)) {
|
|
15
|
-
data = await readPublicAsset(`/inter-latin-ext-${weight}-normal.woff`);
|
|
16
|
-
}
|
|
17
|
-
if (font.path) {
|
|
18
|
-
data = await readPublicAsset(font.path);
|
|
19
|
-
if (!data) {
|
|
20
|
-
try {
|
|
21
|
-
data = await globalThis.$fetch(font.path, {
|
|
22
|
-
responseType: "arrayBuffer",
|
|
23
|
-
baseURL: requestOrigin
|
|
24
|
-
});
|
|
25
|
-
} catch {
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
if (!data) {
|
|
30
|
-
const fontUrl = await globalThis.$fetch("/api/og-image-font", {
|
|
31
|
-
query: { name, weight }
|
|
32
|
-
});
|
|
33
|
-
data = await globalThis.$fetch(fontUrl, {
|
|
34
|
-
responseType: "arrayBuffer"
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
cachedFonts[fontKey] = { name, weight: Number(weight), data, style: "normal" };
|
|
38
|
-
await useStorage().setItem(storageKey, Buffer.from(data).toString("base64"));
|
|
39
|
-
return cachedFonts[fontKey];
|
|
40
|
-
}
|
|
41
|
-
export async function walkSatoriTree(node, plugins, props) {
|
|
42
|
-
if (!node.props?.children)
|
|
43
|
-
return;
|
|
44
|
-
if (Array.isArray(node.props.children) && node.props.children.length === 0) {
|
|
45
|
-
delete node.props.children;
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
for (const child of node.props.children || []) {
|
|
49
|
-
if (child) {
|
|
50
|
-
for (const plugin of plugins.flat()) {
|
|
51
|
-
if (plugin.filter(child))
|
|
52
|
-
await plugin.transform(child, props);
|
|
53
|
-
}
|
|
54
|
-
await walkSatoriTree(child, plugins, props);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
export function defineSatoriTransformer(transformer) {
|
|
59
|
-
return transformer;
|
|
60
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { getQuery } from "h3";
|
|
2
|
-
import { cachedEventHandler } from "#imports";
|
|
3
|
-
export default cachedEventHandler(async (e) => {
|
|
4
|
-
const { name, weight } = getQuery(e);
|
|
5
|
-
if (!name || !weight)
|
|
6
|
-
return "Provide a font name and weight";
|
|
7
|
-
const css = await await globalThis.$fetch(`https://fonts.googleapis.com/css2?family=${name}:wght@${weight}`, {
|
|
8
|
-
headers: {
|
|
9
|
-
// Make sure it returns TTF.
|
|
10
|
-
"User-Agent": "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; de-at) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/5.0.5 Safari/533.21.1"
|
|
11
|
-
}
|
|
12
|
-
});
|
|
13
|
-
const resource = css.match(/src: url\((.+)\) format\('(opentype|truetype)'\)/);
|
|
14
|
-
if (!resource)
|
|
15
|
-
return;
|
|
16
|
-
return resource[1];
|
|
17
|
-
}, {
|
|
18
|
-
getKey: (e) => {
|
|
19
|
-
const query = getQuery(e);
|
|
20
|
-
return `nuxt-og-image:font-url:${query.name}:${query.weight}`;
|
|
21
|
-
}
|
|
22
|
-
});
|