ayezee-astro-cms 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cloudinary-utils.d.ts +54 -0
- package/dist/cloudinary-utils.js +152 -0
- package/dist/cms-helper.d.ts +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/package.json +1 -1
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloudinary URL helpers for optimized image delivery
|
|
3
|
+
*
|
|
4
|
+
* Upload presets store originals at full quality with NO transformations.
|
|
5
|
+
* Transformations are applied dynamically via URL at delivery time.
|
|
6
|
+
*
|
|
7
|
+
* Presets in Cloudinary dashboard:
|
|
8
|
+
* - ayezee_gallery: For gallery/fan-wall images → folder: gallery-images
|
|
9
|
+
* - ayezee_optimized: For project logos → folder: project-logos
|
|
10
|
+
*/
|
|
11
|
+
type CloudinaryTransformOptions = {
|
|
12
|
+
width?: number;
|
|
13
|
+
height?: number;
|
|
14
|
+
quality?: number | "auto" | "auto:best" | "auto:good" | "auto:eco" | "auto:low";
|
|
15
|
+
format?: "auto" | "webp" | "avif" | "jpg" | "png";
|
|
16
|
+
crop?: "fill" | "fit" | "limit" | "scale" | "thumb" | "pad";
|
|
17
|
+
gravity?: "auto" | "face" | "center" | "north" | "south" | "east" | "west";
|
|
18
|
+
dpr?: number | "auto";
|
|
19
|
+
aspectRatio?: string;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Build a Cloudinary URL with transformations
|
|
23
|
+
*/
|
|
24
|
+
export declare function buildCloudinaryUrl(url: string, options?: CloudinaryTransformOptions): string;
|
|
25
|
+
/**
|
|
26
|
+
* Generate srcset for responsive images
|
|
27
|
+
*/
|
|
28
|
+
export declare function buildCloudinarySrcSet(url: string, widths: number[], quality?: CloudinaryTransformOptions["quality"]): string;
|
|
29
|
+
/**
|
|
30
|
+
* Preset configurations for common use cases
|
|
31
|
+
*/
|
|
32
|
+
export declare const CLOUDINARY_PRESETS: {
|
|
33
|
+
readonly logo: {
|
|
34
|
+
readonly default: (url: string) => string;
|
|
35
|
+
readonly thumb: (url: string) => string;
|
|
36
|
+
readonly large: (url: string) => string;
|
|
37
|
+
};
|
|
38
|
+
readonly gallery: {
|
|
39
|
+
readonly src: (url: string) => string;
|
|
40
|
+
readonly srcset: (url: string) => string;
|
|
41
|
+
readonly hero: (url: string) => string;
|
|
42
|
+
readonly thumb: (url: string) => string;
|
|
43
|
+
};
|
|
44
|
+
readonly avatar: (url: string) => string;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Helper to check if a URL is from Cloudinary
|
|
48
|
+
*/
|
|
49
|
+
export declare function isCloudinaryUrl(url: string): boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Extract public ID from Cloudinary URL
|
|
52
|
+
*/
|
|
53
|
+
export declare function getCloudinaryPublicId(url: string): string | null;
|
|
54
|
+
export {};
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloudinary URL helpers for optimized image delivery
|
|
3
|
+
*
|
|
4
|
+
* Upload presets store originals at full quality with NO transformations.
|
|
5
|
+
* Transformations are applied dynamically via URL at delivery time.
|
|
6
|
+
*
|
|
7
|
+
* Presets in Cloudinary dashboard:
|
|
8
|
+
* - ayezee_gallery: For gallery/fan-wall images → folder: gallery-images
|
|
9
|
+
* - ayezee_optimized: For project logos → folder: project-logos
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Build a Cloudinary URL with transformations
|
|
13
|
+
*/
|
|
14
|
+
export function buildCloudinaryUrl(url, options = {}) {
|
|
15
|
+
if (!url || !url.includes("cloudinary.com"))
|
|
16
|
+
return url;
|
|
17
|
+
const uploadIndex = url.indexOf("/upload/");
|
|
18
|
+
if (uploadIndex === -1)
|
|
19
|
+
return url;
|
|
20
|
+
const baseUrl = url.substring(0, uploadIndex + 8); // includes '/upload/'
|
|
21
|
+
const imagePath = url.substring(uploadIndex + 8);
|
|
22
|
+
const transforms = [];
|
|
23
|
+
// Format (most important for file size + quality)
|
|
24
|
+
if (options.format !== undefined) {
|
|
25
|
+
transforms.push(`f_${options.format}`);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
transforms.push("f_auto"); // Auto-select WebP/AVIF for modern browsers
|
|
29
|
+
}
|
|
30
|
+
// Quality
|
|
31
|
+
if (options.quality !== undefined) {
|
|
32
|
+
transforms.push(`q_${options.quality}`);
|
|
33
|
+
}
|
|
34
|
+
// Device pixel ratio (retina support)
|
|
35
|
+
if (options.dpr !== undefined) {
|
|
36
|
+
transforms.push(`dpr_${options.dpr}`);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
transforms.push("dpr_auto"); // Auto-detect retina displays
|
|
40
|
+
}
|
|
41
|
+
// Dimensions
|
|
42
|
+
if (options.width) {
|
|
43
|
+
transforms.push(`w_${options.width}`);
|
|
44
|
+
}
|
|
45
|
+
if (options.height) {
|
|
46
|
+
transforms.push(`h_${options.height}`);
|
|
47
|
+
}
|
|
48
|
+
if (options.aspectRatio) {
|
|
49
|
+
transforms.push(`ar_${options.aspectRatio}`);
|
|
50
|
+
}
|
|
51
|
+
// Cropping
|
|
52
|
+
if (options.crop) {
|
|
53
|
+
transforms.push(`c_${options.crop}`);
|
|
54
|
+
}
|
|
55
|
+
else if (options.width || options.height) {
|
|
56
|
+
transforms.push("c_limit"); // Don't upscale beyond original
|
|
57
|
+
}
|
|
58
|
+
// Gravity (for cropping)
|
|
59
|
+
if (options.gravity) {
|
|
60
|
+
transforms.push(`g_${options.gravity}`);
|
|
61
|
+
}
|
|
62
|
+
return `${baseUrl}${transforms.join(",")}/${imagePath}`;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Generate srcset for responsive images
|
|
66
|
+
*/
|
|
67
|
+
export function buildCloudinarySrcSet(url, widths, quality = "auto:good") {
|
|
68
|
+
return widths
|
|
69
|
+
.map((width) => `${buildCloudinaryUrl(url, { width, quality })} ${width}w`)
|
|
70
|
+
.join(", ");
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Preset configurations for common use cases
|
|
74
|
+
*/
|
|
75
|
+
export const CLOUDINARY_PRESETS = {
|
|
76
|
+
// Project logos
|
|
77
|
+
logo: {
|
|
78
|
+
// Standard logo display
|
|
79
|
+
default: (url) => buildCloudinaryUrl(url, {
|
|
80
|
+
width: 400,
|
|
81
|
+
quality: "auto:good",
|
|
82
|
+
crop: "limit",
|
|
83
|
+
}),
|
|
84
|
+
// Small thumbnail (for lists)
|
|
85
|
+
thumb: (url) => buildCloudinaryUrl(url, {
|
|
86
|
+
width: 100,
|
|
87
|
+
height: 100,
|
|
88
|
+
quality: "auto:good",
|
|
89
|
+
crop: "fill",
|
|
90
|
+
gravity: "center",
|
|
91
|
+
}),
|
|
92
|
+
// Large (for hero sections)
|
|
93
|
+
large: (url) => buildCloudinaryUrl(url, {
|
|
94
|
+
width: 800,
|
|
95
|
+
quality: "auto:best",
|
|
96
|
+
crop: "limit",
|
|
97
|
+
}),
|
|
98
|
+
},
|
|
99
|
+
// Gallery images - high quality, responsive
|
|
100
|
+
gallery: {
|
|
101
|
+
// Default src (mobile-first, good balance)
|
|
102
|
+
src: (url) => buildCloudinaryUrl(url, {
|
|
103
|
+
width: 1000,
|
|
104
|
+
quality: "auto:good",
|
|
105
|
+
crop: "limit",
|
|
106
|
+
}),
|
|
107
|
+
// Full srcset for responsive images
|
|
108
|
+
srcset: (url) => buildCloudinarySrcSet(url, [600, 1000, 1400, 1800, 2400], // Wide range for all devices + retina
|
|
109
|
+
"auto:good"),
|
|
110
|
+
// Hero/featured images (highest quality)
|
|
111
|
+
hero: (url) => buildCloudinaryUrl(url, {
|
|
112
|
+
width: 2400,
|
|
113
|
+
quality: "auto:best",
|
|
114
|
+
crop: "limit",
|
|
115
|
+
}),
|
|
116
|
+
// Thumbnail (for grid previews in admin)
|
|
117
|
+
thumb: (url) => buildCloudinaryUrl(url, {
|
|
118
|
+
width: 400,
|
|
119
|
+
height: 300,
|
|
120
|
+
quality: "auto:eco",
|
|
121
|
+
crop: "fill",
|
|
122
|
+
gravity: "auto",
|
|
123
|
+
}),
|
|
124
|
+
},
|
|
125
|
+
// Avatar/profile images
|
|
126
|
+
avatar: (url) => buildCloudinaryUrl(url, {
|
|
127
|
+
width: 200,
|
|
128
|
+
height: 200,
|
|
129
|
+
quality: "auto:good",
|
|
130
|
+
crop: "fill",
|
|
131
|
+
gravity: "face",
|
|
132
|
+
}),
|
|
133
|
+
};
|
|
134
|
+
/**
|
|
135
|
+
* Helper to check if a URL is from Cloudinary
|
|
136
|
+
*/
|
|
137
|
+
export function isCloudinaryUrl(url) {
|
|
138
|
+
return url.includes("res.cloudinary.com") || url.includes("cloudinary.com");
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Extract public ID from Cloudinary URL
|
|
142
|
+
*/
|
|
143
|
+
export function getCloudinaryPublicId(url) {
|
|
144
|
+
if (!isCloudinaryUrl(url))
|
|
145
|
+
return null;
|
|
146
|
+
const uploadIndex = url.indexOf("/upload/");
|
|
147
|
+
if (uploadIndex === -1)
|
|
148
|
+
return null;
|
|
149
|
+
const pathAfterUpload = url.substring(uploadIndex + 8);
|
|
150
|
+
// Remove file extension
|
|
151
|
+
return pathAfterUpload.replace(/\.[^.]+$/, "");
|
|
152
|
+
}
|
package/dist/cms-helper.d.ts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED