Functions/Public/Convert-ColourString.ps1

<#
.SYNOPSIS
Convert string to coloured format
.DESCRIPTION
Takes a string using custom colour blocks (seee https://github.com/stuartio/writecolour) to ANSI escape sequences which can be used with regular printing functions such as Write-Host
.PARAMETER InputObject
Input string to convert
.EXAMPLE
Convert-ColourString "Hello, my name is |red|Inigo Montoya|!|"
#>

function Convert-ColourString {
    [Alias('Convert-ColorString')]
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory)]
        [string]
        $InputObject
    )

    Process {
        $e = [char]0x1b
        $Reset = "$e[0m"
        $Separator = " "
        
        # Begin by removing end values
        $ParsedInput = $InputObject
        $ParsedInput = $ParsedInput.Replace('|!|', $Reset)
        
        # Parse Input and extract colours
        $ColourPattern = '\|([^\|]+)\|'
    
        # Find colour matches
        $ColourMatches = $ParsedInput | Select-String -Pattern $ColourPattern -AllMatches
    
        if ($ColourMatches) {
            Write-Debug "Convert-ColourfulString: Found $($ColourMatches.Matches.count) matches"
            $ColourMatches.Matches | ForEach-Object {
                Write-Debug "Parsing colour match $($_.Value)"
                $Value = $_.Value
                $ColourMatch = $_.Groups[1].Value
                $Foreground = $null
                $Background = $null
                $Flags = $null

                # Split value into components
                $ColourComponents = $ColourMatch.Split($Separator)
                Write-Debug "Found $($ColourComponents.count) components"

                # If single element then check between either foreground colour or flags
                if ($ColourComponents.Count -eq 1) {
                    $Foreground = Get-RGB -Colour $ColourComponents[0]
                    if ($null -eq $Foreground) {
                        Write-Debug "Using single element as flags"
                        $Flags = $ColourComponents[0]
                    }
                }

                # If 2 elements, then assume the first is the foreground, the 2nd can be either background or flags
                elseif ($ColourComponents.Count -eq 2) {
                    $Foreground = Get-RGB -Colour $ColourComponents[0]
                    $Background = Get-RGB -Colour $ColourComponents[1]
                    if ($null -eq $Background) {
                        Write-Debug "Using 2nd element as flags"
                        $Flags = $ColourComponents[1]
                    }
                }

                # If 3 elements, then 1st is foreground, 2nd is background, 3rd is flags
                elseif ($ColourComponents.Count -eq 3) {
                    $Foreground = Get-RGB -Colour $ColourComponents[0]
                    $Background = Get-RGB -Colour $ColourComponents[1]
                    $Flags = $ColourComponents[2]
                }

                # Otherwise panic
                else {
                    Write-Warning "Convert-ColourString: Prefix string is malformed"
                }
    
                # ---- Process foreground
                $FormattedValue = "$e[38;2;$($Foreground.red);$($Foreground.green);$($Foreground.blue)"
    
                # ---- Add background
                if ($Background) {
                    $FormattedValue += ";48;2;$($Background.red);$($Background.green);$($Background.blue)"
                }

                # ---- Add flags, if any
                if ($Flags) {
                    Write-Debug "Convert-ColourfulString: Flags = $Flags"
                    $FlagsArray = $Flags.ToCharArray()
                    foreach ($Flag in $FlagsArray) {
                        switch -CaseSensitive ($Flag) {
                            "b" { $FormattedValue += ";1" } # Bold
                            "f" { $FormattedValue += ";2" } # Dim/Faint
                            "i" { $FormattedValue += ";3" } # Italic
                            "u" { $FormattedValue += ";4" } # Underline
                            "B" { $FormattedValue += ";5" } # Blinking
                            "r" { $FormattedValue += ";7" } # Inverse/Reverse
                            "h" { $FormattedValue += ";8" } # Hidden/Invisible
                            "s" { $FormattedValue += ";9" } # Strikethrough
                        }
                    }
                }
    
                # Add closing char
                $FormattedValue += "m"
    
                # Update input string with formatted value
                $ParsedInput = $ParsedInput.Replace($Value, $FormattedValue)

                # Add trailing reset, just in case
                $ParsedInput += $Reset
            }
    
            return $ParsedInput
        }
        else {
            Write-Warning "Convert-ColourfulString: Found no colour matches"
            return $InputObject
        }
    }
}