Private/Get-FixFromMarkdown.ps1
|
<#
.SYNOPSIS Extract fix/resolution steps from markdown content. #> function Get-FixFromMarkdown { <# .SYNOPSIS Extract fix, resolution, mitigation, or workaround sections from markdown. .DESCRIPTION Heuristically identifies sections containing fix steps by looking for: - Headings containing: fix, resolution, mitigation, workaround, steps, solution - PowerShell code blocks with commands - Numbered lists or bullet lists following such headings .PARAMETER MarkdownContent The markdown content to parse. .OUTPUTS PSCustomObject with FixSummary and FixSteps properties. #> [CmdletBinding()] [OutputType([PSCustomObject])] param( [Parameter(Mandatory)] [AllowEmptyString()] [string]$MarkdownContent ) $result = [PSCustomObject]@{ FixSummary = '' FixSteps = @() } if ([string]::IsNullOrWhiteSpace($MarkdownContent)) { return $result } # Look for sections with fix-related keywords $fixKeywords = @('fix', 'resolution', 'mitigation', 'workaround', 'solution', 'steps', 'remediation', 'repair', 'command') $lines = $MarkdownContent -split "`r?`n" $inFixSection = $false $inCodeBlock = $false $currentSection = @() $fixSectionContent = @() $codeBlockLines = @() $codeBlockMarker = '```' for ($i = 0; $i -lt $lines.Count; $i++) { $line = $lines[$i] # Check for code block markers if ($line.Trim() -match '^```') { if ($inCodeBlock) { # End of code block - save it if we're in a fix section if ($inFixSection -and @($codeBlockLines).Count -gt 0) { $currentSection += $codeBlockMarker $currentSection += $codeBlockLines $currentSection += $codeBlockMarker } $codeBlockLines = @() $inCodeBlock = $false } else { # Start of code block $inCodeBlock = $true $codeBlockLines = @() } continue } # Collect code block content if ($inCodeBlock) { $codeBlockLines += $line continue } # Check if this is a heading with fix keywords if ($line -match '^#{1,6}\s+(.+)$') { $heading = $matches[1].ToLowerInvariant() # If we were in a fix section, save it if ($inFixSection -and @($currentSection).Count -gt 0) { $fixSectionContent += $currentSection $currentSection = @() } # Check if this heading indicates a fix section $inFixSection = $false foreach ($keyword in $fixKeywords) { if ($heading -like "*$keyword*") { $inFixSection = $true $currentSection += $line break } } } elseif ($inFixSection) { # Collect content within fix section $currentSection += $line } } # Add final section if we were in one if ($inFixSection -and @($currentSection).Count -gt 0) { $fixSectionContent += $currentSection } # Extract steps from fix section content $steps = @() $inExtractCodeBlock = $false $currentCodeBlock = @() foreach ($line in $fixSectionContent) { # Handle code blocks if ($line.Trim() -match '^```') { if ($inExtractCodeBlock) { # End of code block - add as a single step if (@($currentCodeBlock).Count -gt 0) { # Get first few non-comment, non-empty lines $codeLines = $currentCodeBlock | Where-Object { $_.Trim() -ne '' -and -not ($_.TrimStart() -match '^#[^!]') } | Select-Object -First 5 if (@($codeLines).Count -gt 0) { $codeText = $codeLines -join "`n" if ($codeText.Length -gt 150) { $codeText = $codeText.Substring(0, 147) + '...' } $steps += "Run PowerShell: $codeText" } } $currentCodeBlock = @() $inExtractCodeBlock = $false } else { $inExtractCodeBlock = $true } continue } if ($inExtractCodeBlock) { $currentCodeBlock += $line continue } # Numbered list item (e.g., "1. Step one") if ($line -match '^\s*\d+\.\s+(.+)$') { $steps += $matches[1].Trim() } # Bullet list item (e.g., "- Step one" or "* Step one") elseif ($line -match '^\s*[-*]\s+(.+)$') { $steps += $matches[1].Trim() } # Lines starting with "Then" or "Next" or "Now" elseif ($line -match '^\s*(Then|Next|Now|After|Finally)\s+(.+)$') { $steps += $matches[2].Trim() } } # Create fix summary (first non-empty paragraph in fix section) $summary = '' foreach ($line in $fixSectionContent) { if (-not [string]::IsNullOrWhiteSpace($line) -and $line -notmatch '^\s*[-*\d]' -and $line -notmatch '^#{1,6}\s' -and $line.Trim() -notmatch '^```') { $summary = $line.Trim() if ($summary.Length -gt 200) { $summary = $summary.Substring(0, 197) + '...' } break } } $result.FixSummary = $summary $result.FixSteps = $steps return $result } |