@simple-photo-gallery/common 1.0.5 → 2.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,138 @@
1
+ /* PhotoSwipe CSS Custom Properties - Override these in your theme */
2
+ :root {
3
+ /* Background */
4
+ --pswp-bg-color: rgba(0, 0, 0, 1);
5
+
6
+ /* Buttons */
7
+ --pswp-button-color: white;
8
+ --pswp-button-opacity: 0.8;
9
+ --pswp-button-opacity-hover: 1;
10
+
11
+ /* Counter */
12
+ --pswp-counter-color: white;
13
+ --pswp-counter-font-size: 1rem;
14
+
15
+ /* Caption container */
16
+ --pswp-caption-bg: rgba(128, 128, 128, 0.3);
17
+ --pswp-caption-blur: 8px;
18
+ --pswp-caption-color: white;
19
+ --pswp-caption-padding: 16px;
20
+ --pswp-caption-padding-mobile: 8px 16px;
21
+ --pswp-caption-radius: 16px;
22
+ --pswp-caption-margin: 1rem;
23
+ --pswp-caption-margin-mobile: 8px 0;
24
+ --pswp-caption-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
25
+ --pswp-caption-max-width: 42rem;
26
+
27
+ /* Caption typography */
28
+ --pswp-caption-title-size: 1.5rem;
29
+ --pswp-caption-title-weight: 600;
30
+ --pswp-caption-text-size: 1rem;
31
+ --pswp-caption-text-size-mobile: 0.8rem;
32
+ --pswp-caption-description-size: 0.95rem;
33
+
34
+ /* Animation */
35
+ --pswp-slide-animation-duration: 0.6s;
36
+ --pswp-slide-animation-easing: ease-out;
37
+ }
38
+
39
+ /* PhotoSwipe enhanced styles */
40
+ .pswp .pswp__bg {
41
+ --pswp-bg: var(--pswp-bg-color);
42
+ }
43
+
44
+ .pswp__counter {
45
+ color: var(--pswp-counter-color);
46
+ font-size: var(--pswp-counter-font-size);
47
+ }
48
+
49
+ .pswp__button {
50
+ color: var(--pswp-button-color);
51
+ opacity: var(--pswp-button-opacity);
52
+ transition: opacity 0.3s ease;
53
+ }
54
+
55
+ .pswp__button:hover {
56
+ opacity: var(--pswp-button-opacity-hover);
57
+ }
58
+
59
+ .pswp__caption {
60
+ position: absolute;
61
+ bottom: 0;
62
+ left: 50%;
63
+ transform: translateX(-50%);
64
+ }
65
+
66
+ @media (max-width: 768px) {
67
+ .pswp__caption {
68
+ width: calc(100% - 16px);
69
+ }
70
+ }
71
+
72
+ .pswp__caption .image-caption {
73
+ text-align: left;
74
+ background: var(--pswp-caption-bg);
75
+ backdrop-filter: blur(var(--pswp-caption-blur));
76
+ -webkit-backdrop-filter: blur(var(--pswp-caption-blur));
77
+ color: var(--pswp-caption-color);
78
+ padding: var(--pswp-caption-padding);
79
+ border-radius: var(--pswp-caption-radius);
80
+ margin: var(--pswp-caption-margin);
81
+ box-shadow: var(--pswp-caption-shadow);
82
+ }
83
+
84
+ @media (max-width: 768px) {
85
+ .pswp__caption .image-caption {
86
+ padding: var(--pswp-caption-padding-mobile);
87
+ font-size: var(--pswp-caption-text-size-mobile);
88
+ margin: var(--pswp-caption-margin-mobile);
89
+ }
90
+ }
91
+
92
+ .pswp__caption__center {
93
+ text-align: center;
94
+ max-width: var(--pswp-caption-max-width);
95
+ margin: 0 auto;
96
+ }
97
+
98
+ .pswp__caption h3 {
99
+ font-size: var(--pswp-caption-title-size);
100
+ font-weight: var(--pswp-caption-title-weight);
101
+ margin-bottom: 0.5rem;
102
+ text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
103
+ }
104
+
105
+ .pswp__caption p {
106
+ font-size: var(--pswp-caption-text-size);
107
+ opacity: 0.95;
108
+ line-height: 1.6;
109
+ text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
110
+ font-weight: 400;
111
+ }
112
+
113
+ .pswp__caption .description {
114
+ display: block;
115
+ margin-top: 0.5rem;
116
+ font-size: var(--pswp-caption-description-size);
117
+ opacity: 0.9;
118
+ font-weight: 300;
119
+ font-style: italic;
120
+ }
121
+
122
+ /* Slide-in animation */
123
+ .pswp__img {
124
+ opacity: 0;
125
+ }
126
+
127
+ .pswp__img--in-viewport {
128
+ animation: pswp-slideIn var(--pswp-slide-animation-duration) var(--pswp-slide-animation-easing) forwards;
129
+ }
130
+
131
+ @keyframes pswp-slideIn {
132
+ from {
133
+ opacity: 0;
134
+ }
135
+ to {
136
+ opacity: 1;
137
+ }
138
+ }
@@ -0,0 +1,442 @@
1
+ import { z } from 'zod';
2
+
3
+ /** Zod schema for header image variants allowing explicit specification of responsive hero images */
4
+ declare const HeaderImageVariantsSchema: z.ZodObject<{
5
+ portrait: z.ZodOptional<z.ZodObject<{
6
+ avif: z.ZodOptional<z.ZodObject<{
7
+ 360: z.ZodOptional<z.ZodString>;
8
+ 480: z.ZodOptional<z.ZodString>;
9
+ 720: z.ZodOptional<z.ZodString>;
10
+ 1080: z.ZodOptional<z.ZodString>;
11
+ }, z.core.$strip>>;
12
+ jpg: z.ZodOptional<z.ZodObject<{
13
+ 360: z.ZodOptional<z.ZodString>;
14
+ 480: z.ZodOptional<z.ZodString>;
15
+ 720: z.ZodOptional<z.ZodString>;
16
+ 1080: z.ZodOptional<z.ZodString>;
17
+ }, z.core.$strip>>;
18
+ }, z.core.$strip>>;
19
+ landscape: z.ZodOptional<z.ZodObject<{
20
+ avif: z.ZodOptional<z.ZodObject<{
21
+ 640: z.ZodOptional<z.ZodString>;
22
+ 960: z.ZodOptional<z.ZodString>;
23
+ 1280: z.ZodOptional<z.ZodString>;
24
+ 1920: z.ZodOptional<z.ZodString>;
25
+ 2560: z.ZodOptional<z.ZodString>;
26
+ 3840: z.ZodOptional<z.ZodString>;
27
+ }, z.core.$strip>>;
28
+ jpg: z.ZodOptional<z.ZodObject<{
29
+ 640: z.ZodOptional<z.ZodString>;
30
+ 960: z.ZodOptional<z.ZodString>;
31
+ 1280: z.ZodOptional<z.ZodString>;
32
+ 1920: z.ZodOptional<z.ZodString>;
33
+ 2560: z.ZodOptional<z.ZodString>;
34
+ 3840: z.ZodOptional<z.ZodString>;
35
+ }, z.core.$strip>>;
36
+ }, z.core.$strip>>;
37
+ }, z.core.$strip>;
38
+ /** Zod schema for complete gallery data including metadata, sections, and sub-galleries */
39
+ declare const GalleryMetadataSchema: z.ZodObject<{
40
+ image: z.ZodOptional<z.ZodString>;
41
+ imageWidth: z.ZodOptional<z.ZodNumber>;
42
+ imageHeight: z.ZodOptional<z.ZodNumber>;
43
+ ogUrl: z.ZodOptional<z.ZodString>;
44
+ ogType: z.ZodOptional<z.ZodString>;
45
+ ogSiteName: z.ZodOptional<z.ZodString>;
46
+ twitterSite: z.ZodOptional<z.ZodString>;
47
+ twitterCreator: z.ZodOptional<z.ZodString>;
48
+ author: z.ZodOptional<z.ZodString>;
49
+ keywords: z.ZodOptional<z.ZodString>;
50
+ canonicalUrl: z.ZodOptional<z.ZodString>;
51
+ language: z.ZodOptional<z.ZodString>;
52
+ robots: z.ZodOptional<z.ZodString>;
53
+ }, z.core.$strip>;
54
+ /** Zod schema for complete gallery data including metadata, sections, and sub-galleries */
55
+ declare const GalleryDataSchema: z.ZodObject<{
56
+ title: z.ZodString;
57
+ description: z.ZodString;
58
+ mediaBasePath: z.ZodOptional<z.ZodString>;
59
+ url: z.ZodOptional<z.ZodString>;
60
+ headerImage: z.ZodString;
61
+ headerImageBlurHash: z.ZodOptional<z.ZodString>;
62
+ headerImageVariants: z.ZodOptional<z.ZodObject<{
63
+ portrait: z.ZodOptional<z.ZodObject<{
64
+ avif: z.ZodOptional<z.ZodObject<{
65
+ 360: z.ZodOptional<z.ZodString>;
66
+ 480: z.ZodOptional<z.ZodString>;
67
+ 720: z.ZodOptional<z.ZodString>;
68
+ 1080: z.ZodOptional<z.ZodString>;
69
+ }, z.core.$strip>>;
70
+ jpg: z.ZodOptional<z.ZodObject<{
71
+ 360: z.ZodOptional<z.ZodString>;
72
+ 480: z.ZodOptional<z.ZodString>;
73
+ 720: z.ZodOptional<z.ZodString>;
74
+ 1080: z.ZodOptional<z.ZodString>;
75
+ }, z.core.$strip>>;
76
+ }, z.core.$strip>>;
77
+ landscape: z.ZodOptional<z.ZodObject<{
78
+ avif: z.ZodOptional<z.ZodObject<{
79
+ 640: z.ZodOptional<z.ZodString>;
80
+ 960: z.ZodOptional<z.ZodString>;
81
+ 1280: z.ZodOptional<z.ZodString>;
82
+ 1920: z.ZodOptional<z.ZodString>;
83
+ 2560: z.ZodOptional<z.ZodString>;
84
+ 3840: z.ZodOptional<z.ZodString>;
85
+ }, z.core.$strip>>;
86
+ jpg: z.ZodOptional<z.ZodObject<{
87
+ 640: z.ZodOptional<z.ZodString>;
88
+ 960: z.ZodOptional<z.ZodString>;
89
+ 1280: z.ZodOptional<z.ZodString>;
90
+ 1920: z.ZodOptional<z.ZodString>;
91
+ 2560: z.ZodOptional<z.ZodString>;
92
+ 3840: z.ZodOptional<z.ZodString>;
93
+ }, z.core.$strip>>;
94
+ }, z.core.$strip>>;
95
+ }, z.core.$strip>>;
96
+ theme: z.ZodOptional<z.ZodString>;
97
+ thumbnails: z.ZodOptional<z.ZodObject<{
98
+ size: z.ZodOptional<z.ZodNumber>;
99
+ edge: z.ZodOptional<z.ZodEnum<{
100
+ width: "width";
101
+ height: "height";
102
+ auto: "auto";
103
+ }>>;
104
+ }, z.core.$strip>>;
105
+ metadata: z.ZodObject<{
106
+ image: z.ZodOptional<z.ZodString>;
107
+ imageWidth: z.ZodOptional<z.ZodNumber>;
108
+ imageHeight: z.ZodOptional<z.ZodNumber>;
109
+ ogUrl: z.ZodOptional<z.ZodString>;
110
+ ogType: z.ZodOptional<z.ZodString>;
111
+ ogSiteName: z.ZodOptional<z.ZodString>;
112
+ twitterSite: z.ZodOptional<z.ZodString>;
113
+ twitterCreator: z.ZodOptional<z.ZodString>;
114
+ author: z.ZodOptional<z.ZodString>;
115
+ keywords: z.ZodOptional<z.ZodString>;
116
+ canonicalUrl: z.ZodOptional<z.ZodString>;
117
+ language: z.ZodOptional<z.ZodString>;
118
+ robots: z.ZodOptional<z.ZodString>;
119
+ }, z.core.$strip>;
120
+ mediaBaseUrl: z.ZodOptional<z.ZodString>;
121
+ thumbsBaseUrl: z.ZodOptional<z.ZodString>;
122
+ analyticsScript: z.ZodOptional<z.ZodString>;
123
+ ctaBanner: z.ZodOptional<z.ZodBoolean>;
124
+ sections: z.ZodArray<z.ZodObject<{
125
+ title: z.ZodOptional<z.ZodString>;
126
+ description: z.ZodOptional<z.ZodString>;
127
+ images: z.ZodArray<z.ZodObject<{
128
+ type: z.ZodEnum<{
129
+ image: "image";
130
+ video: "video";
131
+ }>;
132
+ filename: z.ZodString;
133
+ url: z.ZodOptional<z.ZodString>;
134
+ alt: z.ZodOptional<z.ZodString>;
135
+ width: z.ZodNumber;
136
+ height: z.ZodNumber;
137
+ thumbnail: z.ZodOptional<z.ZodObject<{
138
+ baseUrl: z.ZodOptional<z.ZodString>;
139
+ path: z.ZodString;
140
+ pathRetina: z.ZodString;
141
+ width: z.ZodNumber;
142
+ height: z.ZodNumber;
143
+ blurHash: z.ZodOptional<z.ZodString>;
144
+ }, z.core.$strip>>;
145
+ lastMediaTimestamp: z.ZodOptional<z.ZodString>;
146
+ }, z.core.$strip>>;
147
+ }, z.core.$strip>>;
148
+ subGalleries: z.ZodObject<{
149
+ title: z.ZodString;
150
+ galleries: z.ZodArray<z.ZodObject<{
151
+ title: z.ZodString;
152
+ headerImage: z.ZodString;
153
+ path: z.ZodString;
154
+ }, z.core.$strip>>;
155
+ }, z.core.$strip>;
156
+ }, z.core.$strip>;
157
+
158
+ /** TypeScript type for header image variants */
159
+ type HeaderImageVariants = z.infer<typeof HeaderImageVariantsSchema>;
160
+ /** TypeScript type for gallery metadata */
161
+ type GalleryMetadata = z.infer<typeof GalleryMetadataSchema>;
162
+ /** TypeScript type for complete gallery data structure */
163
+ type GalleryData = z.infer<typeof GalleryDataSchema>;
164
+
165
+ /** Zod schema for thumbnail configuration */
166
+ declare const ThumbnailConfigSchema: z.ZodObject<{
167
+ size: z.ZodOptional<z.ZodNumber>;
168
+ edge: z.ZodOptional<z.ZodEnum<{
169
+ width: "width";
170
+ height: "height";
171
+ auto: "auto";
172
+ }>>;
173
+ }, z.core.$strip>;
174
+ /** Zod schema for theme configuration file (themeConfig.json) */
175
+ declare const ThemeConfigSchema: z.ZodObject<{
176
+ thumbnails: z.ZodOptional<z.ZodObject<{
177
+ size: z.ZodOptional<z.ZodNumber>;
178
+ edge: z.ZodOptional<z.ZodEnum<{
179
+ width: "width";
180
+ height: "height";
181
+ auto: "auto";
182
+ }>>;
183
+ }, z.core.$strip>>;
184
+ }, z.core.$strip>;
185
+ /** TypeScript type for thumbnail configuration */
186
+ type ThumbnailConfig = z.infer<typeof ThumbnailConfigSchema>;
187
+ /** TypeScript type for theme configuration */
188
+ type ThemeConfig = z.infer<typeof ThemeConfigSchema>;
189
+ /** Default thumbnail configuration values */
190
+ declare const DEFAULT_THUMBNAIL_CONFIG: Required<ThumbnailConfig>;
191
+ /**
192
+ * Extracts thumbnail config from gallery data.
193
+ * @param gallery - The gallery data object
194
+ * @returns ThumbnailConfig with values from gallery data
195
+ */
196
+ declare function extractThumbnailConfigFromGallery(gallery: {
197
+ thumbnails?: ThumbnailConfig;
198
+ }): ThumbnailConfig;
199
+ /**
200
+ * Merges thumbnail configurations with hierarchy:
201
+ * 1. CLI flags (highest precedence)
202
+ * 2. gallery.json settings
203
+ * 3. themeConfig.json (theme defaults)
204
+ * 4. Built-in defaults (lowest)
205
+ *
206
+ * @param cliConfig - Config from CLI flags (optional)
207
+ * @param galleryConfig - Config from gallery.json (optional)
208
+ * @param themeConfig - Config from themeConfig.json (optional)
209
+ * @returns Merged thumbnail configuration with all values resolved
210
+ */
211
+ declare function mergeThumbnailConfig(cliConfig?: ThumbnailConfig, galleryConfig?: ThumbnailConfig, themeConfig?: ThumbnailConfig): Required<ThumbnailConfig>;
212
+
213
+ /** Resolved hero data with all paths computed and markdown parsed */
214
+ interface ResolvedHero {
215
+ title: string;
216
+ description?: string;
217
+ parsedDescription: string;
218
+ headerImage?: string;
219
+ headerPhotoPath: string;
220
+ headerImageBlurHash?: string;
221
+ headerImageVariants?: HeaderImageVariants;
222
+ thumbnailBasePath: string;
223
+ imgBasename: string;
224
+ srcsets: {
225
+ portraitAvif: string;
226
+ portraitJpg: string;
227
+ landscapeAvif: string;
228
+ landscapeJpg: string;
229
+ };
230
+ }
231
+ /** Resolved image with all paths computed */
232
+ interface ResolvedImage {
233
+ type: 'image' | 'video';
234
+ filename: string;
235
+ alt?: string;
236
+ width: number;
237
+ height: number;
238
+ imagePath: string;
239
+ thumbnailPath: string;
240
+ thumbnailSrcSet?: string;
241
+ thumbnailWidth?: number;
242
+ thumbnailHeight?: number;
243
+ blurHash?: string;
244
+ }
245
+ /** Resolved section with parsed markdown and resolved image paths */
246
+ interface ResolvedSection {
247
+ title?: string;
248
+ description?: string;
249
+ parsedDescription: string;
250
+ images: ResolvedImage[];
251
+ }
252
+ /** Resolved sub-gallery with computed thumbnail path */
253
+ interface ResolvedSubGallery {
254
+ title: string;
255
+ headerImage: string;
256
+ path: string;
257
+ thumbnailPath: string;
258
+ /** Pre-computed relative path for linking (only present when galleryJsonPath is provided to resolveGalleryData) */
259
+ resolvedPath?: string;
260
+ }
261
+ /** Fully resolved gallery data ready for rendering */
262
+ interface ResolvedGalleryData {
263
+ title: string;
264
+ url?: string;
265
+ metadata: GalleryMetadata;
266
+ analyticsScript?: string;
267
+ ctaBanner?: boolean;
268
+ hero: ResolvedHero;
269
+ sections: ResolvedSection[];
270
+ subGalleries?: {
271
+ title: string;
272
+ galleries: ResolvedSubGallery[];
273
+ };
274
+ mediaBaseUrl?: string;
275
+ thumbsBaseUrl?: string;
276
+ /**
277
+ * Thumbnail configuration with dimension and edge settings.
278
+ * Themes should use this for display sizing (e.g., row-height for modern theme).
279
+ */
280
+ thumbnails?: Required<ThumbnailConfig>;
281
+ }
282
+
283
+ /** Portrait image sizes for responsive hero images */
284
+ declare const PORTRAIT_SIZES: readonly [360, 480, 720, 1080];
285
+ /** Landscape image sizes for responsive hero images */
286
+ declare const LANDSCAPE_SIZES: readonly [640, 960, 1280, 1920, 2560, 3840];
287
+
288
+ /**
289
+ * Renders markdown with limited formatting options.
290
+ * Supported: paragraphs, bold, italic, lists, code blocks, blockquotes, links
291
+ * Disabled: headings (rendered as paragraphs), images, HTML, tables
292
+ */
293
+ declare function renderMarkdown(markdown: string): Promise<string>;
294
+
295
+ /**
296
+ * Normalizes resource paths to be relative to the gallery root directory.
297
+ *
298
+ * @param resourcePath - The resource path (file or directory), typically relative to the gallery.json file
299
+ * @param galleryJsonPath - Path to the gallery.json file used to resolve relative paths
300
+ * @returns The normalized path relative to the gallery root directory
301
+ */
302
+ declare function getRelativePath(resourcePath: string, galleryJsonPath: string): string;
303
+ /**
304
+ * Get the path to a thumbnail that is relative to the gallery root directory or the thumbnails base URL.
305
+ *
306
+ * @param resourcePath - The resource path (file or directory), typically relative to the gallery.json file
307
+ * @param thumbsBaseUrl - The base URL for the thumbnails (gallery-level)
308
+ * @param thumbnailBaseUrl - Optional thumbnail-specific base URL that overrides thumbsBaseUrl if provided
309
+ * @returns The normalized path relative to the gallery root directory or the thumbnails base URL
310
+ */
311
+ declare function getThumbnailPath(resourcePath: string, thumbsBaseUrl?: string, thumbnailBaseUrl?: string): string;
312
+ /**
313
+ * Get the path to a photo that is always in the gallery root directory.
314
+ *
315
+ * @param filename - The filename to get the path for
316
+ * @param mediaBaseUrl - The base URL for the media
317
+ * @param url - Optional URL that, if provided, will be used directly regardless of base URL or path
318
+ * @returns The normalized path relative to the gallery root directory, or the provided URL
319
+ */
320
+ declare function getPhotoPath(filename: string, mediaBaseUrl?: string, url?: string): string;
321
+ /**
322
+ * Get the path to a subgallery thumbnail that is always in the subgallery directory.
323
+ *
324
+ * @param subgalleryHeaderImagePath - The path to the subgallery header image on the hard disk
325
+ * @returns The normalized path relative to the subgallery directory
326
+ */
327
+ declare function getSubgalleryThumbnailPath(subgalleryHeaderImagePath: string): string;
328
+ /**
329
+ * Build a srcset string for responsive images.
330
+ * Uses custom paths from variants when provided, otherwise generates default paths.
331
+ *
332
+ * @param variants - Optional record mapping sizes to custom URLs
333
+ * @param sizes - Array of image widths to include
334
+ * @param thumbnailBasePath - Base path for generated thumbnails
335
+ * @param imgBasename - Image basename for generated paths
336
+ * @param orientation - 'portrait' or 'landscape'
337
+ * @param format - Image format ('avif' or 'jpg')
338
+ * @param useDefaultPaths - Whether to use generated paths when no custom variant exists
339
+ * @returns Comma-separated srcset string
340
+ */
341
+ declare function buildHeroSrcset(variants: Record<number, string | undefined> | undefined, sizes: readonly number[], thumbnailBasePath: string, imgBasename: string, orientation: 'portrait' | 'landscape', format: 'avif' | 'jpg', useDefaultPaths: boolean): string;
342
+
343
+ interface LoadGalleryDataOptions {
344
+ /**
345
+ * When true, validates the loaded JSON against the GalleryData schema.
346
+ * Throws a descriptive error if validation fails.
347
+ * @default false
348
+ */
349
+ validate?: boolean;
350
+ }
351
+ /**
352
+ * Load theme configuration from themeConfig.json file.
353
+ *
354
+ * Searches for themeConfig.json in the following locations (in priority order):
355
+ * 1. Current working directory (process.cwd()) - checked first
356
+ * 2. Provided themePath parameter - checked second
357
+ *
358
+ * The first valid configuration found is returned. This means a themeConfig.json
359
+ * in the project root will take precedence over the theme's built-in configuration,
360
+ * allowing users to override theme defaults without modifying the theme itself.
361
+ *
362
+ * **Note for theme authors:** Your theme's themeConfig.json provides sensible defaults,
363
+ * but users can override these by placing their own themeConfig.json in their project root.
364
+ *
365
+ * @param themePath - Optional path to the theme directory
366
+ * @returns The thumbnail configuration from the theme, or undefined if not found
367
+ *
368
+ * @example
369
+ * ```typescript
370
+ * // Load from theme directory
371
+ * const themeConfig = loadThemeConfig('/path/to/theme');
372
+ *
373
+ * // Load from current directory
374
+ * const themeConfig = loadThemeConfig();
375
+ * ```
376
+ */
377
+ declare function loadThemeConfig(themePath?: string): ThumbnailConfig | undefined;
378
+ /**
379
+ * Load gallery data from a JSON file.
380
+ *
381
+ * @param galleryJsonPath - Path to the gallery.json file. Defaults to './gallery.json'.
382
+ * @param options - Optional settings for loading behavior.
383
+ * @returns The parsed gallery data
384
+ * @throws Error if file cannot be read, parsed, or fails validation
385
+ *
386
+ * @example
387
+ * ```typescript
388
+ * // Basic usage (no validation)
389
+ * const gallery = loadGalleryData('./gallery.json');
390
+ *
391
+ * // With schema validation
392
+ * const gallery = loadGalleryData('./gallery.json', { validate: true });
393
+ * ```
394
+ */
395
+ declare function loadGalleryData(galleryJsonPath?: string, options?: LoadGalleryDataOptions): GalleryData;
396
+
397
+ /**
398
+ * Options for resolving gallery data.
399
+ */
400
+ interface ResolveGalleryDataOptions {
401
+ /**
402
+ * Path to the gallery.json file. When provided, enables resolution of
403
+ * relative paths for sub-galleries (resolvedPath field).
404
+ */
405
+ galleryJsonPath?: string;
406
+ /**
407
+ * Theme-specific thumbnail configuration from themeConfig.json.
408
+ * Used as fallback when gallery.json doesn't specify thumbnail settings.
409
+ */
410
+ themeConfig?: ThumbnailConfig;
411
+ /**
412
+ * CLI-specified thumbnail configuration (highest priority).
413
+ * Overrides both gallery.json and theme config settings.
414
+ */
415
+ cliConfig?: ThumbnailConfig;
416
+ }
417
+ /**
418
+ * Transform raw gallery data into a fully resolved structure with all paths
419
+ * computed and markdown parsed. This is the main API for themes.
420
+ *
421
+ * @param gallery - Raw gallery data from loadGalleryData()
422
+ * @param options - Optional configuration for path resolution
423
+ * @returns Fully resolved gallery data ready for rendering
424
+ */
425
+ declare function resolveGalleryData(gallery: GalleryData, options?: ResolveGalleryDataOptions): Promise<ResolvedGalleryData>;
426
+
427
+ /** Astro integration type (simplified to avoid astro dependency in common) */
428
+ interface AstroIntegration {
429
+ name: string;
430
+ hooks: {
431
+ 'astro:build:done': (options: {
432
+ dir: URL;
433
+ }) => void;
434
+ };
435
+ }
436
+ /**
437
+ * Astro integration to prevent empty content collection files from being generated.
438
+ * Removes empty content-assets.mjs and content-modules.mjs files after build.
439
+ */
440
+ declare function preventEmptyContentFiles(): AstroIntegration;
441
+
442
+ export { DEFAULT_THUMBNAIL_CONFIG, LANDSCAPE_SIZES, type LoadGalleryDataOptions, PORTRAIT_SIZES, type ResolveGalleryDataOptions, type ResolvedGalleryData, type ResolvedHero, type ResolvedImage, type ResolvedSection, type ResolvedSubGallery, type ThemeConfig, ThemeConfigSchema, type ThumbnailConfig, ThumbnailConfigSchema, buildHeroSrcset, extractThumbnailConfigFromGallery, getPhotoPath, getRelativePath, getSubgalleryThumbnailPath, getThumbnailPath, loadGalleryData, loadThemeConfig, mergeThumbnailConfig, preventEmptyContentFiles, renderMarkdown, resolveGalleryData };