simple-photo-gallery 2.0.14-rc.1 → 2.0.15
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/index.cjs +83 -130
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +80 -126
- package/dist/index.js.map +1 -1
- package/dist/lib/index.cjs +1 -50
- package/dist/lib/index.cjs.map +1 -1
- package/dist/lib/index.js +1 -48
- package/dist/lib/index.js.map +1 -1
- package/package.json +3 -4
- package/assets/fonts/dejavu/DejaVuSans-Bold.ttf +0 -0
- package/assets/fonts/dejavu/LICENSE.txt +0 -78
package/dist/index.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import
|
|
2
|
+
import process3, { stdout } from 'process';
|
|
3
3
|
import { Command } from 'commander';
|
|
4
4
|
import { LogLevels, createConsola } from 'consola';
|
|
5
5
|
import { execSync, spawn } from 'child_process';
|
|
6
6
|
import fs8, { promises } from 'fs';
|
|
7
|
-
import
|
|
7
|
+
import path7 from 'path';
|
|
8
8
|
import { Buffer } from 'buffer';
|
|
9
|
-
import { fileURLToPath } from 'url';
|
|
10
9
|
import sharp2 from 'sharp';
|
|
11
10
|
import { encode } from 'blurhash';
|
|
12
11
|
import { GalleryDataSchema, GalleryDataDeprecatedSchema } from '@simple-photo-gallery/common';
|
|
@@ -77,44 +76,9 @@ async function generateBlurHash(imagePath, componentX = 4, componentY = 3) {
|
|
|
77
76
|
}
|
|
78
77
|
|
|
79
78
|
// src/modules/build/utils/index.ts
|
|
80
|
-
var __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
81
|
-
var SOCIAL_CARD_FONT_RELATIVE_PATH = path.join("assets", "fonts", "dejavu", "DejaVuSans-Bold.ttf");
|
|
82
|
-
var socialCardFontBase64;
|
|
83
|
-
function resolveFromCurrentDir(...segments) {
|
|
84
|
-
return path.resolve(__dirname, ...segments);
|
|
85
|
-
}
|
|
86
|
-
function findSocialCardFontPath() {
|
|
87
|
-
const fontCandidates = [
|
|
88
|
-
resolveFromCurrentDir("../../../../", SOCIAL_CARD_FONT_RELATIVE_PATH),
|
|
89
|
-
path.resolve(__dirname, "../", SOCIAL_CARD_FONT_RELATIVE_PATH),
|
|
90
|
-
path.resolve(__dirname, "../../", SOCIAL_CARD_FONT_RELATIVE_PATH),
|
|
91
|
-
path.resolve(process4.cwd(), SOCIAL_CARD_FONT_RELATIVE_PATH),
|
|
92
|
-
path.resolve(process4.cwd(), "../", SOCIAL_CARD_FONT_RELATIVE_PATH),
|
|
93
|
-
path.resolve(process4.cwd(), "../simple-photo-gallery/", SOCIAL_CARD_FONT_RELATIVE_PATH)
|
|
94
|
-
];
|
|
95
|
-
for (const candidate of fontCandidates) {
|
|
96
|
-
if (fs8.existsSync(candidate)) {
|
|
97
|
-
return candidate;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
return null;
|
|
101
|
-
}
|
|
102
|
-
function getSocialCardFontBase64() {
|
|
103
|
-
if (socialCardFontBase64 !== void 0) {
|
|
104
|
-
return socialCardFontBase64;
|
|
105
|
-
}
|
|
106
|
-
const fontPath = findSocialCardFontPath();
|
|
107
|
-
console.log("DBG:", { fontPath, dirname: __dirname, cwd: process4.cwd() });
|
|
108
|
-
if (!fontPath) {
|
|
109
|
-
socialCardFontBase64 = null;
|
|
110
|
-
return null;
|
|
111
|
-
}
|
|
112
|
-
socialCardFontBase64 = fs8.readFileSync(fontPath).toString("base64");
|
|
113
|
-
return socialCardFontBase64;
|
|
114
|
-
}
|
|
115
79
|
async function createGallerySocialMediaCardImage(headerPhotoPath, title, ouputPath, ui) {
|
|
116
80
|
ui?.start(`Creating social media card image`);
|
|
117
|
-
const headerBasename =
|
|
81
|
+
const headerBasename = path7.basename(headerPhotoPath, path7.extname(headerPhotoPath));
|
|
118
82
|
if (fs8.existsSync(ouputPath)) {
|
|
119
83
|
ui?.success(`Social media card image already exists`);
|
|
120
84
|
return headerBasename;
|
|
@@ -123,21 +87,11 @@ async function createGallerySocialMediaCardImage(headerPhotoPath, title, ouputPa
|
|
|
123
87
|
const resizedImageBuffer = await image.resize(1200, 631, { fit: "cover" }).jpeg({ quality: 90 }).toBuffer();
|
|
124
88
|
const outputPath = ouputPath;
|
|
125
89
|
await sharp2(resizedImageBuffer).toFile(outputPath);
|
|
126
|
-
const fontBase64 = getSocialCardFontBase64();
|
|
127
|
-
const fontFace = fontBase64 ? `
|
|
128
|
-
@font-face {
|
|
129
|
-
font-family: 'DejaVu Sans';
|
|
130
|
-
src: url('data:font/ttf;base64,${fontBase64}') format('truetype');
|
|
131
|
-
font-weight: 700;
|
|
132
|
-
font-style: normal;
|
|
133
|
-
}` : "";
|
|
134
|
-
const fontFamily = fontBase64 ? "'DejaVu Sans', Arial, sans-serif" : "Arial, sans-serif";
|
|
135
90
|
const svgText = `
|
|
136
91
|
<svg width="1200" height="631" xmlns="http://www.w3.org/2000/svg">
|
|
137
92
|
<defs>
|
|
138
93
|
<style>
|
|
139
|
-
|
|
140
|
-
.title { font-family: ${fontFamily}; font-size: 96px; font-weight: bold; fill: white; stroke: black; stroke-width: 5; paint-order: stroke; text-anchor: middle; }
|
|
94
|
+
.title { font-family: 'Arial, sans-serif'; font-size: 96px; font-weight: bold; fill: white; stroke: black; stroke-width: 5; paint-order: stroke; text-anchor: middle; }
|
|
141
95
|
</style>
|
|
142
96
|
</defs>
|
|
143
97
|
<text x="600" y="250" class="title">${title}</text>
|
|
@@ -151,7 +105,7 @@ async function createGallerySocialMediaCardImage(headerPhotoPath, title, ouputPa
|
|
|
151
105
|
async function createOptimizedHeaderImage(headerPhotoPath, outputFolder, ui) {
|
|
152
106
|
ui?.start(`Creating optimized header images`);
|
|
153
107
|
const image = await loadImage(headerPhotoPath);
|
|
154
|
-
const headerBasename =
|
|
108
|
+
const headerBasename = path7.basename(headerPhotoPath, path7.extname(headerPhotoPath));
|
|
155
109
|
const generatedFiles = [];
|
|
156
110
|
ui?.debug("Generating blurhash for header image");
|
|
157
111
|
const blurHash = await generateBlurHash(headerPhotoPath);
|
|
@@ -160,22 +114,22 @@ async function createOptimizedHeaderImage(headerPhotoPath, outputFolder, ui) {
|
|
|
160
114
|
ui?.debug(`Creating landscape header image ${width}`);
|
|
161
115
|
const avifFilename = `${headerBasename}_landscape_${width}.avif`;
|
|
162
116
|
const jpgFilename = `${headerBasename}_landscape_${width}.jpg`;
|
|
163
|
-
if (fs8.existsSync(
|
|
117
|
+
if (fs8.existsSync(path7.join(outputFolder, avifFilename))) {
|
|
164
118
|
ui?.debug(`Landscape header image ${width} AVIF already exists`);
|
|
165
119
|
} else {
|
|
166
120
|
await cropAndResizeImage(
|
|
167
121
|
image.clone(),
|
|
168
|
-
|
|
122
|
+
path7.join(outputFolder, avifFilename),
|
|
169
123
|
width,
|
|
170
124
|
width * landscapeYFactor,
|
|
171
125
|
"avif"
|
|
172
126
|
);
|
|
173
127
|
}
|
|
174
128
|
generatedFiles.push(avifFilename);
|
|
175
|
-
if (fs8.existsSync(
|
|
129
|
+
if (fs8.existsSync(path7.join(outputFolder, jpgFilename))) {
|
|
176
130
|
ui?.debug(`Landscape header image ${width} JPG already exists`);
|
|
177
131
|
} else {
|
|
178
|
-
await cropAndResizeImage(image.clone(),
|
|
132
|
+
await cropAndResizeImage(image.clone(), path7.join(outputFolder, jpgFilename), width, width * landscapeYFactor, "jpg");
|
|
179
133
|
}
|
|
180
134
|
generatedFiles.push(jpgFilename);
|
|
181
135
|
}
|
|
@@ -184,16 +138,16 @@ async function createOptimizedHeaderImage(headerPhotoPath, outputFolder, ui) {
|
|
|
184
138
|
ui?.debug(`Creating portrait header image ${width}`);
|
|
185
139
|
const avifFilename = `${headerBasename}_portrait_${width}.avif`;
|
|
186
140
|
const jpgFilename = `${headerBasename}_portrait_${width}.jpg`;
|
|
187
|
-
if (fs8.existsSync(
|
|
141
|
+
if (fs8.existsSync(path7.join(outputFolder, avifFilename))) {
|
|
188
142
|
ui?.debug(`Portrait header image ${width} AVIF already exists`);
|
|
189
143
|
} else {
|
|
190
|
-
await cropAndResizeImage(image.clone(),
|
|
144
|
+
await cropAndResizeImage(image.clone(), path7.join(outputFolder, avifFilename), width, width * portraitYFactor, "avif");
|
|
191
145
|
}
|
|
192
146
|
generatedFiles.push(avifFilename);
|
|
193
|
-
if (fs8.existsSync(
|
|
147
|
+
if (fs8.existsSync(path7.join(outputFolder, jpgFilename))) {
|
|
194
148
|
ui?.debug(`Portrait header image ${width} JPG already exists`);
|
|
195
149
|
} else {
|
|
196
|
-
await cropAndResizeImage(image.clone(),
|
|
150
|
+
await cropAndResizeImage(image.clone(), path7.join(outputFolder, jpgFilename), width, width * portraitYFactor, "jpg");
|
|
197
151
|
}
|
|
198
152
|
generatedFiles.push(jpgFilename);
|
|
199
153
|
}
|
|
@@ -226,12 +180,12 @@ function cleanupOldHeaderImages(outputFolder, currentHeaderBasename, ui) {
|
|
|
226
180
|
const landscapeMatch = file.match(/^(.+)_landscape_\d+\.(avif|jpg)$/);
|
|
227
181
|
const portraitMatch = file.match(/^(.+)_portrait_\d+\.(avif|jpg)$/);
|
|
228
182
|
if (landscapeMatch && landscapeMatch[1] !== currentHeaderBasename) {
|
|
229
|
-
const filePath =
|
|
183
|
+
const filePath = path7.join(outputFolder, file);
|
|
230
184
|
ui?.debug(`Deleting old landscape header image: ${file}`);
|
|
231
185
|
fs8.unlinkSync(filePath);
|
|
232
186
|
deletedCount++;
|
|
233
187
|
} else if (portraitMatch && portraitMatch[1] !== currentHeaderBasename) {
|
|
234
|
-
const filePath =
|
|
188
|
+
const filePath = path7.join(outputFolder, file);
|
|
235
189
|
ui?.debug(`Deleting old portrait header image: ${file}`);
|
|
236
190
|
fs8.unlinkSync(filePath);
|
|
237
191
|
deletedCount++;
|
|
@@ -245,7 +199,7 @@ function cleanupOldHeaderImages(outputFolder, currentHeaderBasename, ui) {
|
|
|
245
199
|
}
|
|
246
200
|
function findGalleries(basePath, recursive) {
|
|
247
201
|
const galleryDirs = [];
|
|
248
|
-
const galleryJsonPath =
|
|
202
|
+
const galleryJsonPath = path7.join(basePath, "gallery", "gallery.json");
|
|
249
203
|
if (fs8.existsSync(galleryJsonPath)) {
|
|
250
204
|
galleryDirs.push(basePath);
|
|
251
205
|
}
|
|
@@ -254,7 +208,7 @@ function findGalleries(basePath, recursive) {
|
|
|
254
208
|
const entries = fs8.readdirSync(basePath, { withFileTypes: true });
|
|
255
209
|
for (const entry of entries) {
|
|
256
210
|
if (entry.isDirectory() && entry.name !== "gallery") {
|
|
257
|
-
const subPath =
|
|
211
|
+
const subPath = path7.join(basePath, entry.name);
|
|
258
212
|
const subResults = findGalleries(subPath, recursive);
|
|
259
213
|
galleryDirs.push(...subResults);
|
|
260
214
|
}
|
|
@@ -313,20 +267,20 @@ function migrateGalleryJson(deprecatedGalleryData, galleryJsonPath, ui) {
|
|
|
313
267
|
ui.start("Old gallery.json format detected. Migrating gallery.json to the new data format.");
|
|
314
268
|
let mediaBasePath;
|
|
315
269
|
const imagePath = deprecatedGalleryData.sections[0].images[0].path;
|
|
316
|
-
if (imagePath && imagePath !==
|
|
317
|
-
mediaBasePath =
|
|
270
|
+
if (imagePath && imagePath !== path7.join("..", path7.basename(imagePath))) {
|
|
271
|
+
mediaBasePath = path7.resolve(path7.join(path7.dirname(galleryJsonPath)), path7.dirname(imagePath));
|
|
318
272
|
}
|
|
319
273
|
const sections = deprecatedGalleryData.sections.map((section) => ({
|
|
320
274
|
...section,
|
|
321
275
|
images: section.images.map((image) => ({
|
|
322
276
|
...image,
|
|
323
277
|
path: void 0,
|
|
324
|
-
filename:
|
|
278
|
+
filename: path7.basename(image.path)
|
|
325
279
|
}))
|
|
326
280
|
}));
|
|
327
281
|
const galleryData = {
|
|
328
282
|
...deprecatedGalleryData,
|
|
329
|
-
headerImage:
|
|
283
|
+
headerImage: path7.basename(deprecatedGalleryData.headerImage),
|
|
330
284
|
sections,
|
|
331
285
|
mediaBasePath
|
|
332
286
|
};
|
|
@@ -338,7 +292,7 @@ function migrateGalleryJson(deprecatedGalleryData, galleryJsonPath, ui) {
|
|
|
338
292
|
return galleryData;
|
|
339
293
|
}
|
|
340
294
|
function getMediaFileType(fileName) {
|
|
341
|
-
const ext =
|
|
295
|
+
const ext = path7.extname(fileName).toLowerCase();
|
|
342
296
|
if (IMAGE_EXTENSIONS.has(ext)) return "image";
|
|
343
297
|
if (VIDEO_EXTENSIONS.has(ext)) return "video";
|
|
344
298
|
return null;
|
|
@@ -366,7 +320,7 @@ async function scanDirectory(dirPath, ui) {
|
|
|
366
320
|
mediaFiles.push(mediaFile);
|
|
367
321
|
}
|
|
368
322
|
} else if (entry.isDirectory() && entry.name !== "gallery") {
|
|
369
|
-
subGalleryDirectories.push(
|
|
323
|
+
subGalleryDirectories.push(path7.join(dirPath, entry.name));
|
|
370
324
|
}
|
|
371
325
|
}
|
|
372
326
|
} catch (error) {
|
|
@@ -402,12 +356,12 @@ async function getGallerySettingsFromUser(galleryName, defaultImage, ui) {
|
|
|
402
356
|
return { title, description, url, headerImage };
|
|
403
357
|
}
|
|
404
358
|
async function createGalleryJson(mediaFiles, galleryJsonPath, scanPath, subGalleries = [], useDefaultSettings, ctaBanner, ui) {
|
|
405
|
-
const galleryDir =
|
|
406
|
-
const isSameLocation =
|
|
359
|
+
const galleryDir = path7.dirname(galleryJsonPath);
|
|
360
|
+
const isSameLocation = path7.relative(scanPath, path7.join(galleryDir, "..")) === "";
|
|
407
361
|
const mediaBasePath = isSameLocation ? void 0 : scanPath;
|
|
408
362
|
const relativeSubGalleries = subGalleries.map((subGallery) => ({
|
|
409
363
|
...subGallery,
|
|
410
|
-
headerImage: subGallery.headerImage ?
|
|
364
|
+
headerImage: subGallery.headerImage ? path7.relative(galleryDir, subGallery.headerImage) : ""
|
|
411
365
|
}));
|
|
412
366
|
let galleryData = {
|
|
413
367
|
title: "My Gallery",
|
|
@@ -430,8 +384,8 @@ async function createGalleryJson(mediaFiles, galleryJsonPath, scanPath, subGalle
|
|
|
430
384
|
galleryData = {
|
|
431
385
|
...galleryData,
|
|
432
386
|
...await getGallerySettingsFromUser(
|
|
433
|
-
|
|
434
|
-
|
|
387
|
+
path7.basename(path7.join(galleryDir, "..")),
|
|
388
|
+
path7.basename(mediaFiles[0]?.filename || ""),
|
|
435
389
|
ui
|
|
436
390
|
)
|
|
437
391
|
};
|
|
@@ -439,8 +393,8 @@ async function createGalleryJson(mediaFiles, galleryJsonPath, scanPath, subGalle
|
|
|
439
393
|
await promises.writeFile(galleryJsonPath, JSON.stringify(galleryData, null, 2));
|
|
440
394
|
}
|
|
441
395
|
async function galleryExists(outputPath) {
|
|
442
|
-
const galleryPath =
|
|
443
|
-
const galleryJsonPath =
|
|
396
|
+
const galleryPath = path7.join(outputPath, "gallery");
|
|
397
|
+
const galleryJsonPath = path7.join(galleryPath, "gallery.json");
|
|
444
398
|
try {
|
|
445
399
|
await promises.access(galleryJsonPath);
|
|
446
400
|
return true;
|
|
@@ -459,7 +413,7 @@ async function processDirectory(scanPath, outputPath, recursive, useDefaultSetti
|
|
|
459
413
|
for (const subGalleryDir of subGalleryDirectories) {
|
|
460
414
|
const result2 = await processDirectory(
|
|
461
415
|
subGalleryDir,
|
|
462
|
-
|
|
416
|
+
path7.join(outputPath, path7.basename(subGalleryDir)),
|
|
463
417
|
recursive,
|
|
464
418
|
useDefaultSettings,
|
|
465
419
|
force,
|
|
@@ -474,8 +428,8 @@ async function processDirectory(scanPath, outputPath, recursive, useDefaultSetti
|
|
|
474
428
|
}
|
|
475
429
|
}
|
|
476
430
|
if (mediaFiles.length > 0 || subGalleries.length > 0) {
|
|
477
|
-
const galleryPath =
|
|
478
|
-
const galleryJsonPath =
|
|
431
|
+
const galleryPath = path7.join(outputPath, "gallery");
|
|
432
|
+
const galleryJsonPath = path7.join(galleryPath, "gallery.json");
|
|
479
433
|
const exists = await galleryExists(outputPath);
|
|
480
434
|
if (exists && !force) {
|
|
481
435
|
const shouldOverride = await ui.prompt(`Gallery already exists at ${galleryJsonPath}. Do you want to override it?`, {
|
|
@@ -500,19 +454,19 @@ async function processDirectory(scanPath, outputPath, recursive, useDefaultSetti
|
|
|
500
454
|
}
|
|
501
455
|
const result = { totalFiles, totalGalleries };
|
|
502
456
|
if (mediaFiles.length > 0 || subGalleries.length > 0) {
|
|
503
|
-
const dirName =
|
|
457
|
+
const dirName = path7.basename(scanPath);
|
|
504
458
|
result.subGallery = {
|
|
505
459
|
title: capitalizeTitle(dirName),
|
|
506
460
|
headerImage: mediaFiles[0]?.filename || "",
|
|
507
|
-
path:
|
|
461
|
+
path: path7.join("..", dirName)
|
|
508
462
|
};
|
|
509
463
|
}
|
|
510
464
|
return result;
|
|
511
465
|
}
|
|
512
466
|
async function init(options, ui) {
|
|
513
467
|
try {
|
|
514
|
-
const scanPath =
|
|
515
|
-
const outputPath = options.gallery ?
|
|
468
|
+
const scanPath = path7.resolve(options.photos);
|
|
469
|
+
const outputPath = options.gallery ? path7.resolve(options.gallery) : scanPath;
|
|
516
470
|
const result = await processDirectory(
|
|
517
471
|
scanPath,
|
|
518
472
|
outputPath,
|
|
@@ -636,7 +590,7 @@ async function processImage(imagePath, thumbnailPath, thumbnailPathRetina, thumb
|
|
|
636
590
|
const blurHash = await generateBlurHash(thumbnailPath);
|
|
637
591
|
return {
|
|
638
592
|
type: "image",
|
|
639
|
-
filename:
|
|
593
|
+
filename: path7.basename(imagePath),
|
|
640
594
|
alt: description,
|
|
641
595
|
width: imageDimensions.width,
|
|
642
596
|
height: imageDimensions.height,
|
|
@@ -667,7 +621,7 @@ async function processVideo(videoPath, thumbnailPath, thumbnailPathRetina, thumb
|
|
|
667
621
|
const blurHash = await generateBlurHash(thumbnailPath);
|
|
668
622
|
return {
|
|
669
623
|
type: "video",
|
|
670
|
-
filename:
|
|
624
|
+
filename: path7.basename(videoPath),
|
|
671
625
|
alt: void 0,
|
|
672
626
|
width: videoDimensions.width,
|
|
673
627
|
height: videoDimensions.height,
|
|
@@ -683,11 +637,11 @@ async function processVideo(videoPath, thumbnailPath, thumbnailPathRetina, thumb
|
|
|
683
637
|
}
|
|
684
638
|
async function processMediaFile(mediaFile, mediaBasePath, thumbnailsPath, thumbnailSize, ui) {
|
|
685
639
|
try {
|
|
686
|
-
const filePath =
|
|
640
|
+
const filePath = path7.resolve(path7.join(mediaBasePath, mediaFile.filename));
|
|
687
641
|
const fileName = mediaFile.filename;
|
|
688
|
-
const fileNameWithoutExt =
|
|
642
|
+
const fileNameWithoutExt = path7.parse(fileName).name;
|
|
689
643
|
const thumbnailFileName = `${fileNameWithoutExt}.avif`;
|
|
690
|
-
const thumbnailPath =
|
|
644
|
+
const thumbnailPath = path7.join(thumbnailsPath, thumbnailFileName);
|
|
691
645
|
const thumbnailPathRetina = thumbnailPath.replace(".avif", "@2x.avif");
|
|
692
646
|
const lastMediaTimestamp = mediaFile.lastMediaTimestamp ? new Date(mediaFile.lastMediaTimestamp) : void 0;
|
|
693
647
|
const verbose = ui.level === LogLevels.debug;
|
|
@@ -713,8 +667,8 @@ async function processMediaFile(mediaFile, mediaBasePath, thumbnailsPath, thumbn
|
|
|
713
667
|
}
|
|
714
668
|
updatedMediaFile.filename = mediaFile.filename;
|
|
715
669
|
if (updatedMediaFile.thumbnail) {
|
|
716
|
-
updatedMediaFile.thumbnail.path =
|
|
717
|
-
updatedMediaFile.thumbnail.pathRetina =
|
|
670
|
+
updatedMediaFile.thumbnail.path = path7.basename(thumbnailPath);
|
|
671
|
+
updatedMediaFile.thumbnail.pathRetina = path7.basename(thumbnailPathRetina);
|
|
718
672
|
if (mediaFile.thumbnail?.baseUrl) {
|
|
719
673
|
updatedMediaFile.thumbnail.baseUrl = mediaFile.thumbnail.baseUrl;
|
|
720
674
|
}
|
|
@@ -729,14 +683,14 @@ async function processMediaFile(mediaFile, mediaBasePath, thumbnailsPath, thumbn
|
|
|
729
683
|
}
|
|
730
684
|
}
|
|
731
685
|
async function processGalleryThumbnails(galleryDir, ui) {
|
|
732
|
-
const galleryJsonPath =
|
|
733
|
-
const thumbnailsPath =
|
|
686
|
+
const galleryJsonPath = path7.join(galleryDir, "gallery", "gallery.json");
|
|
687
|
+
const thumbnailsPath = path7.join(galleryDir, "gallery", "images");
|
|
734
688
|
ui.start(`Creating thumbnails: ${galleryDir}`);
|
|
735
689
|
try {
|
|
736
690
|
fs8.mkdirSync(thumbnailsPath, { recursive: true });
|
|
737
691
|
const galleryData = parseGalleryJson(galleryJsonPath, ui);
|
|
738
692
|
const thumbnailSize = galleryData.thumbnailSize || DEFAULT_THUMBNAIL_SIZE;
|
|
739
|
-
const mediaBasePath = galleryData.mediaBasePath ??
|
|
693
|
+
const mediaBasePath = galleryData.mediaBasePath ?? path7.join(galleryDir);
|
|
740
694
|
let processedCount = 0;
|
|
741
695
|
for (const section of galleryData.sections) {
|
|
742
696
|
for (const [index, mediaFile] of section.images.entries()) {
|
|
@@ -783,8 +737,8 @@ function copyPhotos(galleryData, galleryDir, ui) {
|
|
|
783
737
|
for (const section of galleryData.sections) {
|
|
784
738
|
for (const image of section.images) {
|
|
785
739
|
if (galleryData.mediaBasePath) {
|
|
786
|
-
const sourcePath =
|
|
787
|
-
const destPath =
|
|
740
|
+
const sourcePath = path7.join(galleryData.mediaBasePath, image.filename);
|
|
741
|
+
const destPath = path7.join(galleryDir, image.filename);
|
|
788
742
|
ui.debug(`Copying photo to ${destPath}`);
|
|
789
743
|
fs8.copyFileSync(sourcePath, destPath);
|
|
790
744
|
}
|
|
@@ -823,17 +777,17 @@ async function scanAndAppendNewFiles(galleryDir, galleryJsonPath, galleryData, u
|
|
|
823
777
|
}
|
|
824
778
|
async function buildGallery(galleryDir, templateDir, scan, shouldCreateThumbnails, ui, baseUrl, thumbsBaseUrl) {
|
|
825
779
|
ui.start(`Building gallery ${galleryDir}`);
|
|
826
|
-
const galleryJsonPath =
|
|
780
|
+
const galleryJsonPath = path7.join(galleryDir, "gallery", "gallery.json");
|
|
827
781
|
let galleryData = parseGalleryJson(galleryJsonPath, ui);
|
|
828
782
|
if (scan) {
|
|
829
783
|
galleryData = await scanAndAppendNewFiles(galleryDir, galleryJsonPath, galleryData, ui);
|
|
830
784
|
}
|
|
831
|
-
const socialMediaCardImagePath =
|
|
785
|
+
const socialMediaCardImagePath = path7.join(galleryDir, "gallery", "images", "social-media-card.jpg");
|
|
832
786
|
const mediaBasePath = galleryData.mediaBasePath;
|
|
833
787
|
const mediaBaseUrl = baseUrl || galleryData.mediaBaseUrl;
|
|
834
|
-
const headerImagePath = mediaBasePath ?
|
|
835
|
-
const imagesFolder =
|
|
836
|
-
const currentHeaderBasename =
|
|
788
|
+
const headerImagePath = mediaBasePath ? path7.join(mediaBasePath, galleryData.headerImage) : path7.resolve(galleryDir, galleryData.headerImage);
|
|
789
|
+
const imagesFolder = path7.join(galleryDir, "gallery", "images");
|
|
790
|
+
const currentHeaderBasename = path7.basename(headerImagePath, path7.extname(headerImagePath));
|
|
837
791
|
if (shouldCreateThumbnails) {
|
|
838
792
|
if (!fs8.existsSync(imagesFolder)) {
|
|
839
793
|
fs8.mkdirSync(imagesFolder, { recursive: true });
|
|
@@ -876,7 +830,7 @@ async function buildGallery(galleryDir, templateDir, scan, shouldCreateThumbnail
|
|
|
876
830
|
}
|
|
877
831
|
if (!galleryData.metadata.image) {
|
|
878
832
|
ui.debug("Updating gallery.json with social media card URL");
|
|
879
|
-
galleryData.metadata.image = thumbsBaseUrl ? `${thumbsBaseUrl}/${
|
|
833
|
+
galleryData.metadata.image = thumbsBaseUrl ? `${thumbsBaseUrl}/${path7.basename(socialMediaCardImagePath)}` : `${galleryData.url || ""}/${path7.relative(galleryDir, socialMediaCardImagePath)}`;
|
|
880
834
|
fs8.writeFileSync(galleryJsonPath, JSON.stringify(galleryData, null, 2));
|
|
881
835
|
}
|
|
882
836
|
if (shouldCreateThumbnails) {
|
|
@@ -884,20 +838,20 @@ async function buildGallery(galleryDir, templateDir, scan, shouldCreateThumbnail
|
|
|
884
838
|
}
|
|
885
839
|
ui.debug("Building gallery from template");
|
|
886
840
|
try {
|
|
887
|
-
|
|
888
|
-
|
|
841
|
+
process3.env.GALLERY_JSON_PATH = galleryJsonPath;
|
|
842
|
+
process3.env.GALLERY_OUTPUT_DIR = path7.join(galleryDir, "gallery");
|
|
889
843
|
execSync("npx astro build", { cwd: templateDir, stdio: ui.level === LogLevels.debug ? "inherit" : "ignore" });
|
|
890
844
|
} catch (error) {
|
|
891
845
|
ui.error(`Build failed for ${galleryDir}`);
|
|
892
846
|
throw error;
|
|
893
847
|
}
|
|
894
|
-
const outputDir =
|
|
895
|
-
const buildDir =
|
|
848
|
+
const outputDir = path7.join(galleryDir, "gallery");
|
|
849
|
+
const buildDir = path7.join(outputDir, "_build");
|
|
896
850
|
ui.debug(`Copying build output to ${outputDir}`);
|
|
897
851
|
fs8.cpSync(buildDir, outputDir, { recursive: true });
|
|
898
852
|
ui.debug("Moving index.html to gallery directory");
|
|
899
|
-
fs8.copyFileSync(
|
|
900
|
-
fs8.rmSync(
|
|
853
|
+
fs8.copyFileSync(path7.join(outputDir, "index.html"), path7.join(galleryDir, "index.html"));
|
|
854
|
+
fs8.rmSync(path7.join(outputDir, "index.html"));
|
|
901
855
|
ui.debug("Cleaning up build directory");
|
|
902
856
|
fs8.rmSync(buildDir, { recursive: true, force: true });
|
|
903
857
|
ui.success(`Gallery built successfully`);
|
|
@@ -910,12 +864,12 @@ async function build(options, ui) {
|
|
|
910
864
|
return { processedGalleryCount: 0 };
|
|
911
865
|
}
|
|
912
866
|
const themePath = await import.meta.resolve("@simple-photo-gallery/theme-modern/package.json");
|
|
913
|
-
const themeDir =
|
|
867
|
+
const themeDir = path7.dirname(new URL(themePath).pathname);
|
|
914
868
|
let totalGalleries = 0;
|
|
915
869
|
for (const dir of galleryDirs) {
|
|
916
|
-
const baseUrl = options.baseUrl ? `${options.baseUrl}${
|
|
917
|
-
const thumbsBaseUrl = options.thumbsBaseUrl ? `${options.thumbsBaseUrl}${
|
|
918
|
-
await buildGallery(
|
|
870
|
+
const baseUrl = options.baseUrl ? `${options.baseUrl}${path7.relative(options.gallery, dir)}` : void 0;
|
|
871
|
+
const thumbsBaseUrl = options.thumbsBaseUrl ? `${options.thumbsBaseUrl}${path7.relative(options.gallery, dir)}` : void 0;
|
|
872
|
+
await buildGallery(path7.resolve(dir), themeDir, options.scan, options.thumbnails, ui, baseUrl, thumbsBaseUrl);
|
|
919
873
|
++totalGalleries;
|
|
920
874
|
}
|
|
921
875
|
ui.box(`Built ${totalGalleries} ${totalGalleries === 1 ? "gallery" : "galleries"} successfully`);
|
|
@@ -931,7 +885,7 @@ async function build(options, ui) {
|
|
|
931
885
|
}
|
|
932
886
|
async function cleanGallery(galleryDir, ui) {
|
|
933
887
|
let filesRemoved = 0;
|
|
934
|
-
const indexHtmlPath =
|
|
888
|
+
const indexHtmlPath = path7.join(galleryDir, "index.html");
|
|
935
889
|
if (fs8.existsSync(indexHtmlPath)) {
|
|
936
890
|
try {
|
|
937
891
|
fs8.rmSync(indexHtmlPath);
|
|
@@ -941,7 +895,7 @@ async function cleanGallery(galleryDir, ui) {
|
|
|
941
895
|
ui?.warn(`Failed to remove index.html: ${error}`);
|
|
942
896
|
}
|
|
943
897
|
}
|
|
944
|
-
const galleryPath =
|
|
898
|
+
const galleryPath = path7.join(galleryDir, "gallery");
|
|
945
899
|
if (fs8.existsSync(galleryPath)) {
|
|
946
900
|
try {
|
|
947
901
|
fs8.rmSync(galleryPath, { recursive: true, force: true });
|
|
@@ -960,7 +914,7 @@ async function cleanGallery(galleryDir, ui) {
|
|
|
960
914
|
}
|
|
961
915
|
async function clean(options, ui) {
|
|
962
916
|
try {
|
|
963
|
-
const basePath =
|
|
917
|
+
const basePath = path7.resolve(options.gallery);
|
|
964
918
|
if (!fs8.existsSync(basePath)) {
|
|
965
919
|
ui.error(`Directory does not exist: ${basePath}`);
|
|
966
920
|
return { processedGalleryCount: 0 };
|
|
@@ -1009,7 +963,7 @@ var ApiTelemetryClient = class {
|
|
|
1009
963
|
axios.post(this.endpoint, event, {
|
|
1010
964
|
headers: {
|
|
1011
965
|
"content-type": "application/json",
|
|
1012
|
-
"user-agent": `simple-photo-gallery/${event.packageVersion} (${
|
|
966
|
+
"user-agent": `simple-photo-gallery/${event.packageVersion} (${process3.platform}; ${process3.arch})`
|
|
1013
967
|
}
|
|
1014
968
|
});
|
|
1015
969
|
} catch {
|
|
@@ -1046,11 +1000,11 @@ var TelemetryService = class {
|
|
|
1046
1000
|
if (override) {
|
|
1047
1001
|
return override === "1";
|
|
1048
1002
|
}
|
|
1049
|
-
if (
|
|
1003
|
+
if (process3.env.CI || process3.env.DO_NOT_TRACK) {
|
|
1050
1004
|
return false;
|
|
1051
1005
|
}
|
|
1052
|
-
if (
|
|
1053
|
-
return
|
|
1006
|
+
if (process3.env.SPG_TELEMETRY) {
|
|
1007
|
+
return process3.env.SPG_TELEMETRY === "1";
|
|
1054
1008
|
}
|
|
1055
1009
|
const stored = this.getStoredPreference();
|
|
1056
1010
|
if (stored === void 0) {
|
|
@@ -1092,7 +1046,7 @@ var TelemetryService = class {
|
|
|
1092
1046
|
durationMs: now - startedAt,
|
|
1093
1047
|
packageName: this.packageName,
|
|
1094
1048
|
packageVersion: this.packageVersion,
|
|
1095
|
-
nodeVersion:
|
|
1049
|
+
nodeVersion: process3.version,
|
|
1096
1050
|
osPlatform: os.platform(),
|
|
1097
1051
|
osRelease: os.release(),
|
|
1098
1052
|
osArch: os.arch(),
|
|
@@ -1126,7 +1080,7 @@ var TelemetryService = class {
|
|
|
1126
1080
|
/** Returns the telemetry client. */
|
|
1127
1081
|
getClient() {
|
|
1128
1082
|
if (!this.client) {
|
|
1129
|
-
switch (
|
|
1083
|
+
switch (process3.env.SPG_TELEMETRY_PROVIDER) {
|
|
1130
1084
|
case "none": {
|
|
1131
1085
|
this.client = void 0;
|
|
1132
1086
|
break;
|
|
@@ -1218,7 +1172,7 @@ async function waitForUpdateCheck(checkPromise) {
|
|
|
1218
1172
|
// package.json
|
|
1219
1173
|
var package_default = {
|
|
1220
1174
|
name: "simple-photo-gallery",
|
|
1221
|
-
version: "2.0.
|
|
1175
|
+
version: "2.0.15"};
|
|
1222
1176
|
|
|
1223
1177
|
// src/index.ts
|
|
1224
1178
|
var program = new Command();
|
|
@@ -1260,7 +1214,7 @@ function withCommandContext(handler) {
|
|
|
1260
1214
|
} catch (error) {
|
|
1261
1215
|
ui.debug(error);
|
|
1262
1216
|
errorInfo = error instanceof Error ? { name: error.name, message: error.message } : { name: "UnknownError", message: String(error) };
|
|
1263
|
-
|
|
1217
|
+
process3.exitCode = 1;
|
|
1264
1218
|
}
|
|
1265
1219
|
const updateInfo = await waitForUpdateCheck(updateCheckPromise);
|
|
1266
1220
|
if (updateInfo) {
|
|
@@ -1282,14 +1236,14 @@ function withCommandContext(handler) {
|
|
|
1282
1236
|
program.command("init").description("Initialize a gallery by scaning a folder for images and videos").option(
|
|
1283
1237
|
"-p, --photos <path>",
|
|
1284
1238
|
"Path to the folder where the photos are stored. Default: current working directory",
|
|
1285
|
-
|
|
1239
|
+
process3.cwd()
|
|
1286
1240
|
).option(
|
|
1287
1241
|
"-g, --gallery <path>",
|
|
1288
1242
|
"Path to the directory where the gallery will be initialized. Default: same directory as the photos folder"
|
|
1289
1243
|
).option("-r, --recursive", "Recursively create galleries from all photos subdirectories", false).option("-d, --default", "Use default gallery settings instead of asking the user", false).option("-f, --force", "Force override existing galleries without asking", false).option("--cta-banner", "Add a Simple Photo Gallery call-to-action banner to the end of the gallery", false).action(withCommandContext((options, ui) => init(options, ui)));
|
|
1290
|
-
program.command("thumbnails").description("Create thumbnails for all media files in the gallery").option("-g, --gallery <path>", "Path to the directory of the gallery. Default: current working directory",
|
|
1291
|
-
program.command("build").description("Build the HTML gallery in the specified directory").option("-g, --gallery <path>", "Path to the directory of the gallery. Default: current working directory",
|
|
1292
|
-
program.command("clean").description("Remove all gallery files and folders (index.html, gallery/)").option("-g, --gallery <path>", "Path to the directory of the gallery. Default: current working directory",
|
|
1244
|
+
program.command("thumbnails").description("Create thumbnails for all media files in the gallery").option("-g, --gallery <path>", "Path to the directory of the gallery. Default: current working directory", process3.cwd()).option("-r, --recursive", "Scan subdirectories recursively", false).action(withCommandContext((options, ui) => thumbnails(options, ui)));
|
|
1245
|
+
program.command("build").description("Build the HTML gallery in the specified directory").option("-g, --gallery <path>", "Path to the directory of the gallery. Default: current working directory", process3.cwd()).option("-r, --recursive", "Scan subdirectories recursively", false).option("-b, --base-url <url>", "Base URL where the photos are hosted").option("-t, --thumbs-base-url <url>", "Base URL where the thumbnails are hosted").option("--no-thumbnails", "Skip creating thumbnails when building the gallery", true).option("--no-scan", "Do not scan for new photos when building the gallery", true).action(withCommandContext((options, ui) => build(options, ui)));
|
|
1246
|
+
program.command("clean").description("Remove all gallery files and folders (index.html, gallery/)").option("-g, --gallery <path>", "Path to the directory of the gallery. Default: current working directory", process3.cwd()).option("-r, --recursive", "Clean subdirectories recursively", false).action(withCommandContext((options, ui) => clean(options, ui)));
|
|
1293
1247
|
program.command("telemetry").description("Manage anonymous telemetry preferences. Use 1 to enable, 0 to disable, or no argument to check status").option("-s, --state <state>", "Enable (1) or disable (0) telemetry", parseTelemetryOption).action(withCommandContext((options, ui) => telemetry(options, ui, telemetryService)));
|
|
1294
1248
|
program.parse();
|
|
1295
1249
|
//# sourceMappingURL=index.js.map
|