Private/Highlighting.ps1

# PSSnips — Syntax highlighting helpers (ANSI tokenizer and bat).
function script:ConvertTo-HighlightedPS {
    <#
    .SYNOPSIS
        Applies ANSI syntax highlighting to a PowerShell code string using the built-in tokenizer.
    #>

    [OutputType([string])]
    param(
        [Parameter(Mandatory)]
        [AllowEmptyString()]
        [string]$Code
    )
    if ([string]::IsNullOrEmpty($Code)) { return $Code }

    $tokens = $null
    $errors = $null
    $null = [System.Management.Automation.Language.Parser]::ParseInput($Code, [ref]$tokens, [ref]$errors)

    $esc   = [char]27
    $reset = "${esc}[0m"

    $hasPSStyle = $null -ne (Get-Variable -Name PSStyle -ErrorAction SilentlyContinue)

    $colorComment  = if ($hasPSStyle) { $PSStyle.Foreground.Green } else { "${esc}[32m" }
    $colorString   = "${esc}[33m"
    $colorVariable = "${esc}[35m"
    $colorKeyword  = "${esc}[94m"
    $colorNumber   = "${esc}[36m"
    $colorOperator = "${esc}[37m"
    $colorType     = "${esc}[33m"

    $result = [System.Text.StringBuilder]::new($Code.Length * 2)
    $pos    = 0

    foreach ($token in ($tokens | Sort-Object { $_.Extent.StartOffset })) {
        $start = $token.Extent.StartOffset
        $end   = $token.Extent.EndOffset

        if ($start -gt $pos) {
            $null = $result.Append($Code.Substring($pos, $start - $pos))
        }

        $tkKind  = $token.Kind
        $tkFlags = $token.TokenFlags

        $color = if ($tkKind -eq [System.Management.Automation.Language.TokenKind]::Comment) {
            $colorComment
        } elseif ($tkKind -eq [System.Management.Automation.Language.TokenKind]::StringLiteral -or
                  $tkKind -eq [System.Management.Automation.Language.TokenKind]::StringExpandable -or
                  $tkKind -eq [System.Management.Automation.Language.TokenKind]::HereStringLiteral -or
                  $tkKind -eq [System.Management.Automation.Language.TokenKind]::HereStringExpandable) {
            $colorString
        } elseif ($tkKind -eq [System.Management.Automation.Language.TokenKind]::Variable) {
            $colorVariable
        } elseif ($tkKind -eq [System.Management.Automation.Language.TokenKind]::Number) {
            $colorNumber
        } elseif ($tkFlags -band [System.Management.Automation.Language.TokenFlags]::Keyword) {
            $colorKeyword
        } elseif ($tkFlags -band [System.Management.Automation.Language.TokenFlags]::TypeName) {
            $colorType
        } elseif ($tkFlags -band ([System.Management.Automation.Language.TokenFlags]::BinaryOperator -bor
                                   [System.Management.Automation.Language.TokenFlags]::UnaryOperator)) {
            $colorOperator
        } else {
            $null
        }

        if ($color) {
            $null = $result.Append($color)
            $null = $result.Append($token.Extent.Text)
            $null = $result.Append($reset)
        } else {
            $null = $result.Append($token.Extent.Text)
        }

        $pos = $end
    }

    if ($pos -lt $Code.Length) {
        $null = $result.Append($Code.Substring($pos))
    }

    return $result.ToString()
}

function script:Invoke-BatHighlight {
    <#
    .SYNOPSIS
        Pipes source code through bat for syntax highlighting.
    #>

    [OutputType([string])]
    param(
        [Parameter(Mandatory)]
        [AllowEmptyString()]
        [string]$Code,
        [Parameter(Mandatory)]
        [string]$Extension
    )
    if ([string]::IsNullOrEmpty($Code)) { return $Code }
    if (-not (Get-Command bat -ErrorAction SilentlyContinue)) {
        script:Out-Warn 'bat is not installed or not on PATH. Falling back to plain output.'
        return $Code
    }
    try {
        $lines = $Code | bat --language $Extension --color always --paging never --plain 2>$null
        return ($lines -join "`n")
    } catch {
        Write-Verbose "Invoke-BatHighlight: bat failed — $($_.Exception.Message)"
        return $Code
    }
}