PowerShell Syntax Highlighting script


As a SharePoint administrator, I end up either writing a lot of PowerShell scripts or copying existing scripts and modifying them to fit a new need.  With all of these scripts comes the need to share them with other admins outside of the command line and in such a way that allows them to be easily read.  To this end, I thought that something that could do syntax highlighting would really be handy so I set out in search of some way to parse a PowerShell script, highlight it and then create a self-contained HTML file that could then be used elsewhere or even just pasted into SharePoint in some fashion.

After some searching, I ran across Helge Klein’s script that does exactly what I was looking for – well, almost.  His script perfectly parsed a PowerShell file and created an HTML file with the highlighting but was limited in that it could only apply color to the various elements in the output.  I needed to also specify bolding and italics so I updated his script to use CSS classes instead of fixed colors. This gives almost unlimited flexibility to formatting including background colors, images, custom fonts, or whatever else your CSS mind can come up with.

I hope someone else finds it useful!


# Original Author: Lee Holmes, http://www.leeholmes.com/blog/MorePowerShellSyntaxHighlighting.aspx
# Modified by: Helge Klein, http://blogs.sepago.de/helge/
# (http://blogs.sepago.de/e/helge/2010/01/18/syntax-highlighting-powershell-code-in-html-with-a-powershell-script)
# Modified again by: David Wise, http://blog.davidjwise.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.2: David Wise
# – Converted to use CSS Classes instead of fixed color values
#
# 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")
# define the CSS Classes for the various elements. the prefix of 'pshs' is to hopefully make the class names unique in almost any
# environment. It is short for "PowerShell Highlight Syntax"
$styles = "
<style type=""text/css"">
.pshs-Body {
font-size: 12px;
font-family: ""Courier New"",Courier,monospace;
line-height:12px;
}
.pshs-Attribute { color: #ADD8E6; }
.pshs-Command { color: #0000FF; font-weight:bold; }
.pshs-CommandArgument { color: #8A2BE2; }
.pshs-CommandParameter { color: #000080; }
.pshs-Comment { color: #006400; font-style:italic; }
.pshs-GroupEnd { color: #000000; }
.pshs-GroupStart { color: #000000; }
.pshs-Keyword { color: #00008B; }
.pshs-LineContinuation { color: #000000; }
.pshs-LoopLabel { color: #00008B; }
.pshs-Member { color: #000000; }
.pshs-NewLine { color: #000000; }
.pshs-Number { color: #800080; }
.pshs-Operator { color: #A9A9A9; }
.pshs-Position { color: #000000; }
.pshs-StatementSeparator { color: #000000; }
.pshs-String { color: #8B0000; background-color:ECECEC; }
.pshs-Type { color: #008080; }
.pshs-Unknown { color: #000000; }
.pshs-Variable { color: #FF4500; }
</style>
"
# 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(' ', '&nbsp;')
}
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 = "&nbsp;" * ($line.Length – $newText.Length) + $newText
$block += $newText
$multipleLines = $true
}
}
$null = $codeBuilder.Append("<span class=""pshs-$tokenColor"">$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
$null = $codeBuilder.Append($styles)
$null = $codeBuilder.Append("<span class=""pshs-Body"">")
# 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
}
$null = $codeBuilder.Append("</span>");
# Build the entire syntax-highlighted script
$code = $codeBuilder.ToString()
# Replace tabs with three blanks
$code = $code -replace "\t","&nbsp;&nbsp;&nbsp;"
# Write the HTML to a file
$code | set-content -path "$path.html"
}
. Main

 

Leave a comment