Syntax Highlighting PowerShell Code in HTML - With a PowerShell Script

  • Scripting
  • Published Jan 18, 2010 Updated Jan 4, 2026

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](/files/Highlight-Syntax/Highlight-Syntax v1.1.zip).

Comments

Related Posts

Creating Realistic Test User Accounts in Active Directory

Creating Realistic Test User Accounts in Active Directory
When you need to simulate a real Active Directory with thousands of users you quickly find that creating realistic test accounts is not trivial. Sure enough, you can whip up a quick PowerShell one-liner that creates any number of accounts, but what if you need real first and last names? Real (existing) addresses? Postal codes matching phone area codes? I could go on. The point is that you need two things: input files with names, addresses etc. And script logic that creates user accounts from that data. This blog post provides both.
Scripting

PowerShell Script: Test Chrome, Firefox & IE Browser Performance

PowerShell Script: Test Chrome, Firefox & IE Browser Performance
There is more than one way to test the performance of web browsers like Chrome, Firefox, or IE, but regardless of how you do it, you need a consistent workload that makes the browsers comparable. Unless you are testing with synthetic benchmarks (which come with a plethora of problems of their own) you need a way to automate browsers opening tabs and loading URLs. This article presents a simple solution to do just that.
Scripting

Latest Posts

Fast & Silent 5 Watt PC: Minimizing Idle Power Usage

Fast & Silent 5 Watt PC: Minimizing Idle Power Usage
This micro-series explains how to turn the Lenovo ThinkCentre M90t Gen 6 into a smart workstation that consumes only 5 Watts when idle but reaches top Cinebench scores while staying almost imperceptibly silent. In the first post, I showed how to silence the machine by replacing and adding to Lenovo’s CPU cooler. In this second post, I’m listing the exact configuration that achieves the lofty goal of combining minimal idle power consumption with top Cinebench scores.
Hardware

Fast & Silent 5 Watt PC: Lenovo ThinkCentre M90t Modding

Fast & Silent 5 Watt PC: Lenovo ThinkCentre M90t Modding
This micro-series explains how to turn the Lenovo ThinkCentre M90t Gen 6 into a smart workstation that consumes only 5 Watts when idle but reaches top Cinebench scores while staying almost imperceptibly silent. In this first post, I’m showing how to silence the machine by replacing and adding to Lenovo’s CPU cooler. In a second post, I’m listing the exact configuration that achieves the lofty goal of combining minimal idle power consumption with top Cinebench scores.
Hardware