Private/ConvertTo-SpectreMarkup.ps1
|
function ConvertTo-SpectreMarkup { <# .SYNOPSIS Converts markdown formatting to Spectre Console markup. .DESCRIPTION Transforms common markdown inline formatting into Spectre Console markup tags for rich terminal rendering. This enables markdown text to display with colors, bold, italic, and other formatting in the terminal. The conversion process handles: 1. Protection of inline code blocks (backticks) from markup conversion 2. HTML color tags (<color>text</color> and <span style="color:name">text</span>) 3. Bold formatting (**text** or __text__) 4. Italic formatting (*text* or _text_) 5. Strikethrough formatting (~~text~~) 6. Inline code styling with grey on grey15 background Conversion order matters to prevent conflicts between overlapping patterns. Code blocks are protected first using placeholders, then restored after all other conversions to prevent markdown inside code examples from being parsed. Image markdown syntax  is escaped to prevent Spectre.Console from attempting to parse it. .PARAMETER Text The text containing markdown formatting to convert. Can be empty string. Accepts pipeline input. .EXAMPLE ConvertTo-SpectreMarkup -Text "This is **bold** and *italic* text" Returns: "This is [bold]bold[/] and [italic]italic[/] text" .EXAMPLE ConvertTo-SpectreMarkup -Text "Use `Get-Process` to list processes" Returns: "Use [grey on grey15]Get-Process[/] to list processes" Inline code is styled with grey text on dark grey background. .EXAMPLE ConvertTo-SpectreMarkup -Text "This is <red>red text</red> and <cyan>cyan text</cyan>" Returns: "This is [red]red text[/] and [cyan]cyan text[/]" .EXAMPLE ConvertTo-SpectreMarkup -Text "This is <span style='color:magenta'>magenta</span>" Returns: "This is [magenta]magenta[/]" .EXAMPLE "Hello **world**" | ConvertTo-SpectreMarkup Demonstrates pipeline input. Returns: "Hello [bold]world[/]" .EXAMPLE $lines = @( "**Bold** text", "*Italic* text", "~~Strikethrough~~ text" ) $lines | ForEach-Object { ConvertTo-SpectreMarkup -Text $_ } Converts multiple lines with different formatting types. .OUTPUTS System.String Returns the input text with markdown formatting converted to Spectre Console markup tags ([bold], [italic], [color], etc.). .NOTES Conversion Order (important to prevent conflicts): 1. Escape image syntax ( → ![[...]](...)) 2. Extract and protect inline code blocks with placeholders 3. Convert HTML color tags to Spectre markup 4. Convert bold (**text** and __text__) 5. Convert italic (*text* and _text_) 6. Convert strikethrough (~~text~~) 7. Restore protected code blocks Markdown Patterns Supported: - Bold: **text** or __text__ → [bold]text[/] - Italic: *text* or _text_ → [italic]text[/] - Code: `text` → [grey on grey15]text[/] (with proper escaping) - Strikethrough: ~~text~~ → [strikethrough]text[/] - HTML color: <color>text</color> → [color]text[/] - Span color: <span style="color:name">text</span> → [name]text[/] Code Block Protection: - Inline code content is escaped using [Spectre.Console.Markup]::Escape() - Prevents special characters in code from being interpreted as markup - Temporarily replaced with placeholders during other conversions - Restored after all pattern matching complete Image Syntax Escaping: -  → ![[alt]](url) - Prevents Spectre.Console from parsing image references - Preserves image syntax for display as text Color Names: - Must match Spectre.Console.Color names (case-insensitive) - Examples: Red, Green, Blue, Cyan1, Magenta1, Yellow, White, Black - Invalid colors may cause rendering issues Not Supported: - Nested formatting (e.g., ***bold italic***) - Per-character coloring - Links [text](url) - displayed as-is - Block-level markdown (headers, lists, etc.) - handled by slide renderers #> [CmdletBinding()] param( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [AllowEmptyString()] [string]$Text ) process { $result = $Text # Escape markdown image syntax before other conversions to prevent Spectre from parsing it #  or {width=N} -> escaped brackets $result = $result -replace '!\[([^\]]*)\]\(([^)]+)\)(\{width=\d+\})?', '![[${1}]]($2)$3' # Convert code blocks FIRST (backticks) to protect code from other formatting # Use placeholders to prevent color tag regex from matching code content $codeBlocks = @{} $codeIndex = 0 $result = [regex]::Replace($result, '`([^`]+)`', { param($match) $codeContent = $match.Groups[1].Value # Use Spectre's built-in escaping $escapedContent = [Spectre.Console.Markup]::Escape($codeContent) $codeMarkup = "[grey on grey15]$escapedContent[/]" # Store in placeholder $placeholder = "___INLINECODE_${codeIndex}___" $codeBlocks[$placeholder] = $codeMarkup $codeIndex++ return $placeholder }) # Convert HTML color tags to Spectre markup # <span style="color:colorname">text</span> -> [colorname]text[/] $result = $result -replace '<span\s+style=[''"]color:\s*([a-zA-Z][a-zA-Z0-9]*)[''"]>(.*?)</span>', '[$1]$2[/]' # Convert simple color tags: <colorname>text</colorname> -> [colorname]text[/] $result = $result -replace '<([a-zA-Z][a-zA-Z0-9]*)>(.*?)</\1>', '[$1]$2[/]' # Bold: **text** or __text__ -> [bold]text[/] $result = $result -replace '\*\*([^\*]+)\*\*', '[bold]$1[/]' $result = $result -replace '__([^_]+)__', '[bold]$1[/]' # Italic: *text* or _text_ -> [italic]text[/] # Must come after bold to avoid conflicts $result = $result -replace '(?<!\*)\*(?!\*)([^\*]+)(?<!\*)\*(?!\*)', '[italic]$1[/]' $result = $result -replace '(?<!_)_(?!_)([^_]+)(?<!_)_(?!_)', '[italic]$1[/]' # Strikethrough: ~~text~~ -> [strikethrough]text[/] $result = $result -replace '~~([^~]+)~~', '[strikethrough]$1[/]' # Restore code block placeholders foreach ($placeholder in $codeBlocks.Keys) { $result = $result.Replace($placeholder, $codeBlocks[$placeholder]) } return $result } } |