Syntax Highlighting PowerShell Code in HTML – With a PowerShell Script
When you are publishing PowerShell code on the web, you soon discover that it looks much nicer with syntax highlighting – as did I. There are several ways to add syntax highlighting to your blog or web site, most of which rely on external (WordPress) plugins or JavaScript on the page. I do not like that approach too much. I prefer to have the syntax highlighting embedded in the HTML code. That way I have full control over the appearance (and the highlighting also works in the RSS feed). The logical solution is to use a script that embeds HTML coloring tags directly into the script.
Highlight-Syntax.ps1
My script Highlight-Syntax.ps1 is a much stripped down and slightly changed version of Lee Holmes’ Set-ClipboardScript.ps1 – thank you for making it available, Lee!
You call Highlight-Syntax.ps1 with the name of a PowerShell script which it parses and then generates an HTML file with a colorized version of that script. If you input Get-AppVPackageDependencies.ps1 you will get Get-AppVPackageDependencies.ps1.html. That is it. The code in the HTML file can then easily be pasted into your favorite blog editor.
Highlight-Syntax.ps1 does not create fully-featured HTML files with head and body tags. That is by design. It simply takes your code and adds color information to it.
The Code – And a Sample
Here is the script which doubles as a sample of what its output looks like.
# # Original Author: Lee Holmes, http://www.leeholmes.com/blog/MorePowerShellSyntaxHighlighting.aspx # # Modified by: Helge Klein, https://helgeklein.com/ # # # Syntax highlights a PowerShell script. # # Usage: Supply the script to syntax hightligh as first and only parameter # # Output: Copy of original script with extension ".html" # # Example: .\Highlight-Syntax.ps1 .\Get-AppVPackageDependencies.ps1 # # Version history: # # 1.1: # # - Loading the required assembly System.Web now. This was missing earlier. # # 1.0: Initial version # [CmdletBinding()] param($path) # Load required assemblies [void] [System.Reflection.Assembly]::Load("System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a") $tokenColours = @{ 'Attribute' = '#FFADD8E6' 'Command' = '#FF0000FF' 'CommandArgument' = '#FF8A2BE2' 'CommandParameter' = '#FF000080' 'Comment' = '#FF006400' 'GroupEnd' = '#FF000000' 'GroupStart' = '#FF000000' 'Keyword' = '#FF00008B' 'LineContinuation' = '#FF000000' 'LoopLabel' = '#FF00008B' 'Member' = '#FF000000' 'NewLine' = '#FF000000' 'Number' = '#FF800080' 'Operator' = '#FFA9A9A9' 'Position' = '#FF000000' 'StatementSeparator' = '#FF000000' 'String' = '#FF8B0000' 'Type' = '#FF008080' 'Unknown' = '#FF000000' 'Variable' = '#FFFF4500' } # Generate an HTML span and append it to HTML string builder $currentLine = 1 function Append-HtmlSpan ($block, $tokenColor) { if (($tokenColor -eq 'NewLine') -or ($tokenColor -eq 'LineContinuation')) { if($tokenColor -eq 'LineContinuation') { $null = $codeBuilder.Append('`') } $null = $codeBuilder.Append("<br />`r`n") } else { $block = [System.Web.HttpUtility]::HtmlEncode($block) if (-not $block.Trim()) { $block = $block.Replace(' ', ' ') } $htmlColor = $tokenColours[$tokenColor].ToString().Replace('#FF', '#') if($tokenColor -eq 'String') { $lines = $block -split "`r`n" $block = "" $multipleLines = $false foreach($line in $lines) { if($multipleLines) { $block += "<BR />`r`n" } $newText = $line.TrimStart() $newText = " " * ($line.Length - $newText.Length) + $newText $block += $newText $multipleLines = $true } } $null = $codeBuilder.Append("<span style='color:$htmlColor'>$block</span>") } } function Main { $text = $null if($path) { $text = (Get-Content $path) -join "`r`n" } else { Write-Error 'Please supply the path to the PowerShell script to syntax highlight as first (and only) parameter.' return } trap { break } # Do syntax parsing. $errors = $null $tokens = [system.management.automation.psparser]::Tokenize($Text, [ref] $errors) # Initialize HTML builder. $codeBuilder = new-object system.text.stringbuilder # Iterate over the tokens and set the colors appropriately. $position = 0 foreach ($token in $tokens) { if ($position -lt $token.Start) { $block = $text.Substring($position, ($token.Start - $position)) $tokenColor = 'Unknown' Append-HtmlSpan $block $tokenColor } $block = $text.Substring($token.Start, $token.Length) $tokenColor = $token.Type.ToString() Append-HtmlSpan $block $tokenColor $position = $token.Start + $token.Length } # Build the entire syntax-highlighted script $code = $codeBuilder.ToString() # Replace tabs with three blanks $code = $code -replace "\t"," " # Write the HTML to a file $code | set-content -path "$path.html" } . Main
Download
You can download a digitally signed version of the script here.
7 Comments
I get this message when i m trying to use this script….not sure what\’s wrong.
PS C:\\KC\\PowerShell\\Store\\Highlight-Syntax> .\\Highlight-Syntax.ps1 .\\Get-CitrixPrinterInfo.ps1
You must provide a value expression on the right-hand side of the \’-\’ operator.
At C:\\KC\\PowerShell\\Store\\Highlight-Syntax\\Highlight-Syntax.ps1:68 char:21
+ $lines = $block -s <<<< plit \"`r`n\"
Please check line #68: Do you have a blank in “-split”? It should look like this:
$lines = $block -split “`r`n”
What do we need to chhnge to handle Multi-Line-Comments and Tabs/Indention correctly?
Line 146 should say: $code = $code -replace “\t”,” ”
To make tab indent work properly.
Thank you very much for this! I’ve spent the last hour googling around for something that would do this. Great piece of code – keep up the good work!
This code is very useful.
Here the small modification I made to input/output from Clipboard:
if($path)
{
$text = (Get-Content $path) -join “`r`n”
}
else
{
Write-Output ‘Please supply the path to the PowerShell script to syntax highlight as first (and only) parameter.’
Write-Output ‘We will work with the clipboard then…’
$Text = $(Get-Clipboard) -join “`r`n”
# return
}
…
if($path){
# Write the HTML to a file
$code | set-content -path “$path.html”
} else {
$code | Set-Clipboard
}
Thanks a lot!.
I’ve forked your script with few adjustments:
– works on strings, not files
– sets span class names instead of hardcoded colors (see sample CSS), more flexible
– uses real tab instead of spaces (use CSS tab-size to fit your needs or origin IDE)
– replaces other characters that do sometimes cause issues with scripts (“{}$”)
Reworked script and sample CSS:
– https://pastebin.com/bAEadaSg
– https://pastebin.com/4bjSdEte