private/00-helpers.ps1
|
# ------------------------------------------------------------------------------ helpers -- function ConvertTo-UiHtml { param([AllowNull()][object] $Value) if ($null -eq $Value) { return '' } return [System.Net.WebUtility]::HtmlEncode([string] $Value) } function Assert-UiBuilder { if ($null -eq $script:UiBuilder) { throw 'UI4ME components must be created inside Invoke-UI4MEApp -Content { ... } (or one of its callbacks).' } return $script:UiBuilder } function New-UiId { param([string]$Prefix = 'u') $ctx = Assert-UiBuilder $ctx.Sequence = [int]$ctx.Sequence + 1 return ('u4ps-{0}-{1}' -f $Prefix, $ctx.Sequence) } function Add-UiMarkup { param([string]$Markup) $ctx = Assert-UiBuilder [void]$ctx.Target.Markup.Append($Markup) } function Add-UiSetup { # Runs once the element exists in the live document (immediately for runtime content). param($Initializer) $ctx = Assert-UiBuilder [void]$ctx.Target.Setups.Add($Initializer) } function Get-UiClassAttr { param([string]$Base, [string]$Extra) return ('class="{0}"' -f (ConvertTo-UiHtml ((@($Base, $Extra) | Where-Object { $_ }) -join ' '))) } function Test-UiState { param([AllowNull()][object]$Value) return ($null -ne $Value -and $Value.PSObject.TypeNames -contains 'UI4ME.UiState') } function Get-UiValue { # A plain value, or the current value of a state/computed. param([AllowNull()][object]$Value) if (Test-UiState $Value) { return $Value.Value } return $Value } function Invoke-UiBuild { # Dot-source a build block so variables it defines stay visible to later callbacks. param([scriptblock]$Content) if ($null -ne $Content) { $null = . $Content } } function Invoke-UiContainer { param([string]$Tag, [string]$Class, [string]$Style, [scriptblock]$Content, [AllowNull()][object]$Visible, [hashtable]$Attributes, [string]$Prefix) if ($Tag -notmatch '^[a-z][a-z0-9-]*$' -or $script:BlockedTags -contains $Tag) { throw "Invalid container tag '$Tag'" } $id = New-UiId 'box' $attrs = '' if ($Attributes) { foreach ($key in $Attributes.Keys) { if ($key -notmatch '^[a-zA-Z_:][-a-zA-Z0-9_:.]*$' -or $key -match '^on') { throw "Invalid attribute '$key'" } $attrs += (' {0}="{1}"' -f $key, (ConvertTo-UiHtml $Attributes[$key])) } } $styleAttr = if ($Style) { ' style="{0}"' -f (ConvertTo-UiHtml $Style) } else { '' } Add-UiMarkup ('<{0} id="{1}" {2}{3}{4}{5}>' -f $Tag, $id, (Get-UiClassAttr '' $Class), $styleAttr, $attrs, (Get-UiHiddenAttr $Visible)) if ($Prefix) { Add-UiMarkup $Prefix } try { Invoke-UiBuild $Content } finally { Add-UiMarkup "</$Tag>" } Register-UiVisibility $id $Visible return $id } function Get-UiHiddenAttr { param([AllowNull()][object]$Visible) if ($null -eq $Visible) { return '' } if ([bool](Get-UiValue $Visible)) { return '' } return ' hidden' } function Register-UiVisibility { param([string]$Id, [AllowNull()][object]$Visible) if (-not (Test-UiState $Visible)) { return } $null = Register-UiBinding $Visible $Id 'Set-UiHiddenBinding' } |