Private/Show-SectionSlide.ps1
|
function Show-SectionSlide { <# .SYNOPSIS Renders a section slide with medium figlet text. .DESCRIPTION Displays a full-screen section slide containing a ## heading rendered as medium figlet text. Section slides serve as dividers between major parts of a presentation, creating visual breaks and organizing content into logical sections. The rendering process: 1. Extracts ## heading text from slide content 2. Detects inline color tags for color override 3. Loads font file from h2 setting (default: 'small' font) 4. Creates centered figlet text with specified color 5. Calculates padding to vertically center content 6. Renders in bordered panel filling terminal height Section slides use the h2 font setting (also accepts aliases: sectionFont, h2Font). The default h2 font is 'small', which is smaller than title slides but larger than content slide headers. Section slides should contain ONLY a ## heading with no other content. Additional content will not be displayed. .PARAMETER Slide The slide object containing a ## heading. Must match pattern: ^##\s+(.+)$ .PARAMETER Settings The presentation settings hashtable containing: - foreground: Default text color - background: Slide background color - border: Border color - borderStyle: Border style - h2: Font name for ## headings (default: 'small') - h2Color: Optional color override for ## headings .PARAMETER CurrentSlide The current slide number for pagination display. .PARAMETER TotalSlides The total number of slides in the presentation for pagination. .EXAMPLE Show-SectionSlide -Slide $slideObject -Settings $settings Renders a section slide with medium centered figlet text. .EXAMPLE $slide = [PSCustomObject]@{ Number = 10 Content = '## Implementation Details' } $settings = @{ h2 = 'small'; foreground = 'White'; border = 'Blue' } Show-SectionSlide -Slide $slide -Settings $settings Renders a section slide divider with default 'small' font. .EXAMPLE $slide = [PSCustomObject]@{ Number = 15 Content = '## <cyan>Demo Time</cyan>' } Show-SectionSlide -Slide $slide -Settings $settings Renders a section slide with inline color override (cyan text). .EXAMPLE $settings = @{ h2 = 'mini'; h2Color = 'Green'; border = 'Green' } Show-SectionSlide -Slide $slide -Settings $settings Renders a section slide using 'mini' font and green color from settings. .OUTPUTS None. Renders directly to the terminal console using PwshSpectreConsole. .NOTES Font Configuration: - h2 setting specifies font name without .flf extension - Default h2 font is 'small' (medium-sized figlet text) - Fonts loaded from ../Fonts/ directory relative to script - Custom fonts must be valid FIGlet (.flf) format Font Aliases: - h2, sectionFont, h2Font all map to the same setting - Normalized by ConvertFrom-DeckMarkdown during parsing Color Priority: - Inline tags: <color>text</color> or <span style="color:name">text</span> - h2Color setting in frontmatter - foreground setting as fallback Content Rules: - MUST contain exactly one ## heading - NO additional content after heading - Use # for title slides instead - Use ### for content slides with headers Visual Design: - Content vertically centered in panel - Figlet text horizontally centered - Panel fills entire terminal height - Typically smaller than title slides but larger than content headers Usage Pattern: - Opening: Title slide (#) - Sections: Section slides (##) to divide major topics - Content: Content slides (###) for detailed information #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [PSCustomObject]$Slide, [Parameter(Mandatory = $true)] [hashtable]$Settings, [Parameter(Mandatory = $false)] [int]$CurrentSlide = 1, [Parameter(Mandatory = $false)] [int]$TotalSlides = 1 ) begin { Write-Verbose "Rendering section slide #$($Slide.Number)" } process { try { # Extract the ## heading text if ($Slide.Content -match '^##\s+(.+)$') { $sectionText = $Matches[1].Trim() Write-Verbose " Section: $sectionText" } else { throw "Section slide does not contain a valid ## heading" } # Check for color tags in heading text and extract color $headingColor = $null if ($sectionText -match '<(\w+)>.*?</\1>') { $headingColor = $Matches[1] Write-Verbose " Extracted color from tag: $headingColor" } elseif ($sectionText -match "<span\s+style=['""]color:(\w+)['""]>.*?</span>") { $headingColor = $Matches[1] Write-Verbose " Extracted color from span: $headingColor" } # Strip HTML tags from section text $sectionText = $sectionText -replace "<span\s+style=['""]color:\w+['""]>(.*?)</span>", '$1' $sectionText = $sectionText -replace '<(\w+)>(.*?)</\1>', '$2' # Get colors and styles from settings $colorName = if ($headingColor) { $headingColor } elseif ($Settings.h2Color) { $Settings.h2Color } else { $Settings.foreground } $figletColor = Get-SpectreColorFromSettings -ColorName $colorName -SettingName 'Figlet' $borderInfo = Get-BorderStyleFromSettings -Settings $Settings # Create figlet text object with optional font from settings $figletParams = @{ Text = $sectionText Color = $figletColor Justification = 'Center' } # Default to 'small' font if h2 is 'default', otherwise use specified font $fontName = if ($Settings.h2 -eq 'default') { 'small' } else { $Settings.h2 } $fontPath = if (Test-Path $fontName) { $fontName } else { Join-Path $PSScriptRoot "../Fonts/$fontName.flf" } if (Test-Path $fontPath) { $figletParams['FontPath'] = $fontPath Write-Verbose " Using h2 font: $fontName" } $figlet = New-FigletText @figletParams # Create panel with internal padding calculated to fill terminal height # Account for rendering behavior to prevent scrolling $dimensions = Get-TerminalDimensions $windowHeight = $dimensions.Height $windowWidth = $dimensions.Width # Set panel to expand and measure what we need to fill $panel = [Spectre.Console.Panel]::new($figlet) $panel.Expand = $true # Add border style first if ($borderInfo.Style) { $panel.Border = [Spectre.Console.BoxBorder]::$($borderInfo.Style) } # Measure figlet with horizontal padding already applied # Horizontal padding is 4 on each side = 8 total $contentWidth = $windowWidth - 8 $figletSize = Get-SpectreRenderableSize -Renderable $figlet -ContainerWidth $contentWidth $actualFigletHeight = $figletSize.Height # Calculate vertical padding needed # Total height = border (2) + top padding + content + bottom padding $borderHeight = 2 $remainingSpace = $windowHeight - $actualFigletHeight - $borderHeight $topPadding = [math]::Max(0, [math]::Ceiling($remainingSpace / 2.0)) $bottomPadding = [math]::Max(0, $remainingSpace - $topPadding) $panel.Padding = [Spectre.Console.Padding]::new(4, $topPadding, 4, $bottomPadding) # Border style already added above if ($borderInfo.Style) { $panel.Border = [Spectre.Console.BoxBorder]::$($borderInfo.Style) } # Add border color if ($borderInfo.Color) { $panel.BorderStyle = [Spectre.Console.Style]::new($borderInfo.Color) } # Add pagination header if enabled if ($Settings.pagination -eq $true) { $paginationParams = @{ CurrentSlide = $CurrentSlide TotalSlides = $TotalSlides Style = $Settings.paginationStyle } if ($borderInfo.Color) { $paginationParams['Color'] = $borderInfo.Color } $paginationText = Get-PaginationText @paginationParams $panel.Header = [Spectre.Console.PanelHeader]::new($paginationText) $panel.Header.Justification = [Spectre.Console.Justify]::Right } # Render panel Out-SpectreHost $panel } catch { $errorRecord = [System.Management.Automation.ErrorRecord]::new( $_.Exception, 'SectionSlideRenderFailed', [System.Management.Automation.ErrorCategory]::InvalidOperation, $Slide ) $PSCmdlet.ThrowTerminatingError($errorRecord) } } end { Write-Verbose "Section slide rendered" } } |