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.
@@ -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
+ }
@@ -48,7 +48,7 @@ export interface CachedModule {
48
48
  instanceKey: string;
49
49
  label: string;
50
50
  slug: string;
51
- dataType: 'collection' | 'singleton' | 'submissions';
51
+ dataType: string;
52
52
  category: string;
53
53
  description?: string;
54
54
  icon?: string;
package/dist/index.d.ts CHANGED
@@ -6,5 +6,6 @@
6
6
  * @packageDocumentation
7
7
  */
8
8
  export * from './cms-helper.js';
9
+ export * from './cloudinary-utils.js';
9
10
  export { ayezeeCms, type AyezeeCmsOptions } from './integration.js';
10
11
  export { ayezeeCms as default } from './integration.js';
package/dist/index.js CHANGED
@@ -7,6 +7,8 @@
7
7
  */
8
8
  // Export CMS helper functions and types
9
9
  export * from './cms-helper.js';
10
+ // Export Cloudinary utilities
11
+ export * from './cloudinary-utils.js';
10
12
  // Export integration
11
13
  export { ayezeeCms } from './integration.js';
12
14
  // Default export
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ayezee-astro-cms",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "AyeZee CMS integration for Astro with automatic data fetching, form handling, and validation",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",