nuxt-og-image 6.10.4 → 7.0.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 +10 -14
- package/dist/chunks/tw4.mjs +6 -6
- package/dist/chunks/uno.mjs +7 -7
- package/dist/cli.mjs +4 -4
- package/dist/devtools/components/og-image/RendererSelectModal.vue +1 -1
- package/dist/devtools/lib/og-image/fonts.ts +38 -0
- package/dist/devtools/lib/og-image/types.ts +7 -0
- package/dist/devtools/pages/og-image/index.vue +19 -14
- package/dist/module.d.mts +14 -10
- package/dist/module.d.ts +14 -10
- package/dist/module.json +2 -2
- package/dist/module.mjs +6 -6
- package/dist/runtime/app/client-utils.js +7 -4
- package/dist/runtime/app/components/Templates/Community/SaaS.satori.vue +1 -1
- package/dist/runtime/app/components/Templates/Community/SimpleBlog.satori.vue +1 -1
- package/dist/runtime/app/disabled/components.d.ts +1 -0
- package/dist/runtime/app/disabled/components.js +0 -0
- package/dist/runtime/app/disabled/composables/defineOgImage.d.ts +1 -0
- package/dist/runtime/app/disabled/composables/defineOgImage.js +1 -0
- package/dist/runtime/app/disabled/composables/defineOgImageComponent.d.ts +1 -0
- package/dist/runtime/app/disabled/composables/defineOgImageComponent.js +1 -0
- package/dist/runtime/app/disabled/composables/defineOgImageScreenshot.d.ts +1 -0
- package/dist/runtime/app/disabled/composables/defineOgImageScreenshot.js +1 -0
- package/dist/runtime/app/disabled/composables/mock.d.ts +1 -0
- package/dist/runtime/app/disabled/composables/mock.js +1 -0
- package/dist/runtime/app/disabled/index.d.ts +3 -0
- package/dist/runtime/app/disabled/index.js +3 -0
- package/dist/runtime/app/index.d.ts +4 -0
- package/dist/runtime/app/index.js +4 -0
- package/dist/runtime/app/utils/plugins.js +1 -1
- package/dist/runtime/app/utils.js +2 -2
- package/dist/runtime/server/index.d.ts +1 -0
- package/dist/runtime/server/index.js +1 -0
- package/dist/runtime/server/middleware/signing.d.ts +2 -0
- package/dist/runtime/server/middleware/signing.js +19 -0
- package/dist/runtime/server/nitro.d.ts +3 -3
- package/dist/runtime/server/nitro.js +4 -4
- package/dist/runtime/server/og-image/bindings/font-assets/dev-prerender.js +8 -49
- package/dist/runtime/server/og-image/bindings/font-assets/node.js +3 -2
- package/dist/runtime/server/og-image/bindings/satori/node.d.ts +1 -2
- package/dist/runtime/server/og-image/bindings/satori/wasm-fs.d.ts +1 -2
- package/dist/runtime/server/og-image/bindings/satori/wasm-fs.js +1 -1
- package/dist/runtime/server/og-image/bindings/satori/wasm.d.ts +1 -2
- package/dist/runtime/server/og-image/bindings/satori/wasm.js +1 -1
- package/dist/runtime/server/og-image/browser/screenshot.js +5 -3
- package/dist/runtime/server/og-image/cache/publish.d.ts +46 -0
- package/dist/runtime/server/og-image/cache/publish.js +91 -0
- package/dist/runtime/server/og-image/cache/published.d.ts +17 -0
- package/dist/runtime/server/og-image/cache/published.js +49 -0
- package/dist/runtime/server/og-image/context.js +1 -1
- package/dist/runtime/server/og-image/core/plugins/imageSrc.js +2 -5
- package/dist/runtime/server/og-image/core/transforms/emojis/index.d.ts +3 -2
- package/dist/runtime/server/og-image/core/vnodes.js +19 -1
- package/dist/runtime/server/og-image/font-source.d.ts +1 -0
- package/dist/runtime/server/og-image/font-source.js +1 -0
- package/dist/runtime/server/og-image/fonts.d.ts +1 -1
- package/dist/runtime/server/og-image/fonts.js +1 -1
- package/dist/runtime/server/og-image/satori/filters.d.ts +1 -0
- package/dist/runtime/server/og-image/satori/filters.js +14 -0
- package/dist/runtime/server/og-image/satori/instances.d.ts +1 -2
- package/dist/runtime/server/og-image/satori/plugins/classes.js +0 -7
- package/dist/runtime/server/og-image/satori/renderer.js +2 -1
- package/dist/runtime/server/og-image/satori/vnodes.js +1 -4
- package/dist/runtime/server/og-image/takumi/renderer.js +11 -47
- package/dist/runtime/server/og-image/utils/css.d.ts +0 -5
- package/dist/runtime/server/og-image/utils/css.js +0 -5
- package/dist/runtime/server/plugins/auto-eject-nitro3.d.ts +2 -0
- package/dist/runtime/server/plugins/auto-eject-nitro3.js +9 -0
- package/dist/runtime/server/plugins/auto-eject.js +3 -31
- package/dist/runtime/server/plugins/prerender.js +67 -2
- package/dist/runtime/server/plugins/publish.d.ts +2 -0
- package/dist/runtime/server/plugins/publish.js +44 -0
- package/dist/runtime/server/routes/debug.json.d.ts +10 -1
- package/dist/runtime/server/routes/debug.json.js +4 -4
- package/dist/runtime/server/routes/static-font.d.ts +2 -0
- package/dist/runtime/server/routes/static-font.js +22 -0
- package/dist/runtime/server/signing-secret.d.ts +8 -0
- package/dist/runtime/server/signing-secret.js +75 -0
- package/dist/runtime/server/util/auto-eject-lifecycle.d.ts +13 -0
- package/dist/runtime/server/util/auto-eject-lifecycle.js +31 -0
- package/dist/runtime/server/util/cache.d.ts +1 -0
- package/dist/runtime/server/util/cache.js +12 -6
- package/dist/runtime/server/util/cloudflare.d.ts +2 -2
- package/dist/runtime/server/util/eventHandlers.js +68 -3
- package/dist/runtime/server/util/fetchLocalAsset.js +2 -2
- package/dist/runtime/server/util/origin.d.ts +3 -0
- package/dist/runtime/server/util/origin.js +4 -0
- package/dist/runtime/server/util/publishWarnings.d.ts +6 -0
- package/dist/runtime/server/util/publishWarnings.js +6 -0
- package/dist/runtime/server/utils.d.ts +3 -3
- package/dist/runtime/server/utils.js +5 -10
- package/dist/runtime/shared/publish.d.ts +13 -0
- package/dist/runtime/shared/publish.js +17 -0
- package/dist/runtime/shared/urlEncoding.js +9 -4
- package/dist/runtime/types.d.ts +11 -16
- package/dist/shared/{nuxt-og-image.Bcegsloy.mjs → nuxt-og-image.DR_SxdDv.mjs} +1224 -1109
- package/package.json +60 -62
- package/skills/nuxt-og-image/SKILL.md +31 -14
- package/types/virtual.d.ts +8 -0
- package/dist/runtime/server/og-image/satori/plugins/emojis.d.ts +0 -2
- package/dist/runtime/server/og-image/satori/plugins/emojis.js +0 -112
- package/dist/runtime/server/og-image/satori/plugins/flex.d.ts +0 -2
- package/dist/runtime/server/og-image/satori/plugins/flex.js +0 -48
package/README.md
CHANGED
|
@@ -1,19 +1,12 @@
|
|
|
1
1
|
<img src=".github/assets/og-image-preview.png" alt="Nuxt OG Image DevTools Preview">
|
|
2
2
|
|
|
3
|
-
<h1>nuxt-og-image</h1>
|
|
3
|
+
<h1><a href="https://nuxtseo.com"><img src=".github/assets/icon.svg" width="40" height="40" alt="Nuxt SEO" align="top"></a> nuxt-og-image</h1>
|
|
4
4
|
|
|
5
5
|
[![npm version][npm-version-src]][npm-version-href]
|
|
6
6
|
[![npm downloads][npm-downloads-src]][npm-downloads-href]
|
|
7
7
|
[![License][license-src]][license-href]
|
|
8
8
|
[![Nuxt][nuxt-src]][nuxt-href]
|
|
9
|
-
|
|
10
|
-
<a href="https://skilld.dev/gh/nuxt-modules/og-image">
|
|
11
|
-
<picture>
|
|
12
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://skilld.dev/b/nuxt-modules/og-image?theme=dark">
|
|
13
|
-
<source media="(prefers-color-scheme: light)" srcset="https://skilld.dev/b/nuxt-modules/og-image?theme=light">
|
|
14
|
-
<img alt="Skill repository on skilld.dev" src="https://skilld.dev/b/nuxt-modules/og-image?theme=light">
|
|
15
|
-
</picture>
|
|
16
|
-
</a>
|
|
9
|
+
[![Skill repository on skilld.dev][skilld-src]][skilld-href]
|
|
17
10
|
|
|
18
11
|
Nuxt OG Image allows you to easily generate OG Images using either Vue components or screenshots of your pages.
|
|
19
12
|
|
|
@@ -46,7 +39,7 @@ need this module.
|
|
|
46
39
|
Install `nuxt-og-image` dependency to your project:
|
|
47
40
|
|
|
48
41
|
```bash
|
|
49
|
-
npx
|
|
42
|
+
npx nuxt module add og-image
|
|
50
43
|
```
|
|
51
44
|
|
|
52
45
|
> [!TIP]
|
|
@@ -78,14 +71,17 @@ npx nuxi@latest module add og-image
|
|
|
78
71
|
Licensed under the [MIT license](https://github.com/nuxt-modules/og-image/blob/main/LICENSE.md).
|
|
79
72
|
|
|
80
73
|
<!-- Badges -->
|
|
81
|
-
[npm-version-src]: https://img.shields.io/npm/v/nuxt-og-image/latest.svg?style=flat&
|
|
74
|
+
[npm-version-src]: https://img.shields.io/npm/v/nuxt-og-image/latest.svg?style=flat&labelColor=16152b&color=00a63e
|
|
82
75
|
[npm-version-href]: https://npmjs.com/package/nuxt-og-image
|
|
83
76
|
|
|
84
|
-
[npm-downloads-src]: https://img.shields.io/npm/dm/nuxt-og-image.svg?style=flat&
|
|
77
|
+
[npm-downloads-src]: https://img.shields.io/npm/dm/nuxt-og-image.svg?style=flat&labelColor=16152b&color=00a63e
|
|
85
78
|
[npm-downloads-href]: https://npmjs.com/package/nuxt-og-image
|
|
86
79
|
|
|
87
|
-
[license-src]: https://img.shields.io/github/license/nuxt-modules/og-image.svg?style=flat&
|
|
80
|
+
[license-src]: https://img.shields.io/github/license/nuxt-modules/og-image.svg?style=flat&labelColor=16152b&color=00a63e
|
|
88
81
|
[license-href]: https://github.com/nuxt-modules/og-image/blob/main/LICENSE.md
|
|
89
82
|
|
|
90
|
-
[nuxt-src]: https://img.shields.io/badge/Nuxt-
|
|
83
|
+
[nuxt-src]: https://img.shields.io/badge/Nuxt-16152b?logo=nuxt&style=flat
|
|
91
84
|
[nuxt-href]: https://nuxt.com
|
|
85
|
+
|
|
86
|
+
[skilld-src]: https://skilld.dev/b/nuxt-modules/og-image?style=flat&labelColor=16152b&color=00a63e&logoColor=ffffff
|
|
87
|
+
[skilld-href]: https://skilld.dev/gh/nuxt-modules/og-image
|
package/dist/chunks/tw4.mjs
CHANGED
|
@@ -2,25 +2,24 @@ import { readFile } from 'node:fs/promises';
|
|
|
2
2
|
import { pathToFileURL } from 'node:url';
|
|
3
3
|
import { resolveModulePath } from 'exsolve';
|
|
4
4
|
import { dirname, join } from 'pathe';
|
|
5
|
-
import { e as extractVariantBaseClasses, r as resolveVariantPrefixes, h as resolveExtractedVars, l as resolveVarsDeep, s as simplifyCss, p as postProcessStyles, m as loadLightningCss, a as extractCssVars, c as extractUniversalVars, d as extractPerClassVars, g as extractVarsFromCss, f as extractClassStyles } from '../shared/nuxt-og-image.
|
|
6
|
-
import 'node:crypto';
|
|
5
|
+
import { e as extractVariantBaseClasses, r as resolveVariantPrefixes, h as resolveExtractedVars, l as resolveVarsDeep, s as simplifyCss, p as postProcessStyles, m as loadLightningCss, a as extractCssVars, c as extractUniversalVars, d as extractPerClassVars, g as extractVarsFromCss, f as extractClassStyles } from '../shared/nuxt-og-image.DR_SxdDv.mjs';
|
|
7
6
|
import 'node:fs';
|
|
7
|
+
import 'node:module';
|
|
8
8
|
import '@nuxt/kit';
|
|
9
9
|
import 'defu';
|
|
10
10
|
import 'fnv1a-64';
|
|
11
|
-
import 'nuxt-site-config/kit';
|
|
12
11
|
import 'nuxtseo-shared/kit';
|
|
13
|
-
import '
|
|
12
|
+
import 'node:crypto';
|
|
14
13
|
import 'magic-string';
|
|
15
14
|
import 'oxc-walker';
|
|
16
15
|
import '../../dist/runtime/logger.js';
|
|
17
|
-
import 'chrome-launcher';
|
|
18
16
|
import 'std-env';
|
|
17
|
+
import '../../dist/runtime/server/og-image/utils/css.js';
|
|
19
18
|
import 'nypm';
|
|
20
19
|
import 'nuxtseo-shared/devtools';
|
|
21
20
|
import 'unstorage';
|
|
22
21
|
import 'unstorage/drivers/fs-lite';
|
|
23
|
-
import '
|
|
22
|
+
import 'nuxt-site-config/kit';
|
|
24
23
|
import 'strip-literal';
|
|
25
24
|
import 'unplugin';
|
|
26
25
|
import '@vue/compiler-sfc';
|
|
@@ -30,6 +29,7 @@ import '../../dist/runtime/server/og-image/core/transforms/emojis/emoji-utils.js
|
|
|
30
29
|
import '../shared/nuxt-og-image.CJa2KCie.mjs';
|
|
31
30
|
import 'magicast';
|
|
32
31
|
import 'magicast/helpers';
|
|
32
|
+
import '../../dist/runtime/shared/publish.js';
|
|
33
33
|
|
|
34
34
|
const RE_GRADIENT_STOP_PREFIX = /^(from|via|to)-/;
|
|
35
35
|
const RE_COLOR_SHADE = /^(.+)-(\d+)$/;
|
package/dist/chunks/uno.mjs
CHANGED
|
@@ -1,27 +1,26 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
2
|
import { defu } from 'defu';
|
|
3
3
|
import { logger } from '../../dist/runtime/logger.js';
|
|
4
|
-
import { e as extractVariantBaseClasses, s as simplifyCss, a as extractCssVars, b as extractPropertyInitialValues, c as extractUniversalVars, d as extractPerClassVars, f as extractClassStyles, p as postProcessStyles, r as resolveVariantPrefixes, i as importOptionalPeer, g as extractVarsFromCss, h as resolveExtractedVars } from '../shared/nuxt-og-image.
|
|
5
|
-
export { j as importResolvedModule, k as resolveOptionalModulePath } from '../shared/nuxt-og-image.
|
|
6
|
-
import 'node:crypto';
|
|
4
|
+
import { e as extractVariantBaseClasses, s as simplifyCss, a as extractCssVars, b as extractPropertyInitialValues, c as extractUniversalVars, d as extractPerClassVars, f as extractClassStyles, p as postProcessStyles, r as resolveVariantPrefixes, i as importOptionalPeer, g as extractVarsFromCss, h as resolveExtractedVars } from '../shared/nuxt-og-image.DR_SxdDv.mjs';
|
|
5
|
+
export { j as importResolvedModule, k as resolveOptionalModulePath } from '../shared/nuxt-og-image.DR_SxdDv.mjs';
|
|
7
6
|
import 'node:fs';
|
|
7
|
+
import 'node:module';
|
|
8
8
|
import 'node:url';
|
|
9
9
|
import '@nuxt/kit';
|
|
10
10
|
import 'fnv1a-64';
|
|
11
|
-
import 'nuxt-site-config/kit';
|
|
12
11
|
import 'nuxtseo-shared/kit';
|
|
13
12
|
import 'pathe';
|
|
14
|
-
import '
|
|
13
|
+
import 'node:crypto';
|
|
15
14
|
import 'magic-string';
|
|
16
15
|
import 'oxc-walker';
|
|
17
16
|
import 'exsolve';
|
|
18
|
-
import 'chrome-launcher';
|
|
19
17
|
import 'std-env';
|
|
18
|
+
import '../../dist/runtime/server/og-image/utils/css.js';
|
|
20
19
|
import 'nypm';
|
|
21
20
|
import 'nuxtseo-shared/devtools';
|
|
22
21
|
import 'unstorage';
|
|
23
22
|
import 'unstorage/drivers/fs-lite';
|
|
24
|
-
import '
|
|
23
|
+
import 'nuxt-site-config/kit';
|
|
25
24
|
import 'strip-literal';
|
|
26
25
|
import 'unplugin';
|
|
27
26
|
import '@vue/compiler-sfc';
|
|
@@ -31,6 +30,7 @@ import '../../dist/runtime/server/og-image/core/transforms/emojis/emoji-utils.js
|
|
|
31
30
|
import '../shared/nuxt-og-image.CJa2KCie.mjs';
|
|
32
31
|
import 'magicast';
|
|
33
32
|
import 'magicast/helpers';
|
|
33
|
+
import '../../dist/runtime/shared/publish.js';
|
|
34
34
|
|
|
35
35
|
const RE_SVG_DATA_URL = /url\("data:image\/svg\+xml[;,]([^"]+)"\)/;
|
|
36
36
|
const RE_UTF8_PREFIX = /^utf8,/;
|
package/dist/cli.mjs
CHANGED
|
@@ -646,11 +646,11 @@ async function installNuxtFonts() {
|
|
|
646
646
|
spinner.start("Adding @nuxt/fonts module...");
|
|
647
647
|
const { exec } = await import('tinyexec');
|
|
648
648
|
try {
|
|
649
|
-
await exec("npx", ["
|
|
649
|
+
await exec("npx", ["nuxt", "module", "add", "@nuxt/fonts"], { nodeOptions: { cwd } });
|
|
650
650
|
spinner.stop("@nuxt/fonts module added");
|
|
651
651
|
} catch {
|
|
652
652
|
spinner.stop("Failed to add @nuxt/fonts");
|
|
653
|
-
p.log.warn("Run manually: npx
|
|
653
|
+
p.log.warn("Run manually: npx nuxt module add @nuxt/fonts");
|
|
654
654
|
}
|
|
655
655
|
}
|
|
656
656
|
async function runMigrate(args2) {
|
|
@@ -858,7 +858,7 @@ async function runMigrate(args2) {
|
|
|
858
858
|
if (!p.isCancel(addFonts) && addFonts) {
|
|
859
859
|
await installNuxtFonts();
|
|
860
860
|
} else {
|
|
861
|
-
p.log.info("Skipped @nuxt/fonts installation. Add manually: npx
|
|
861
|
+
p.log.info("Skipped @nuxt/fonts installation. Add manually: npx nuxt module add @nuxt/fonts");
|
|
862
862
|
}
|
|
863
863
|
}
|
|
864
864
|
}
|
|
@@ -1343,7 +1343,7 @@ function generateSecret() {
|
|
|
1343
1343
|
p.log.step(`Secret: ${secret}`);
|
|
1344
1344
|
p.log.message("");
|
|
1345
1345
|
p.log.message("Set the environment variable:");
|
|
1346
|
-
p.log.message(`
|
|
1346
|
+
p.log.message(` NUXT_APP_SECRET=${secret}`);
|
|
1347
1347
|
p.log.message("");
|
|
1348
1348
|
p.log.message("The secret is automatically picked up via runtime config.");
|
|
1349
1349
|
p.outro("");
|
|
@@ -109,7 +109,7 @@ const rendererConfigs = computed<RendererConfig[]>(() => {
|
|
|
109
109
|
...(hasSharp ? [fmt('jpg')] : []),
|
|
110
110
|
],
|
|
111
111
|
disabledReason: !hasTakumi ? 'Module not installed' : null,
|
|
112
|
-
installCommand: !hasTakumi ? 'npx
|
|
112
|
+
installCommand: !hasTakumi ? 'npx nuxt-og-image enable takumi' : null,
|
|
113
113
|
},
|
|
114
114
|
]
|
|
115
115
|
})
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { withBase } from 'ufo'
|
|
2
|
+
|
|
3
|
+
export interface FontPreviewFace {
|
|
4
|
+
family: string
|
|
5
|
+
weight: number
|
|
6
|
+
style: string
|
|
7
|
+
src: string
|
|
8
|
+
subset?: string
|
|
9
|
+
unicodeRange?: string
|
|
10
|
+
weightRange?: [number, number]
|
|
11
|
+
size?: number
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function getFontPreviewFaces(available: FontPreviewFace[], resolved: FontPreviewFace[]): FontPreviewFace[] {
|
|
15
|
+
const seen = new Set<string>()
|
|
16
|
+
return [...available, ...resolved].filter((face) => {
|
|
17
|
+
const key = JSON.stringify([face.family, face.weight, face.style, face.src, face.unicodeRange])
|
|
18
|
+
if (seen.has(key))
|
|
19
|
+
return false
|
|
20
|
+
seen.add(key)
|
|
21
|
+
return true
|
|
22
|
+
})
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function createFontPreviewCss(faces: FontPreviewFace[], origin: string): string {
|
|
26
|
+
const seen = new Set<string>()
|
|
27
|
+
const appUrl = origin ? new URL(origin) : undefined
|
|
28
|
+
return faces.flatMap((face) => {
|
|
29
|
+
const weight = face.weightRange?.join(' ') || String(face.weight)
|
|
30
|
+
const key = JSON.stringify([face.family, weight, face.style, face.src, face.unicodeRange])
|
|
31
|
+
if (seen.has(key))
|
|
32
|
+
return []
|
|
33
|
+
seen.add(key)
|
|
34
|
+
const path = appUrl && face.src.startsWith('/_og-static-fonts/') ? withBase(face.src, appUrl.pathname) : face.src
|
|
35
|
+
const src = appUrl ? new URL(path, appUrl).href : path
|
|
36
|
+
return [`@font-face { font-family: ${JSON.stringify(`ogp-${face.family}`)}; src: url(${JSON.stringify(src)}); font-weight: ${weight}; font-style: ${face.style};${face.unicodeRange ? ` unicode-range: ${face.unicodeRange};` : ''} font-display: swap; }`]
|
|
37
|
+
}).join('\n')
|
|
38
|
+
}
|
|
@@ -33,6 +33,13 @@ export interface GlobalDebugResponse {
|
|
|
33
33
|
componentNames: OgImageComponent[]
|
|
34
34
|
siteConfigUrl?: string
|
|
35
35
|
compatibility?: RuntimeCompatibilitySchema
|
|
36
|
+
origin?: string
|
|
37
|
+
fontRequirements?: {
|
|
38
|
+
weights: number[]
|
|
39
|
+
styles: string[]
|
|
40
|
+
families: string[]
|
|
41
|
+
hasDynamicBindings: boolean
|
|
42
|
+
}
|
|
36
43
|
resolvedFonts?: FontConfig[]
|
|
37
44
|
availableFonts?: FontConfig[]
|
|
38
45
|
}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
2
|
import { useHead } from 'nuxt/app'
|
|
3
|
-
import { hasProductionUrl, previewSource, productionUrl } from 'nuxtseo-layer-devtools/composables/state'
|
|
3
|
+
import { hasProductionUrl, host, previewSource, productionUrl } from 'nuxtseo-layer-devtools/composables/state'
|
|
4
4
|
import { withHttps } from 'ufo'
|
|
5
5
|
import { computed, reactive, ref, watch } from 'vue'
|
|
6
|
+
import { createFontPreviewCss, getFontPreviewFaces } from '../../lib/og-image/fonts'
|
|
6
7
|
import { useOgImage } from '../../lib/og-image/og-image'
|
|
7
8
|
import { RendererSelectDialogPromise } from '../../lib/og-image/renderer-select'
|
|
8
9
|
import { isConnectionFailed, isFallbackMode } from '../../lib/og-image/rpc'
|
|
10
|
+
import { optionsOverrides } from '../../lib/og-image/util/logic'
|
|
9
11
|
|
|
10
12
|
const RE_SINGLE_QUOTE = /'/g
|
|
11
13
|
const RE_VUE_FILENAME = /[^/]+\.vue$/
|
|
@@ -226,7 +228,7 @@ const fontFiles = computed<FontFileEntry[]>(() => {
|
|
|
226
228
|
const resolved = globalDebug.value?.resolvedFonts || []
|
|
227
229
|
if (!available.length && !resolved.length)
|
|
228
230
|
return []
|
|
229
|
-
const source = available
|
|
231
|
+
const source = getFontPreviewFaces(available, resolved)
|
|
230
232
|
// Build set of resolved keys for loaded check
|
|
231
233
|
const resolvedKeys = new Set(resolved.map((f: any) => `${f.family}-${f.weight}-${f.style}`))
|
|
232
234
|
// Count subsets per family+weight+style and collect subset names
|
|
@@ -234,7 +236,7 @@ const fontFiles = computed<FontFileEntry[]>(() => {
|
|
|
234
236
|
for (const f of source) {
|
|
235
237
|
const key = `${f.family}-${f.weight}-${f.style}`
|
|
236
238
|
const subs = subsetMap.get(key) || []
|
|
237
|
-
if (f.subset)
|
|
239
|
+
if (f.subset && !subs.includes(f.subset))
|
|
238
240
|
subs.push(f.subset)
|
|
239
241
|
subsetMap.set(key, subs)
|
|
240
242
|
}
|
|
@@ -268,9 +270,13 @@ const fontFiles = computed<FontFileEntry[]>(() => {
|
|
|
268
270
|
const fontFamilySizes = computed(() => {
|
|
269
271
|
const resolved = globalDebug.value?.resolvedFonts || []
|
|
270
272
|
const sizes = new Map<string, number>()
|
|
273
|
+
const seen = new Set<string>()
|
|
271
274
|
for (const f of resolved) {
|
|
272
|
-
|
|
275
|
+
const key = JSON.stringify([f.family, f.src])
|
|
276
|
+
if (f.size && !seen.has(key)) {
|
|
277
|
+
seen.add(key)
|
|
273
278
|
sizes.set(f.family, (sizes.get(f.family) || 0) + f.size)
|
|
279
|
+
}
|
|
274
280
|
}
|
|
275
281
|
return sizes
|
|
276
282
|
})
|
|
@@ -296,15 +302,8 @@ const unresolvedFamilies = computed(() => {
|
|
|
296
302
|
})
|
|
297
303
|
|
|
298
304
|
const fontFaceCss = computed(() => {
|
|
299
|
-
const
|
|
300
|
-
|
|
301
|
-
for (const f of fontFiles.value) {
|
|
302
|
-
if (seen.has(f.family))
|
|
303
|
-
continue
|
|
304
|
-
seen.add(f.family)
|
|
305
|
-
rules.push(`@font-face { font-family: 'ogp-${f.family}'; src: url('${f.src}'); font-display: swap; }`)
|
|
306
|
-
}
|
|
307
|
-
return rules.join('\n')
|
|
305
|
+
const faces = getFontPreviewFaces(globalDebug.value?.availableFonts || [], globalDebug.value?.resolvedFonts || [])
|
|
306
|
+
return createFontPreviewCss(faces, host.value || globalDebug.value?.origin || '')
|
|
308
307
|
})
|
|
309
308
|
|
|
310
309
|
useHead({ style: computed(() => fontFaceCss.value ? [fontFaceCss.value] : []) })
|
|
@@ -315,7 +314,13 @@ function applyFontOverride(family: string) {
|
|
|
315
314
|
const next = fontOverride.value === family ? '' : family
|
|
316
315
|
fontOverride.value = next
|
|
317
316
|
hasMadeChanges.value = true
|
|
318
|
-
|
|
317
|
+
const props = { ...optionsOverrides.value.props }
|
|
318
|
+
if (next)
|
|
319
|
+
props.fontFamily = next
|
|
320
|
+
else
|
|
321
|
+
delete props.fontFamily
|
|
322
|
+
optionsOverrides.value = { ...optionsOverrides.value, props }
|
|
323
|
+
refreshSources()
|
|
319
324
|
}
|
|
320
325
|
|
|
321
326
|
const metaOverrides = reactive({
|
package/dist/module.d.mts
CHANGED
|
@@ -46,7 +46,7 @@ interface ModuleOptions {
|
|
|
46
46
|
debug: boolean;
|
|
47
47
|
/**
|
|
48
48
|
* Configure the runtime cache storage for generated OG images.
|
|
49
|
-
* - `true` - Use Nitro
|
|
49
|
+
* - `true` - Use configured Nitro cache storage, or a 64 MiB bounded memory cache (default)
|
|
50
50
|
* - `false` - Disable caching
|
|
51
51
|
* - `string` - Use a custom storage mount key (e.g., `'redis'`). You must mount the storage yourself via a Nitro plugin.
|
|
52
52
|
* - `object` - Provide a driver config that the module will mount for you (build-time only)
|
|
@@ -96,6 +96,14 @@ interface ModuleOptions {
|
|
|
96
96
|
buildCache?: boolean | {
|
|
97
97
|
base?: string;
|
|
98
98
|
};
|
|
99
|
+
/**
|
|
100
|
+
* Publish rendered images to a mounted Nitro storage driver.
|
|
101
|
+
* Image objects have no TTL. cacheMaxAgeSeconds limits manifest reuse.
|
|
102
|
+
*/
|
|
103
|
+
publish?: {
|
|
104
|
+
storage: string;
|
|
105
|
+
baseURL: string;
|
|
106
|
+
};
|
|
99
107
|
/**
|
|
100
108
|
* Warn about OG Image components missing renderer suffix in dev mode.
|
|
101
109
|
* Set to false to suppress warnings for legacy/test components.
|
|
@@ -192,21 +200,17 @@ interface ModuleOptions {
|
|
|
192
200
|
*/
|
|
193
201
|
restrictRuntimeImagesToOrigin?: boolean | string[];
|
|
194
202
|
/**
|
|
195
|
-
*
|
|
203
|
+
* Disable URL signing with false. Otherwise, all runtime OG image URLs include a
|
|
196
204
|
* keyed hash signature and the handler rejects requests with missing or
|
|
197
205
|
* invalid signatures.
|
|
198
206
|
*
|
|
199
|
-
* Leave unset to
|
|
200
|
-
* Set
|
|
201
|
-
* `false` to disable signing entirely. Generate one with:
|
|
202
|
-
* `npx nuxt-og-image generate-secret`
|
|
203
|
-
*
|
|
204
|
-
* Required (explicitly) when `strict` is enabled.
|
|
207
|
+
* Leave unset to derive a secret from Nuxt runtimeConfig.appSecret.
|
|
208
|
+
* Set NUXT_APP_SECRET in production. Use false to disable signing.
|
|
205
209
|
*/
|
|
206
|
-
secret?:
|
|
210
|
+
secret?: false;
|
|
207
211
|
/**
|
|
208
212
|
* Enable strict security mode. When enabled:
|
|
209
|
-
* -
|
|
213
|
+
* - URL signing is required through Nuxt appSecret
|
|
210
214
|
* - The `html` option is disabled (prevents SSRF via inline HTML injection)
|
|
211
215
|
* - `maxQueryParamSize` defaults to `2048`
|
|
212
216
|
* - `restrictRuntimeImagesToOrigin` defaults to `true`
|
package/dist/module.d.ts
CHANGED
|
@@ -46,7 +46,7 @@ interface ModuleOptions {
|
|
|
46
46
|
debug: boolean;
|
|
47
47
|
/**
|
|
48
48
|
* Configure the runtime cache storage for generated OG images.
|
|
49
|
-
* - `true` - Use Nitro
|
|
49
|
+
* - `true` - Use configured Nitro cache storage, or a 64 MiB bounded memory cache (default)
|
|
50
50
|
* - `false` - Disable caching
|
|
51
51
|
* - `string` - Use a custom storage mount key (e.g., `'redis'`). You must mount the storage yourself via a Nitro plugin.
|
|
52
52
|
* - `object` - Provide a driver config that the module will mount for you (build-time only)
|
|
@@ -96,6 +96,14 @@ interface ModuleOptions {
|
|
|
96
96
|
buildCache?: boolean | {
|
|
97
97
|
base?: string;
|
|
98
98
|
};
|
|
99
|
+
/**
|
|
100
|
+
* Publish rendered images to a mounted Nitro storage driver.
|
|
101
|
+
* Image objects have no TTL. cacheMaxAgeSeconds limits manifest reuse.
|
|
102
|
+
*/
|
|
103
|
+
publish?: {
|
|
104
|
+
storage: string;
|
|
105
|
+
baseURL: string;
|
|
106
|
+
};
|
|
99
107
|
/**
|
|
100
108
|
* Warn about OG Image components missing renderer suffix in dev mode.
|
|
101
109
|
* Set to false to suppress warnings for legacy/test components.
|
|
@@ -192,21 +200,17 @@ interface ModuleOptions {
|
|
|
192
200
|
*/
|
|
193
201
|
restrictRuntimeImagesToOrigin?: boolean | string[];
|
|
194
202
|
/**
|
|
195
|
-
*
|
|
203
|
+
* Disable URL signing with false. Otherwise, all runtime OG image URLs include a
|
|
196
204
|
* keyed hash signature and the handler rejects requests with missing or
|
|
197
205
|
* invalid signatures.
|
|
198
206
|
*
|
|
199
|
-
* Leave unset to
|
|
200
|
-
* Set
|
|
201
|
-
* `false` to disable signing entirely. Generate one with:
|
|
202
|
-
* `npx nuxt-og-image generate-secret`
|
|
203
|
-
*
|
|
204
|
-
* Required (explicitly) when `strict` is enabled.
|
|
207
|
+
* Leave unset to derive a secret from Nuxt runtimeConfig.appSecret.
|
|
208
|
+
* Set NUXT_APP_SECRET in production. Use false to disable signing.
|
|
205
209
|
*/
|
|
206
|
-
secret?:
|
|
210
|
+
secret?: false;
|
|
207
211
|
/**
|
|
208
212
|
* Enable strict security mode. When enabled:
|
|
209
|
-
* -
|
|
213
|
+
* - URL signing is required through Nuxt appSecret
|
|
210
214
|
* - The `html` option is disabled (prevents SSRF via inline HTML injection)
|
|
211
215
|
* - `maxQueryParamSize` defaults to `2048`
|
|
212
216
|
* - `restrictRuntimeImagesToOrigin` defaults to `true`
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
import 'node:crypto';
|
|
2
1
|
import 'node:fs';
|
|
3
2
|
import 'node:fs/promises';
|
|
3
|
+
import 'node:module';
|
|
4
4
|
import 'node:url';
|
|
5
5
|
import '@nuxt/kit';
|
|
6
6
|
import 'defu';
|
|
7
7
|
import 'fnv1a-64';
|
|
8
|
-
import 'nuxt-site-config/kit';
|
|
9
8
|
import 'nuxtseo-shared/kit';
|
|
10
9
|
import 'pathe';
|
|
11
|
-
|
|
12
|
-
export { n as default } from './shared/nuxt-og-image.Bcegsloy.mjs';
|
|
10
|
+
export { n as default } from './shared/nuxt-og-image.DR_SxdDv.mjs';
|
|
13
11
|
import '../dist/runtime/logger.js';
|
|
12
|
+
import '../dist/runtime/shared/publish.js';
|
|
13
|
+
import 'node:crypto';
|
|
14
14
|
import 'magic-string';
|
|
15
15
|
import 'oxc-walker';
|
|
16
16
|
import 'exsolve';
|
|
17
|
-
import 'chrome-launcher';
|
|
18
17
|
import 'std-env';
|
|
18
|
+
import '../dist/runtime/server/og-image/utils/css.js';
|
|
19
19
|
import 'nypm';
|
|
20
20
|
import 'nuxtseo-shared/devtools';
|
|
21
21
|
import 'unstorage';
|
|
22
22
|
import 'unstorage/drivers/fs-lite';
|
|
23
|
-
import '
|
|
23
|
+
import 'nuxt-site-config/kit';
|
|
24
24
|
import 'strip-literal';
|
|
25
25
|
import 'unplugin';
|
|
26
26
|
import '@vue/compiler-sfc';
|
|
@@ -2,8 +2,9 @@ import { defu } from "defu";
|
|
|
2
2
|
import { injectHead, useHead, useRuntimeConfig } from "nuxt/app";
|
|
3
3
|
import { joinURL, withQuery } from "ufo";
|
|
4
4
|
import { toValue } from "vue";
|
|
5
|
+
import { hasServerRuntime } from "#build/nuxt-og-image/client-config.mjs";
|
|
5
6
|
import { componentNames } from "#build/nuxt-og-image/components.mjs";
|
|
6
|
-
import { createSitePathResolver } from "#site-config/app
|
|
7
|
+
import { createSitePathResolver } from "#site-config/app";
|
|
7
8
|
import { buildOgImageUrl, generateMeta, separateProps } from "../shared.js";
|
|
8
9
|
const clientEntriesByHead = /* @__PURE__ */ new WeakMap();
|
|
9
10
|
function registerClientOgHead(ogKey, input, options) {
|
|
@@ -86,7 +87,7 @@ export function clientProcessOgImageOptions(input, route, basePath) {
|
|
|
86
87
|
paths.push(url);
|
|
87
88
|
continue;
|
|
88
89
|
}
|
|
89
|
-
if (
|
|
90
|
+
if (hasServerRuntime) {
|
|
90
91
|
const finalUrl2 = buildResolverUrl(baseURL, basePath, ogKey, route.query);
|
|
91
92
|
registerClientOgHead(ogKey, { meta: generateMeta(toValue(resolveImageUrl(finalUrl2)), validOptions, metaOptions) }, { tagPriority: "high" });
|
|
92
93
|
paths.push(finalUrl2);
|
|
@@ -101,8 +102,10 @@ export function clientProcessOgImageOptions(input, route, basePath) {
|
|
|
101
102
|
urlOpts._componentHash = component.hash;
|
|
102
103
|
const result = buildOgImageUrl(urlOpts, extension, true, defaults, void 0);
|
|
103
104
|
const resolvedUrl = joinURL("/", baseURL, result.url);
|
|
104
|
-
const
|
|
105
|
-
|
|
105
|
+
const query = opts._query && Object.keys(opts._query).length ? { _query: opts._query } : {};
|
|
106
|
+
const finalUrl = withQuery(resolvedUrl, query);
|
|
107
|
+
const imageUrl = rc.app.cdnURL ? withQuery(joinURL(rc.app.cdnURL, result.url), query) : toValue(resolveImageUrl(finalUrl));
|
|
108
|
+
registerClientOgHead(ogKey, { meta: generateMeta(imageUrl, opts, metaOptions) }, { processTemplateParams: true, tagPriority: "high" });
|
|
106
109
|
paths.push(finalUrl);
|
|
107
110
|
}
|
|
108
111
|
return paths;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
import { useSiteConfig } from "#site-config/app
|
|
2
|
+
import { useSiteConfig } from "#site-config/app";
|
|
3
3
|
const props = defineProps({
|
|
4
4
|
colorMode: { type: String, required: false, default: "light" },
|
|
5
5
|
title: { type: String, required: false },
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { parseURL } from "ufo";
|
|
3
3
|
import { computed } from "vue";
|
|
4
|
-
import { useSiteConfig } from "#site-config/app
|
|
4
|
+
import { useSiteConfig } from "#site-config/app";
|
|
5
5
|
const props = defineProps({
|
|
6
6
|
colorMode: { type: String, required: false, default: "light" },
|
|
7
7
|
title: { type: String, required: false, default: "title" },
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type OgImageComponents = Record<string, Record<string, unknown>>;
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { defineOgImage } from '../../composables/mock.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { defineOgImage } from "../../composables/mock.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { defineOgImageComponent } from '../../composables/mock.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { defineOgImageComponent } from "../../composables/mock.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { defineOgImageScreenshot } from '../../composables/mock.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { defineOgImageScreenshot } from "../../composables/mock.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { defineOgImage, defineOgImageComponent, defineOgImageScreenshot } from '../../composables/mock.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { defineOgImage, defineOgImageComponent, defineOgImageScreenshot } from "../../composables/mock.js";
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { defineOgImage } from './composables/defineOgImage.js';
|
|
2
|
+
export { defineOgImageComponent } from './composables/defineOgImageComponent.js';
|
|
3
|
+
export { defineOgImageScreenshot } from './composables/defineOgImageScreenshot.js';
|
|
4
|
+
export { getOgImagePath } from './utils.js';
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { defineOgImage } from "./composables/defineOgImage.js";
|
|
2
|
+
export { defineOgImageComponent } from "./composables/defineOgImageComponent.js";
|
|
3
|
+
export { defineOgImageScreenshot } from "./composables/defineOgImageScreenshot.js";
|
|
4
|
+
export { getOgImagePath } from "./utils.js";
|
|
@@ -4,7 +4,7 @@ import { createNitroRouteRuleMatcher } from "nuxtseo-shared/server";
|
|
|
4
4
|
import { parseURL } from "ufo";
|
|
5
5
|
import { toValue } from "vue";
|
|
6
6
|
import { defineNuxtPlugin, useRequestEvent } from "#app";
|
|
7
|
-
import { withSiteUrl } from "#site-config/app
|
|
7
|
+
import { withSiteUrl } from "#site-config/app";
|
|
8
8
|
import { createOgImageMeta, getOgImagePath } from "../../app/utils.js";
|
|
9
9
|
import { isInternalRoute } from "../../shared.js";
|
|
10
10
|
const RE_COMMA = /,/g;
|
|
@@ -4,7 +4,7 @@ import { useHead, useRequestEvent, useRuntimeConfig } from "nuxt/app";
|
|
|
4
4
|
import { joinURL, withQuery } from "ufo";
|
|
5
5
|
import { isRef, toValue } from "vue";
|
|
6
6
|
import { componentNames } from "#build/nuxt-og-image/components.mjs";
|
|
7
|
-
import { createSitePathResolver, withSiteUrl } from "#site-config/app
|
|
7
|
+
import { createSitePathResolver, withSiteUrl } from "#site-config/app";
|
|
8
8
|
import { buildOgImageUrl, generateMeta, separateProps } from "../shared.js";
|
|
9
9
|
function resolveUnrefHeadInput(input) {
|
|
10
10
|
if (input == null)
|
|
@@ -242,7 +242,7 @@ export function useOgImageRuntimeConfig() {
|
|
|
242
242
|
const serverCfg = c["nuxt-og-image"] || {};
|
|
243
243
|
const publicCfg = c.public?.["nuxt-og-image"] || {};
|
|
244
244
|
const merged = { defaults: {}, ...publicCfg, ...serverCfg };
|
|
245
|
-
const overrideSecret =
|
|
245
|
+
const overrideSecret = event?.context._ogImageSigningSecret;
|
|
246
246
|
if (overrideSecret)
|
|
247
247
|
merged.security = { ...merged.security || {}, secret: overrideSecret };
|
|
248
248
|
merged.app = { baseURL: c.app.baseURL };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { getOgImageUrl } from './nitro.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { getOgImageUrl } from "./nitro.js";
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { createError, useRuntimeConfig } from "nuxt/server";
|
|
2
|
+
import { joinURL } from "ufo";
|
|
3
|
+
import { defineEventHandler, getRequestURL } from "#nuxtseo/h3";
|
|
4
|
+
import { rendersImages } from "#og-image-virtual/signing.mjs";
|
|
5
|
+
import { initializeOgImageSigning, isOgImageEndpointPath, reportSigningFailure } from "../signing-secret.js";
|
|
6
|
+
export default defineEventHandler(async (event) => {
|
|
7
|
+
if (!rendersImages)
|
|
8
|
+
return;
|
|
9
|
+
const baseURL = useRuntimeConfig().app.baseURL;
|
|
10
|
+
const pathname = getRequestURL(event).pathname;
|
|
11
|
+
if (pathname === "/__nuxt_error" || pathname === joinURL(baseURL, "__nuxt_error"))
|
|
12
|
+
return;
|
|
13
|
+
const failure = await initializeOgImageSigning(event).then(() => void 0, (error) => error);
|
|
14
|
+
if (failure === void 0)
|
|
15
|
+
return;
|
|
16
|
+
reportSigningFailure(failure);
|
|
17
|
+
if (import.meta.prerender || isOgImageEndpointPath(pathname, baseURL))
|
|
18
|
+
throw createError({ status: 500, message: "[nuxt-og-image] URL signing needs NUXT_APP_SECRET with at least 32 characters.", cause: failure });
|
|
19
|
+
});
|