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(' ', '&nbsp;')
      }

      $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 = "&nbsp;" * ($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.

, ,

5 Responses to Syntax Highlighting PowerShell Code in HTML – With a PowerShell Script

  1. VJ January 27, 2010 at 04:17 #

    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\"

    • Helge Klein January 27, 2010 at 09:39 #

      Please check line #68: Do you have a blank in “-split”? It should look like this:

      $lines = $block -split “`r`n”

  2. Torpedro May 20, 2011 at 15:02 #

    What do we need to chhnge to handle Multi-Line-Comments and Tabs/Indention correctly?

  3. Mark September 11, 2017 at 20:41 #

    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!

Trackbacks/Pingbacks

  1. Powershell : tableau multidimensionnel (array de array) | Blog de Mathieu Chateau - January 12, 2011

    […] la coloration syntaxique dans le blog, j’ai utilisé le script PowerShell proposé ici: https://helgeklein.com/blog/2010/01/syntax-highlighting-powershell-code-in-html-with-a-powershell-scr… AKPC_IDS += "906,";Popularity: unranked [?]SHARETHIS.addEntry({ title: "Powershell : tableau […]

Leave a Reply