Functions/GenXdev.AI/GenerateMasonryLayoutHtml.ps1
################################################################################ <# .SYNOPSIS Generates a responsive masonry layout HTML gallery from image data. .DESCRIPTION Creates an interactive HTML gallery with responsive masonry grid layout for displaying images. Features include: - Responsive grid layout that adapts to screen size - Image tooltips showing descriptions and keywords - Click-to-copy image path functionality - Clean modern styling with hover effects .PARAMETER Images Array of image objects containing metadata. Each object requires: - path: String with full filesystem path to image - keywords: String array of descriptive tags - description: Object containing short_description and long_description .PARAMETER FilePath Optional output path for the HTML file. If omitted, returns HTML as string. .EXAMPLE # Create gallery from image array and save to file $images = @( @{ path = "C:\photos\sunset.jpg" keywords = @("nature", "sunset", "landscape") description = @{ short_description = "Mountain sunset" long_description = "Beautiful sunset over mountain range" } } ) GenerateMasonryLayoutHtml -Images $images -FilePath "C:\output\gallery.html" .EXAMPLE # Generate HTML string without saving $html = GenerateMasonryLayoutHtml $images #> function GenerateMasonryLayoutHtml { [CmdletBinding()] [OutputType([System.String])] param ( ############################################################################### [Parameter( Mandatory = $true, Position = 0, ValueFromPipeline = $true, HelpMessage = "Array of image objects with path, keywords and description" )] [array]$Images, ############################################################################### [Parameter( Mandatory = $false, Position = 1, HelpMessage = "Output path for the generated HTML file" )] [string]$FilePath = $null, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "Title for the gallery" )] [string]$Title = "Photo Gallery", ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "Description for the gallery" )] [string]$Description = "Hover over images to see face recognition data", ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "Whether editing is enabled" )] [Switch]$CanEdit = $false, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "Whether deletion is enabled" )] [Switch]$CanDelete = $false, ############################################################################### [Parameter( Mandatory = $false, HelpMessage = "Embed images as base64 data URLs instead of file:// URLs for better portability" )] [Switch]$EmbedImages = $false ############################################################################### ) begin { $templatePath = "$PSScriptRoot\masonary.html" # Load System.Web for HTML encoding Microsoft.PowerShell.Utility\Add-Type -AssemblyName System.Web Microsoft.PowerShell.Utility\Write-Verbose "Starting HTML generation for $($Images.Count) images using template: $templatePath" # Verify template file exists if (-not (Microsoft.PowerShell.Management\Test-Path $templatePath)) { throw "Template file not found: $templatePath" } # Helper function to convert image to base64 data URL function ConvertTo-Base64DataUrl { param( [Parameter(Mandatory = $true)] [string]$ImagePath ) try { # Check if file exists if (-not (Microsoft.PowerShell.Management\Test-Path $ImagePath)) { Microsoft.PowerShell.Utility\Write-Warning "Image file not found: $ImagePath" return $null } # Determine MIME type based on file extension $extension = [System.IO.Path]::GetExtension($ImagePath).ToLower() $mimeType = switch ($extension) { ".jpg" { "image/jpeg" } ".jpeg" { "image/jpeg" } ".png" { "image/png" } default { Microsoft.PowerShell.Utility\Write-Warning "Unsupported image format: $extension" return $null } } # Read image file and convert to base64 $imageBytes = [System.IO.File]::ReadAllBytes($ImagePath) $base64String = [System.Convert]::ToBase64String($imageBytes) # Create data URL $dataUrl = "data:$mimeType;base64,$base64String" Microsoft.PowerShell.Utility\Write-Verbose "Converted image to base64 data URL: $ImagePath ($(($imageBytes.Length / 1KB).ToString('F1')) KB)" return $dataUrl } catch { Microsoft.PowerShell.Utility\Write-Warning "Failed to convert image to base64: $ImagePath - $_" return $null } } } process { # Read the HTML template Microsoft.PowerShell.Utility\Write-Verbose "Reading HTML template from: $templatePath" $html = Microsoft.PowerShell.Management\Get-Content -Path $templatePath -Raw -Encoding UTF8 # Convert image paths for browser compatibility if ($EmbedImages) { Microsoft.PowerShell.Utility\Write-Verbose "Converting image paths to base64 data URLs" } else { Microsoft.PowerShell.Utility\Write-Verbose "Converting image paths to file:// URLs" } $processedImages = @() foreach ($image in $Images) { $imageCopy = $image.PSObject.Copy() if ($imageCopy.path) { # Store original path for copy functionality $imageCopy | Microsoft.PowerShell.Utility\Add-Member -MemberType NoteProperty -Name "originalPath" -Value $imageCopy.path -Force if ($EmbedImages) { # Convert to base64 data URL for embedded display $dataUrl = ConvertTo-Base64DataUrl -ImagePath $imageCopy.path if ($null -ne $dataUrl) { $imageCopy.path = $dataUrl } else { # Fallback to file:// URL if base64 conversion fails $fileUrl = "file:///" + ($imageCopy.path -replace '\\', '/') $imageCopy.path = $fileUrl } } else { # Convert Windows path to file:// URL for display $fileUrl = "file:///" + ($imageCopy.path -replace '\\', '/') $imageCopy.path = $fileUrl } } $processedImages += $imageCopy } # Convert images array to JSON with proper escaping Microsoft.PowerShell.Utility\Write-Verbose "Converting $($processedImages.Count) images to JSON" $imagesJson = $processedImages | Microsoft.PowerShell.Utility\ConvertTo-Json -Compress -Depth 20 -WarningAction SilentlyContinue # Escape the JSON for JavaScript string literal $escapedJson = $imagesJson | Microsoft.PowerShell.Utility\ConvertTo-Json -Compress # Replace the placeholder with actual image data Microsoft.PowerShell.Utility\Write-Verbose "Replacing placeholder JSON.parse(`"[]`") with actual image data" $html = "$html".Replace('images: JSON.parse("[]")', "images: JSON.parse($escapedJson)") # Replace other template variables if they exist if (-not [String]::IsNullOrWhiteSpace($Title)) { $escapedTitle = $Title | Microsoft.PowerShell.Utility\ConvertTo-Json $html = "$html".Replace("title : `"Photo Gallery`"", "title : $escapedTitle") Microsoft.PowerShell.Utility\Write-Verbose "Updated title to: $Title" } if (-not [String]::IsNullOrWhiteSpace($Description)) { $escapedDescription = $Description | Microsoft.PowerShell.Utility\ConvertTo-Json $html = "$html".Replace("`"Hover over images to see face recognition data`"", $escapedDescription) Microsoft.PowerShell.Utility\Write-Verbose "Updated description to: $Description" } if ($CanEdit) { $html = "$html".Replace("canEdit: false", "canEdit: true") Microsoft.PowerShell.Utility\Write-Verbose "Updated canEdit to: $CanEdit" } if ($CanDelete) { $html = "$html".Replace("canDelete: false", "canDelete: true") Microsoft.PowerShell.Utility\Write-Verbose "Updated canDelete to: $CanDelete" } } end { # Either return HTML string or save to file based on parameters if ($null -eq $FilePath) { Microsoft.PowerShell.Utility\Write-Verbose "Returning HTML as string output" return $html } else { Microsoft.PowerShell.Utility\Write-Verbose "Saving HTML gallery to: $FilePath" $html | Microsoft.PowerShell.Utility\Out-File -FilePath (GenXdev.FileSystem\Expand-Path $FilePath -CreateDirectory) -Encoding utf8 } } } ################################################################################ |