@djangocfg/nextjs 2.1.225 → 2.1.226
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 +49 -80
- package/dist/config/index.mjs +6 -17
- package/dist/config/index.mjs.map +1 -1
- package/dist/index.d.mts +1 -6
- package/dist/index.mjs +9 -865
- package/dist/index.mjs.map +1 -1
- package/dist/og-image/index.d.mts +40 -100
- package/dist/og-image/index.mjs +46 -823
- package/dist/og-image/index.mjs.map +1 -1
- package/package.json +14 -25
- package/src/index.ts +0 -3
- package/src/og-image/README.md +142 -53
- package/src/og-image/index.ts +3 -27
- package/src/og-image/metadata.ts +67 -0
- package/src/og-image/types.ts +28 -44
- package/src/og-image/url.ts +58 -0
- package/dist/og-image/components/index.d.mts +0 -59
- package/dist/og-image/components/index.mjs +0 -338
- package/dist/og-image/components/index.mjs.map +0 -1
- package/dist/og-image/utils/index.d.mts +0 -308
- package/dist/og-image/utils/index.mjs +0 -327
- package/dist/og-image/utils/index.mjs.map +0 -1
- package/src/og-image/components/DefaultTemplate.tsx +0 -369
- package/src/og-image/components/index.ts +0 -9
- package/src/og-image/route.tsx +0 -312
- package/src/og-image/utils/fonts.ts +0 -150
- package/src/og-image/utils/index.ts +0 -28
- package/src/og-image/utils/metadata.ts +0 -269
- package/src/og-image/utils/url.ts +0 -386
|
@@ -1,308 +0,0 @@
|
|
|
1
|
-
import { Metadata } from 'next';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Font Utilities for OG Image Generation
|
|
5
|
-
*
|
|
6
|
-
* Provides dynamic font loading from Google Fonts without requiring files in public/
|
|
7
|
-
* Based on Vercel's official @vercel/og documentation
|
|
8
|
-
*/
|
|
9
|
-
interface FontConfig {
|
|
10
|
-
name: string;
|
|
11
|
-
weight?: 400 | 500 | 600 | 700 | 800 | 900;
|
|
12
|
-
style?: 'normal' | 'italic';
|
|
13
|
-
data: ArrayBuffer;
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* Load a Google Font dynamically
|
|
17
|
-
*
|
|
18
|
-
* @param font - Font family name (e.g., "Inter", "Roboto", "Manrope")
|
|
19
|
-
* @param text - Text to optimize font for (optional, reduces file size)
|
|
20
|
-
* @param weight - Font weight (default: 700)
|
|
21
|
-
* @returns ArrayBuffer of font data
|
|
22
|
-
*
|
|
23
|
-
* @example
|
|
24
|
-
* const fontData = await loadGoogleFont('Manrope', 'Hello World', 700);
|
|
25
|
-
*/
|
|
26
|
-
declare function loadGoogleFont(font: string, text?: string, weight?: number): Promise<ArrayBuffer>;
|
|
27
|
-
/**
|
|
28
|
-
* Load multiple Google Fonts
|
|
29
|
-
*
|
|
30
|
-
* @param fonts - Array of font configurations to load
|
|
31
|
-
* @returns Array of FontConfig objects ready for ImageResponse
|
|
32
|
-
*
|
|
33
|
-
* @example
|
|
34
|
-
* const fonts = await loadGoogleFonts([
|
|
35
|
-
* { family: 'Manrope', weight: 700 },
|
|
36
|
-
* { family: 'Inter', weight: 400 }
|
|
37
|
-
* ]);
|
|
38
|
-
*/
|
|
39
|
-
declare function loadGoogleFonts(fonts: Array<{
|
|
40
|
-
family: string;
|
|
41
|
-
weight?: 400 | 500 | 600 | 700 | 800 | 900;
|
|
42
|
-
style?: 'normal' | 'italic';
|
|
43
|
-
text?: string;
|
|
44
|
-
}>): Promise<FontConfig[]>;
|
|
45
|
-
/**
|
|
46
|
-
* Create a font loader with caching
|
|
47
|
-
*
|
|
48
|
-
* Useful for reusing font data across multiple OG image requests
|
|
49
|
-
*
|
|
50
|
-
* @example
|
|
51
|
-
* const fontLoader = createFontLoader();
|
|
52
|
-
* const font = await fontLoader.load('Manrope', 700);
|
|
53
|
-
*/
|
|
54
|
-
declare function createFontLoader(): {
|
|
55
|
-
/**
|
|
56
|
-
* Load a font with caching
|
|
57
|
-
*/
|
|
58
|
-
load(family: string, weight?: number, text?: string): Promise<ArrayBuffer>;
|
|
59
|
-
/**
|
|
60
|
-
* Clear the cache
|
|
61
|
-
*/
|
|
62
|
-
clear(): void;
|
|
63
|
-
/**
|
|
64
|
-
* Get cache size
|
|
65
|
-
*/
|
|
66
|
-
size(): number;
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* URL Generation Helpers for OG Images
|
|
71
|
-
*
|
|
72
|
-
* Utilities to generate OG image URLs with proper query parameters
|
|
73
|
-
*/
|
|
74
|
-
/**
|
|
75
|
-
* Encode string to base64 with Unicode support
|
|
76
|
-
* Works in both browser and Node.js environments
|
|
77
|
-
*/
|
|
78
|
-
declare function encodeBase64(str: string): string;
|
|
79
|
-
/**
|
|
80
|
-
* Decode base64 string with Unicode support
|
|
81
|
-
* Works in both browser, Node.js, and Edge Runtime environments
|
|
82
|
-
*/
|
|
83
|
-
declare function decodeBase64(str: string): string;
|
|
84
|
-
/**
|
|
85
|
-
* OG Image URL parameters
|
|
86
|
-
* All parameters can be encoded in URL via base64
|
|
87
|
-
*/
|
|
88
|
-
interface OgImageUrlParams {
|
|
89
|
-
/** Page title */
|
|
90
|
-
title: string;
|
|
91
|
-
/** Page description (optional) */
|
|
92
|
-
description?: string;
|
|
93
|
-
/** Site name (optional) */
|
|
94
|
-
siteName?: string;
|
|
95
|
-
/** Logo URL (optional) */
|
|
96
|
-
logo?: string;
|
|
97
|
-
/** Background type: 'gradient' or 'solid' */
|
|
98
|
-
backgroundType?: 'gradient' | 'solid';
|
|
99
|
-
/** Gradient start color (hex) */
|
|
100
|
-
gradientStart?: string;
|
|
101
|
-
/** Gradient end color (hex) */
|
|
102
|
-
gradientEnd?: string;
|
|
103
|
-
/** Background color (for solid type) */
|
|
104
|
-
backgroundColor?: string;
|
|
105
|
-
/** Title font size (px) */
|
|
106
|
-
titleSize?: number;
|
|
107
|
-
/** Title font weight */
|
|
108
|
-
titleWeight?: number;
|
|
109
|
-
/** Title text color */
|
|
110
|
-
titleColor?: string;
|
|
111
|
-
/** Description font size (px) */
|
|
112
|
-
descriptionSize?: number;
|
|
113
|
-
/** Description text color */
|
|
114
|
-
descriptionColor?: string;
|
|
115
|
-
/** Site name font size (px) */
|
|
116
|
-
siteNameSize?: number;
|
|
117
|
-
/** Site name text color */
|
|
118
|
-
siteNameColor?: string;
|
|
119
|
-
/** Padding (px) */
|
|
120
|
-
padding?: number;
|
|
121
|
-
/** Logo size (px) */
|
|
122
|
-
logoSize?: number;
|
|
123
|
-
/** Show logo flag */
|
|
124
|
-
showLogo?: boolean;
|
|
125
|
-
/** Show site name flag */
|
|
126
|
-
showSiteName?: boolean;
|
|
127
|
-
/** Additional custom parameters */
|
|
128
|
-
[key: string]: string | number | boolean | undefined;
|
|
129
|
-
}
|
|
130
|
-
/**
|
|
131
|
-
* Options for generating OG image URL
|
|
132
|
-
*/
|
|
133
|
-
interface GenerateOgImageUrlOptions {
|
|
134
|
-
/**
|
|
135
|
-
* Base URL of the OG image API route
|
|
136
|
-
* @default 'https://djangocfg.com/api/og'
|
|
137
|
-
*/
|
|
138
|
-
baseUrl?: string;
|
|
139
|
-
/**
|
|
140
|
-
* If true, encode params as base64 for safer URLs
|
|
141
|
-
* @default true
|
|
142
|
-
*/
|
|
143
|
-
useBase64?: boolean;
|
|
144
|
-
}
|
|
145
|
-
/**
|
|
146
|
-
* Generate OG image URL with query parameters or base64 encoding
|
|
147
|
-
*
|
|
148
|
-
* @param params - URL parameters for the OG image
|
|
149
|
-
* @param options - Generation options (baseUrl, useBase64)
|
|
150
|
-
* @returns Complete OG image URL with encoded parameters
|
|
151
|
-
*
|
|
152
|
-
* @example
|
|
153
|
-
* ```typescript
|
|
154
|
-
* // Using default baseUrl (https://djangocfg.com/api/og)
|
|
155
|
-
* const url = generateOgImageUrl({
|
|
156
|
-
* title: 'My Page Title',
|
|
157
|
-
* description: 'Page description here',
|
|
158
|
-
* });
|
|
159
|
-
*
|
|
160
|
-
* // With custom baseUrl
|
|
161
|
-
* const url = generateOgImageUrl(
|
|
162
|
-
* { title: 'My Page' },
|
|
163
|
-
* { baseUrl: '/api/og' }
|
|
164
|
-
* );
|
|
165
|
-
* ```
|
|
166
|
-
*/
|
|
167
|
-
declare function generateOgImageUrl(params: OgImageUrlParams, options?: GenerateOgImageUrlOptions): string;
|
|
168
|
-
/**
|
|
169
|
-
* Get absolute OG image URL from relative path
|
|
170
|
-
*
|
|
171
|
-
* Useful for generating absolute URLs required by Open Graph meta tags
|
|
172
|
-
*
|
|
173
|
-
* @param relativePath - Relative OG image path (e.g., '/api/og?title=Hello')
|
|
174
|
-
* @param siteUrl - Base site URL (e.g., 'https://example.com')
|
|
175
|
-
* @returns Absolute URL
|
|
176
|
-
*
|
|
177
|
-
* @example
|
|
178
|
-
* ```typescript
|
|
179
|
-
* const absolute = getAbsoluteOgImageUrl(
|
|
180
|
-
* '/api/og?title=Hello',
|
|
181
|
-
* 'https://example.com'
|
|
182
|
-
* );
|
|
183
|
-
* // Result: https://example.com/api/og?title=Hello
|
|
184
|
-
* ```
|
|
185
|
-
*/
|
|
186
|
-
declare function getAbsoluteOgImageUrl(relativePath: string, siteUrl: string): string;
|
|
187
|
-
/**
|
|
188
|
-
* Create OG image URL builder with preset configuration
|
|
189
|
-
*
|
|
190
|
-
* Useful when you want to reuse the same base URL and default parameters
|
|
191
|
-
*
|
|
192
|
-
* @param defaults - Default parameters to merge with each URL generation
|
|
193
|
-
* @param options - Default options (baseUrl, useBase64)
|
|
194
|
-
* @returns URL builder function
|
|
195
|
-
*
|
|
196
|
-
* @example
|
|
197
|
-
* ```typescript
|
|
198
|
-
* const buildOgUrl = createOgImageUrlBuilder(
|
|
199
|
-
* { siteName: 'My Site', logo: '/logo.png' },
|
|
200
|
-
* { baseUrl: '/api/og' }
|
|
201
|
-
* );
|
|
202
|
-
*
|
|
203
|
-
* const url1 = buildOgUrl({ title: 'Page 1' });
|
|
204
|
-
* const url2 = buildOgUrl({ title: 'Page 2', description: 'Custom desc' });
|
|
205
|
-
* ```
|
|
206
|
-
*/
|
|
207
|
-
declare function createOgImageUrlBuilder(defaults?: Partial<OgImageUrlParams>, options?: GenerateOgImageUrlOptions): (params: OgImageUrlParams) => string;
|
|
208
|
-
/**
|
|
209
|
-
* Parse OG image URL parameters from a URL string (legacy query params)
|
|
210
|
-
*
|
|
211
|
-
* @param url - Full or relative URL with query parameters
|
|
212
|
-
* @returns Parsed parameters object
|
|
213
|
-
*
|
|
214
|
-
* @example
|
|
215
|
-
* ```typescript
|
|
216
|
-
* const params = parseOgImageUrl('/api/og?title=Hello&description=World');
|
|
217
|
-
* // Result: { title: 'Hello', description: 'World' }
|
|
218
|
-
* ```
|
|
219
|
-
*/
|
|
220
|
-
declare function parseOgImageUrl(url: string): Record<string, string>;
|
|
221
|
-
/**
|
|
222
|
-
* Parse OG image data from base64-encoded query parameter
|
|
223
|
-
*
|
|
224
|
-
* Use this in your API route to decode the `data` parameter
|
|
225
|
-
* Supports both base64 (new) and legacy query params format
|
|
226
|
-
*
|
|
227
|
-
* @param searchParams - URL search params or request object
|
|
228
|
-
* @returns Parsed OG image parameters
|
|
229
|
-
*
|
|
230
|
-
* @example
|
|
231
|
-
* ```typescript
|
|
232
|
-
* // In Next.js API route (pages/api/og.ts)
|
|
233
|
-
* export default function handler(req) {
|
|
234
|
-
* const params = parseOgImageData(req.query);
|
|
235
|
-
* // { title: 'Hello', description: 'World' }
|
|
236
|
-
* }
|
|
237
|
-
*
|
|
238
|
-
* // In Next.js App Router (app/api/og/route.ts)
|
|
239
|
-
* export async function GET(request: Request) {
|
|
240
|
-
* const { searchParams } = new URL(request.url);
|
|
241
|
-
* const params = parseOgImageData(Object.fromEntries(searchParams));
|
|
242
|
-
* // { title: 'Hello', description: 'World' }
|
|
243
|
-
* }
|
|
244
|
-
* ```
|
|
245
|
-
*/
|
|
246
|
-
declare function parseOgImageData(searchParams: Record<string, string | string[] | undefined> | URLSearchParams): Record<string, string>;
|
|
247
|
-
|
|
248
|
-
/**
|
|
249
|
-
* Metadata Utilities for OG Images
|
|
250
|
-
*
|
|
251
|
-
* Helpers to automatically add og:image to Next.js metadata
|
|
252
|
-
*/
|
|
253
|
-
|
|
254
|
-
/**
|
|
255
|
-
* Options for generating OG image metadata
|
|
256
|
-
*/
|
|
257
|
-
interface AppMetadataOptions {
|
|
258
|
-
/** Base URL of the OG image API route (e.g., '/api/og') */
|
|
259
|
-
ogImageBaseUrl?: string;
|
|
260
|
-
/** Site URL for absolute URLs (e.g., 'https://example.com') */
|
|
261
|
-
siteUrl?: string;
|
|
262
|
-
/** Default parameters to merge with page-specific params */
|
|
263
|
-
defaultParams?: Partial<OgImageUrlParams>;
|
|
264
|
-
/** Whether to use base64 encoding (default: true) */
|
|
265
|
-
useBase64?: boolean;
|
|
266
|
-
/** Favicon URL (e.g., '/favicon.png') - automatically added to metadata.icons */
|
|
267
|
-
favicon?: string;
|
|
268
|
-
/** Apple touch icon URL (e.g., '/apple-icon.png') - automatically added to metadata.icons */
|
|
269
|
-
appleIcon?: string;
|
|
270
|
-
}
|
|
271
|
-
declare function generateAppMetadata(metadata: Metadata, ogImageParams?: Partial<OgImageUrlParams>, options?: AppMetadataOptions): Metadata;
|
|
272
|
-
/**
|
|
273
|
-
* Create OG image metadata generator with preset configuration
|
|
274
|
-
*
|
|
275
|
-
* Useful when you want to reuse the same configuration across multiple pages
|
|
276
|
-
*
|
|
277
|
-
* @param options - Configuration options
|
|
278
|
-
* @returns Metadata generator function
|
|
279
|
-
*
|
|
280
|
-
* @example
|
|
281
|
-
* ```typescript
|
|
282
|
-
* // In a shared file (e.g., lib/metadata.ts)
|
|
283
|
-
* import { createAppMetadataGenerator } from '@djangocfg/nextjs/og-image';
|
|
284
|
-
* import { settings } from '@/core/settings';
|
|
285
|
-
*
|
|
286
|
-
* export const generateMetadata = createAppMetadataGenerator({
|
|
287
|
-
* ogImageBaseUrl: '/api/og',
|
|
288
|
-
* siteUrl: settings.app.siteUrl,
|
|
289
|
-
* favicon: settings.app.icons.favicon,
|
|
290
|
-
* appleIcon: settings.app.icons.logo192,
|
|
291
|
-
* defaultParams: {
|
|
292
|
-
* siteName: settings.app.name,
|
|
293
|
-
* logo: settings.app.icons.logoVector,
|
|
294
|
-
* },
|
|
295
|
-
* });
|
|
296
|
-
*
|
|
297
|
-
* // In page.tsx
|
|
298
|
-
* import { generateMetadata } from '@/lib/metadata';
|
|
299
|
-
*
|
|
300
|
-
* export const metadata = generateMetadata({
|
|
301
|
-
* title: 'My Page',
|
|
302
|
-
* description: 'Description',
|
|
303
|
-
* });
|
|
304
|
-
* ```
|
|
305
|
-
*/
|
|
306
|
-
declare function createAppMetadataGenerator(options: AppMetadataOptions): (metadata: Metadata, ogImageParams?: Partial<OgImageUrlParams>) => Metadata;
|
|
307
|
-
|
|
308
|
-
export { type AppMetadataOptions, type FontConfig, type OgImageUrlParams, createAppMetadataGenerator, createFontLoader, createOgImageUrlBuilder, decodeBase64, encodeBase64, generateAppMetadata, generateOgImageUrl, getAbsoluteOgImageUrl, loadGoogleFont, loadGoogleFonts, parseOgImageData, parseOgImageUrl };
|
|
@@ -1,327 +0,0 @@
|
|
|
1
|
-
// src/og-image/utils/fonts.ts
|
|
2
|
-
async function loadGoogleFont(font, text, weight = 700) {
|
|
3
|
-
let url = `https://fonts.googleapis.com/css2?family=${font}:wght@${weight}`;
|
|
4
|
-
if (text) {
|
|
5
|
-
url += `&text=${encodeURIComponent(text)}`;
|
|
6
|
-
}
|
|
7
|
-
try {
|
|
8
|
-
const css = await fetch(url, {
|
|
9
|
-
headers: {
|
|
10
|
-
// Required to get TTF format instead of WOFF2
|
|
11
|
-
"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"
|
|
12
|
-
}
|
|
13
|
-
}).then((res) => res.text());
|
|
14
|
-
const resource = css.match(/src: url\((.+)\) format\('(opentype|truetype)'\)/);
|
|
15
|
-
if (!resource || !resource[1]) {
|
|
16
|
-
throw new Error(`Failed to parse font URL from CSS for font: ${font}`);
|
|
17
|
-
}
|
|
18
|
-
const response = await fetch(resource[1]);
|
|
19
|
-
if (response.status !== 200) {
|
|
20
|
-
throw new Error(`Failed to fetch font data: HTTP ${response.status}`);
|
|
21
|
-
}
|
|
22
|
-
return await response.arrayBuffer();
|
|
23
|
-
} catch (error) {
|
|
24
|
-
console.error(`Error loading Google Font "${font}":`, error);
|
|
25
|
-
throw new Error(`Failed to load font "${font}": ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
async function loadGoogleFonts(fonts) {
|
|
29
|
-
const fontConfigs = await Promise.all(
|
|
30
|
-
fonts.map(async ({ family, weight = 700, style = "normal", text }) => {
|
|
31
|
-
const data = await loadGoogleFont(family, text, weight);
|
|
32
|
-
return {
|
|
33
|
-
name: family,
|
|
34
|
-
weight,
|
|
35
|
-
style,
|
|
36
|
-
data
|
|
37
|
-
};
|
|
38
|
-
})
|
|
39
|
-
);
|
|
40
|
-
return fontConfigs;
|
|
41
|
-
}
|
|
42
|
-
function createFontLoader() {
|
|
43
|
-
const cache = /* @__PURE__ */ new Map();
|
|
44
|
-
return {
|
|
45
|
-
/**
|
|
46
|
-
* Load a font with caching
|
|
47
|
-
*/
|
|
48
|
-
async load(family, weight = 700, text) {
|
|
49
|
-
const cacheKey = `${family}-${weight}-${text || "all"}`;
|
|
50
|
-
if (!cache.has(cacheKey)) {
|
|
51
|
-
cache.set(cacheKey, loadGoogleFont(family, text, weight));
|
|
52
|
-
}
|
|
53
|
-
return cache.get(cacheKey);
|
|
54
|
-
},
|
|
55
|
-
/**
|
|
56
|
-
* Clear the cache
|
|
57
|
-
*/
|
|
58
|
-
clear() {
|
|
59
|
-
cache.clear();
|
|
60
|
-
},
|
|
61
|
-
/**
|
|
62
|
-
* Get cache size
|
|
63
|
-
*/
|
|
64
|
-
size() {
|
|
65
|
-
return cache.size;
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// src/og-image/utils/url.ts
|
|
71
|
-
var DEFAULT_OG_IMAGE_BASE_URL = "https://djangocfg.com/api/og";
|
|
72
|
-
function encodeBase64(str) {
|
|
73
|
-
if (typeof Buffer !== "undefined") {
|
|
74
|
-
return Buffer.from(str, "utf-8").toString("base64");
|
|
75
|
-
}
|
|
76
|
-
return btoa(unescape(encodeURIComponent(str)));
|
|
77
|
-
}
|
|
78
|
-
function decodeBase64(str) {
|
|
79
|
-
if (typeof Buffer !== "undefined") {
|
|
80
|
-
return Buffer.from(str, "base64").toString("utf-8");
|
|
81
|
-
}
|
|
82
|
-
try {
|
|
83
|
-
const binaryString = atob(str);
|
|
84
|
-
return decodeURIComponent(
|
|
85
|
-
binaryString.split("").map((c) => "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2)).join("")
|
|
86
|
-
);
|
|
87
|
-
} catch (error) {
|
|
88
|
-
return decodeURIComponent(escape(atob(str)));
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
function generateOgImageUrl(params, options = {}) {
|
|
92
|
-
const {
|
|
93
|
-
baseUrl = DEFAULT_OG_IMAGE_BASE_URL,
|
|
94
|
-
useBase64 = true
|
|
95
|
-
} = options;
|
|
96
|
-
if (useBase64) {
|
|
97
|
-
const cleanParams = {};
|
|
98
|
-
Object.entries(params).forEach(([key, value]) => {
|
|
99
|
-
if (value !== void 0 && value !== null && value !== "") {
|
|
100
|
-
cleanParams[key] = value;
|
|
101
|
-
}
|
|
102
|
-
});
|
|
103
|
-
const jsonString = JSON.stringify(cleanParams);
|
|
104
|
-
const base64Data = encodeBase64(jsonString);
|
|
105
|
-
return `${baseUrl}/${base64Data}/`;
|
|
106
|
-
} else {
|
|
107
|
-
const searchParams = new URLSearchParams();
|
|
108
|
-
Object.entries(params).forEach(([key, value]) => {
|
|
109
|
-
if (value !== void 0 && value !== null && value !== "") {
|
|
110
|
-
searchParams.append(key, String(value));
|
|
111
|
-
}
|
|
112
|
-
});
|
|
113
|
-
const query = searchParams.toString();
|
|
114
|
-
return query ? `${baseUrl}?${query}` : baseUrl;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
function getAbsoluteOgImageUrl(relativePath, siteUrl) {
|
|
118
|
-
if (relativePath.startsWith("http://") || relativePath.startsWith("https://")) {
|
|
119
|
-
return relativePath;
|
|
120
|
-
}
|
|
121
|
-
const cleanSiteUrl = siteUrl.replace(/\/$/, "");
|
|
122
|
-
const cleanPath = relativePath.startsWith("/") ? relativePath : `/${relativePath}`;
|
|
123
|
-
return `${cleanSiteUrl}${cleanPath}`;
|
|
124
|
-
}
|
|
125
|
-
function createOgImageUrlBuilder(defaults = {}, options = {}) {
|
|
126
|
-
return (params) => {
|
|
127
|
-
return generateOgImageUrl(
|
|
128
|
-
{ ...defaults, ...params },
|
|
129
|
-
options
|
|
130
|
-
);
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
function parseOgImageUrl(url) {
|
|
134
|
-
try {
|
|
135
|
-
const urlObj = new URL(url, "http://dummy.com");
|
|
136
|
-
const params = {};
|
|
137
|
-
urlObj.searchParams.forEach((value, key) => {
|
|
138
|
-
params[key] = value;
|
|
139
|
-
});
|
|
140
|
-
return params;
|
|
141
|
-
} catch {
|
|
142
|
-
return {};
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
function parseOgImageData(searchParams) {
|
|
146
|
-
try {
|
|
147
|
-
let params;
|
|
148
|
-
if (searchParams instanceof URLSearchParams) {
|
|
149
|
-
params = {};
|
|
150
|
-
for (const [key, value] of searchParams.entries()) {
|
|
151
|
-
params[key] = value;
|
|
152
|
-
}
|
|
153
|
-
} else {
|
|
154
|
-
params = searchParams;
|
|
155
|
-
}
|
|
156
|
-
if (process.env.NODE_ENV === "development") {
|
|
157
|
-
console.log("[parseOgImageData] Input params keys:", Object.keys(params));
|
|
158
|
-
console.log("[parseOgImageData] Input params:", params);
|
|
159
|
-
}
|
|
160
|
-
const dataParam = params.data;
|
|
161
|
-
if (dataParam && typeof dataParam === "string" && dataParam.trim() !== "") {
|
|
162
|
-
if (process.env.NODE_ENV === "development") {
|
|
163
|
-
console.log("[parseOgImageData] Found data param, length:", dataParam.length);
|
|
164
|
-
}
|
|
165
|
-
try {
|
|
166
|
-
const decoded = decodeBase64(dataParam);
|
|
167
|
-
if (process.env.NODE_ENV === "development") {
|
|
168
|
-
console.log("[parseOgImageData] Decoded string:", decoded.substring(0, 100));
|
|
169
|
-
}
|
|
170
|
-
const parsed = JSON.parse(decoded);
|
|
171
|
-
if (process.env.NODE_ENV === "development") {
|
|
172
|
-
console.log("[parseOgImageData] Parsed JSON:", parsed);
|
|
173
|
-
}
|
|
174
|
-
const result2 = {};
|
|
175
|
-
for (const [key, value] of Object.entries(parsed)) {
|
|
176
|
-
if (value !== void 0 && value !== null) {
|
|
177
|
-
result2[key] = String(value);
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
if (process.env.NODE_ENV === "development") {
|
|
181
|
-
console.log("[parseOgImageData] Result:", result2);
|
|
182
|
-
}
|
|
183
|
-
return result2;
|
|
184
|
-
} catch (decodeError) {
|
|
185
|
-
console.error("[parseOgImageData] Error decoding/parsing data param:", decodeError);
|
|
186
|
-
if (decodeError instanceof Error) {
|
|
187
|
-
console.error("[parseOgImageData] Error message:", decodeError.message);
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
} else {
|
|
191
|
-
if (process.env.NODE_ENV === "development") {
|
|
192
|
-
console.log("[parseOgImageData] No data param found or empty");
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
const result = {};
|
|
196
|
-
for (const [key, value] of Object.entries(params)) {
|
|
197
|
-
if (key !== "data" && value !== void 0 && value !== null) {
|
|
198
|
-
result[key] = Array.isArray(value) ? value[0] : String(value);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
if (process.env.NODE_ENV === "development") {
|
|
202
|
-
console.log("[parseOgImageData] Fallback result:", result);
|
|
203
|
-
}
|
|
204
|
-
return result;
|
|
205
|
-
} catch (error) {
|
|
206
|
-
console.error("[parseOgImageData] Unexpected error:", error);
|
|
207
|
-
return {};
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
// src/og-image/utils/metadata.ts
|
|
212
|
-
function extractTitle(metadata) {
|
|
213
|
-
if (typeof metadata.title === "string") {
|
|
214
|
-
return metadata.title;
|
|
215
|
-
}
|
|
216
|
-
if (metadata.title) {
|
|
217
|
-
if ("default" in metadata.title) {
|
|
218
|
-
return metadata.title.default;
|
|
219
|
-
}
|
|
220
|
-
if ("absolute" in metadata.title) {
|
|
221
|
-
return metadata.title.absolute;
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
return "";
|
|
225
|
-
}
|
|
226
|
-
function extractDescription(metadata) {
|
|
227
|
-
if (typeof metadata.description === "string") {
|
|
228
|
-
return metadata.description;
|
|
229
|
-
}
|
|
230
|
-
return "";
|
|
231
|
-
}
|
|
232
|
-
function getSiteUrl() {
|
|
233
|
-
if (typeof process !== "undefined" && process.env.NEXT_PUBLIC_SITE_URL) {
|
|
234
|
-
return process.env.NEXT_PUBLIC_SITE_URL;
|
|
235
|
-
}
|
|
236
|
-
return "";
|
|
237
|
-
}
|
|
238
|
-
function generateAppMetadata(metadata, ogImageParams, options = {}) {
|
|
239
|
-
const {
|
|
240
|
-
ogImageBaseUrl = "https://djangocfg.com/api/og",
|
|
241
|
-
siteUrl: providedSiteUrl,
|
|
242
|
-
defaultParams = {},
|
|
243
|
-
useBase64 = true,
|
|
244
|
-
favicon,
|
|
245
|
-
appleIcon
|
|
246
|
-
} = options;
|
|
247
|
-
const siteUrl = providedSiteUrl && providedSiteUrl !== "undefined" ? providedSiteUrl : getSiteUrl();
|
|
248
|
-
const extractedTitle = extractTitle(metadata);
|
|
249
|
-
const extractedDescription = extractDescription(metadata);
|
|
250
|
-
const finalOgImageParams = {
|
|
251
|
-
...defaultParams,
|
|
252
|
-
title: ogImageParams?.title || extractedTitle || defaultParams.title || "",
|
|
253
|
-
description: ogImageParams?.description || extractedDescription || defaultParams.description || "",
|
|
254
|
-
...ogImageParams
|
|
255
|
-
};
|
|
256
|
-
const imageAlt = finalOgImageParams.title || finalOgImageParams.siteName;
|
|
257
|
-
const relativeOgImageUrl = generateOgImageUrl(
|
|
258
|
-
finalOgImageParams,
|
|
259
|
-
{ baseUrl: ogImageBaseUrl, useBase64 }
|
|
260
|
-
);
|
|
261
|
-
const ogImageUrl = siteUrl ? getAbsoluteOgImageUrl(relativeOgImageUrl, siteUrl) : relativeOgImageUrl;
|
|
262
|
-
const existingOgImages = metadata.openGraph?.images ? Array.isArray(metadata.openGraph.images) ? metadata.openGraph.images : [metadata.openGraph.images] : [];
|
|
263
|
-
const existingTwitterImages = metadata.twitter?.images ? Array.isArray(metadata.twitter.images) ? metadata.twitter.images : [metadata.twitter.images] : [];
|
|
264
|
-
const finalMetadata = {
|
|
265
|
-
...metadata,
|
|
266
|
-
openGraph: {
|
|
267
|
-
...metadata.openGraph,
|
|
268
|
-
images: [
|
|
269
|
-
...existingOgImages,
|
|
270
|
-
{
|
|
271
|
-
url: ogImageUrl,
|
|
272
|
-
width: 1200,
|
|
273
|
-
height: 630,
|
|
274
|
-
alt: imageAlt
|
|
275
|
-
}
|
|
276
|
-
]
|
|
277
|
-
},
|
|
278
|
-
twitter: {
|
|
279
|
-
...metadata.twitter,
|
|
280
|
-
card: "summary_large_image",
|
|
281
|
-
images: [
|
|
282
|
-
...existingTwitterImages,
|
|
283
|
-
{
|
|
284
|
-
url: ogImageUrl,
|
|
285
|
-
alt: imageAlt
|
|
286
|
-
}
|
|
287
|
-
]
|
|
288
|
-
}
|
|
289
|
-
};
|
|
290
|
-
if (!finalMetadata.metadataBase && siteUrl) {
|
|
291
|
-
if (siteUrl.startsWith("http://") || siteUrl.startsWith("https://")) {
|
|
292
|
-
try {
|
|
293
|
-
finalMetadata.metadataBase = new URL(siteUrl);
|
|
294
|
-
} catch (e) {
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
if (favicon || appleIcon) {
|
|
299
|
-
const existingIcons = metadata.icons && typeof metadata.icons === "object" && !Array.isArray(metadata.icons) ? metadata.icons : {};
|
|
300
|
-
finalMetadata.icons = {
|
|
301
|
-
...existingIcons,
|
|
302
|
-
...favicon && { icon: favicon },
|
|
303
|
-
...appleIcon && { apple: appleIcon }
|
|
304
|
-
};
|
|
305
|
-
}
|
|
306
|
-
return finalMetadata;
|
|
307
|
-
}
|
|
308
|
-
function createAppMetadataGenerator(options) {
|
|
309
|
-
return (metadata, ogImageParams) => {
|
|
310
|
-
return generateAppMetadata(metadata, ogImageParams, options);
|
|
311
|
-
};
|
|
312
|
-
}
|
|
313
|
-
export {
|
|
314
|
-
createAppMetadataGenerator,
|
|
315
|
-
createFontLoader,
|
|
316
|
-
createOgImageUrlBuilder,
|
|
317
|
-
decodeBase64,
|
|
318
|
-
encodeBase64,
|
|
319
|
-
generateAppMetadata,
|
|
320
|
-
generateOgImageUrl,
|
|
321
|
-
getAbsoluteOgImageUrl,
|
|
322
|
-
loadGoogleFont,
|
|
323
|
-
loadGoogleFonts,
|
|
324
|
-
parseOgImageData,
|
|
325
|
-
parseOgImageUrl
|
|
326
|
-
};
|
|
327
|
-
//# sourceMappingURL=index.mjs.map
|