feat: parameterless photo_archive for recent photos

This commit is contained in:
2026-02-14 18:40:00 +01:00
parent b0e9e39020
commit 5a097283c9
3 changed files with 240 additions and 70 deletions

View File

@@ -6,15 +6,17 @@
* When rendered, images are automatically linked to the post.
*
* Usage:
* [[photo_archive]] - Newest 10 months with images (month + year label)
* [[photo_archive year="2024"]] - All months of 2024, each in its own lightbox
* [[photo_archive year="2024" month="6"]] - Only June 2024 photos
*
* Parameters:
* - year (required): The year to display photos from (e.g., 2024)
* - month (optional): Specific month (1-12). If omitted, shows all months with photos.
* - year (optional): The year to display photos from (e.g., 2024)
* - month (optional): Specific month (1-12). Requires year. If omitted with year, shows all months.
*
* Gallery Layout:
* - Each month is in its own lightbox with the month name rotated 90° on the side
* - When no year specified, shows "Month Year" label (e.g., "January 2024")
* - Images are displayed in a grid and are clickable for lightbox viewing
*/
@@ -38,18 +40,19 @@ const photoArchiveMacro: MacroDefinition = {
description: 'Creates a photo archive gallery organized by year and month, automatically linking discovered images to the post',
validate(params: MacroParams): string | undefined {
// Year is required
if (!params.year) {
return 'photo_archive macro requires a "year" parameter';
// Year is optional - if not provided, shows recent 10 months
if (params.year) {
const year = parseInt(params.year, 10);
if (isNaN(year) || year < 1000 || year > 9999) {
return 'Year must be a valid 4-digit year (e.g., 2024)';
}
}
const year = parseInt(params.year, 10);
if (isNaN(year) || year < 1000 || year > 9999) {
return 'Year must be a valid 4-digit year (e.g., 2024)';
}
// Month is optional but must be valid if provided
// Month is optional but must be valid if provided, and requires year
if (params.month) {
if (!params.year) {
return 'Month parameter requires a year parameter';
}
const month = parseInt(params.month, 10);
if (isNaN(month) || month < 1 || month > 12) {
return 'Month must be a number between 1 and 12';
@@ -60,7 +63,11 @@ const photoArchiveMacro: MacroDefinition = {
},
editorPreview(params: MacroParams): string {
const year = params.year || '????';
// No year = recent mode
if (!params.year) {
return '📅 Photo Archive: Recent';
}
const year = params.year;
if (params.month) {
const monthNum = parseInt(params.month, 10);
const monthName = getMonthName(monthNum);
@@ -73,12 +80,16 @@ const photoArchiveMacro: MacroDefinition = {
const { year, month } = params;
// Build data attributes for hydration
const dataAttrs = [
`data-year="${year}"`,
];
const dataAttrs: string[] = [];
if (month) {
dataAttrs.push(`data-month="${month}"`);
// If no year, use recent mode (newest 10 months with images)
if (!year) {
dataAttrs.push('data-recent="10"');
} else {
dataAttrs.push(`data-year="${year}"`);
if (month) {
dataAttrs.push(`data-month="${month}"`);
}
}
if (context.postId) {
@@ -87,7 +98,9 @@ const photoArchiveMacro: MacroDefinition = {
// CSS classes
const classes = ['macro-photo-archive'];
if (month) {
if (!year) {
classes.push('photo-archive-recent-months');
} else if (month) {
classes.push('photo-archive-single-month');
} else {
classes.push('photo-archive-full-year');
@@ -96,7 +109,17 @@ const photoArchiveMacro: MacroDefinition = {
// Generate placeholder HTML - actual content is hydrated by Editor.tsx
let html = `<div class="${classes.join(' ')}" ${dataAttrs.join(' ')}>`;
html += `<div class="photo-archive-container">`;
html += `<div class="photo-archive-loading">Loading photo archive for ${year}${month ? ` / ${getMonthName(parseInt(month, 10))}` : ''}...</div>`;
// Loading message based on mode
let loadingMsg: string;
if (!year) {
loadingMsg = 'Loading recent photos...';
} else if (month) {
loadingMsg = `Loading photo archive for ${year} / ${getMonthName(parseInt(month, 10))}...`;
} else {
loadingMsg = `Loading photo archive for ${year}...`;
}
html += `<div class="photo-archive-loading">${loadingMsg}</div>`;
html += `</div>`;
html += `</div>`;