Unleash Pug templates in PowerShell. A versatile CLI for HTML pipelines and a loyal View Engine for your Pode Server projects. πΎ
PugPS is a PowerShell-native implementation of the Pug (formerly Jade) templating engine. It allows you to write clean, indented templates and render them into HTML using PowerShell logic, variables, and functions (JavaScript logic is not supported).
Install-Module -name PugPSLatest version: https://github.com/BananaAcid/PugPS
The general PugJS Language Reference applies. Powershell specific usage is below.
How does Pug look like? See: https://html-to-pug.com/
To use PugPS as your view engine in a Pode server, import the module and initialize the engine within your Start-PodeServer block.
Start-PodeServer {
# Import the view engine module
Import-Module PugPS
# Configure the engine
Set-PodeViewEnginePug -Extension 'pode.pug' -ErrorOutput 'text'
}| Parameter | Type | Req | Default | Description |
|---|---|---|---|---|
| -Extension | string |
Yes | - | The default file extension to target (e.g., pode.pug). |
| -BaseDir | string |
No | "" |
The root directory used to resolve absolute include/extend paths (starting with / or \). |
| -Filters | sb|string |
No | $null |
The path to a .ps1 filters file or a scriptblock containing filter functions. |
| -Properties | bool |
No | $true |
When $true (default), boolean attributes render as attr. When $false, attr='attr'. |
| -VoidTagsSelfClosing | bool |
No | $false |
When $true, standard void tags (like img, br) render as <img />. |
| -ContainerTagsSelfClosing | bool |
No | $false |
When $true, empty container tags (like div) render as <div />. |
| -KebabCaseHTML | bool |
No | $true |
When $true, CamelCase tags in PUG are converted to kebab-case. |
| -ErrorOutput | string |
No | 'rethrow' |
'text' returns HTML error; 'rethrow' triggers the Pode error page. |
| -ErrorContextRange | int |
No | 2 |
Number of context lines to show before and after the error line. |
Use Invoke-PUG for automation, build pipelines, or one-off conversions.
Import-Module PugPS
# Example 1: Convert a file with data and external filters
Invoke-PUG -Path .\test.pug -Data @{
Title = "Pug PowerShell"
Users = @(@{ Name = "Alice"; Role = "Admin" })
} -Filters .\helper.ps1
# Example 2: Pipe content directly with a scriptblock filter
@"
div
:MyFilter
Content
"@ | Invoke-PUG -Filters {
Function MyFilter {
param([Parameter(ValueFromPipeline=$true)]$text)
"<b>$text</b>"
}
}| Parameter | Type | Req | Default | Description |
|---|---|---|---|---|
| -Path | string |
Yes* | - | Path to Pug Template file (Mandatory if not using pipeline). |
| -InputContent | string[] |
Yes* | - | The raw Pug template content (supports pipeline input). |
| -Data | hashtable |
No | @{} |
The data passed to the template as $data. |
| -Filters | sb|string |
No | $null |
Path to filters file (ps1) or a scriptblock with filter functions. |
| -Extension | string |
No | 'pug' |
The default file extension to use for included files. |
| -BaseDir | string |
No | "" |
Root directory used to resolve absolute include/extend paths. |
| -Properties | bool |
No | $true |
If $true, boolean attributes render as attr. |
| -VoidTagsSelfClosing | bool |
No | $false |
If $true, void tags render with a self-closing slash. |
| -ContainerTagsSelfClosing | bool |
No | $false |
If $true, empty container tags render as self-closing. |
| -KebabCaseHTML | bool |
No | $true |
If $true, converts CamelCase tags to kebab-case. |
| -ErrorContextRange | int |
No | 2 |
Context lines to show before/after error line. |
PugPS supports standard PowerShell logic using the - prefix.
- Foreach ($u in $data.Users)
li= $u.Name
- If ($a -eq $true)
li TRUE
- ElseIf ($a -eq $false)
li FALSE
- Else
li Unknown
- Switch ($data.Status)
- "active"
li User is Active
- "disabled"
li User is Locked
- default
li Status Unknown- these can be done with
- Foreach,- If,- For... while keeping the powershell syntax (the PugJS specific implementation is not supported)
PugPS handles PowerShell collections intelligently for clean attribute management.
- Classes from Array: Simple list output.
- $classes = "btn", "btn-primary" button(class=$classes) // <button class="btn btn-primary">
- Classes from Object: Keys mapped to
$trueare included;$falseare omitted.- $classesObj = @{ active = $true; hidden = $false } div(class=$classesObj) // <div class="active">
- Styles from Object: Keys in
camelCaseare automatically converted tokebab-case.- $styles = @{ backgroundColor = "red"; borderRadius = "5px" } div(style=$styles) // <div style="background-color:red;border-radius:5px">
- Attribute Values: These are PowerShell expressions. Double quotes
" "expand variables; single quotes' 'do not. - Content Interpolation: Use
$( $var )or${ $var }for raw content, and#( $var )or#{ $var }for escpaed HTML content. Preferred: use$()and#(). - Escaping: To escape a dollar sign in content, use
\$or`$. (\and`can be escaped as well.)
attr='$a'var will not be parsed (singe quotes),attr="$a"var will be parsed (double quotes),$attr=$avar will be parsed (no quotes).
For body(class=$authenticated ? 'authed' : 'anon' ...) and alike, you should use body(class=$($authenticated ? 'authed' : 'anon') ...) - wrapping the logic in $()
Filters trigger standard PowerShell functions. The nested content is passed via the pipeline. Params are used by their names.
:MyFilter(param="value")
Content here is passed to the functionTo access the pipeline value use [Parameter(ValueFromPipeline=$true)]$text (Conntent is passed as one single string, there is no need to collect lines)
Function TestFN {
param(
$title,
[Parameter(ValueFromPipeline=$true)]$text
)
"<div>" $title + '<br>' + ($text ? $text : "-- no text --") + "<div>"
}A filter can also be created inline in within the Pug (using - Function TestFN{...})
- Shortcuts:
5(HTML5),smil1,smil2, ... and for the PugJS default oness look them up here - Casing: When using the XML doctype,
KebabCaseHTMLis automatically disabled to preserve XML casing. - XML Mode: For XML types (plist, svg1.1, smil1, smil2, etc.), always include
doctype xmlfirst.
Example:
doctype xml
doctype plist
plist(version="1.0")
dict
...A specific doctype for SVG Tiny 1.1 and 1.2 is not recomended. Only use: doctype xml
Are supported as defined by PugJS.
- https://pugjs.org/language/includes.html
- https://pugjs.org/language/mixins.html
- https://pugjs.org/language/inheritance.html
If you need to generate the PowerShell script representation of a Pug file without immediately rendering it, use Convert-PugToPowerShell.
You need to save the module into your project first:
Save-Module -Name PugPS -Path .\ # this creates a subfolder .\PugPS\1.0.0\Then use it:
. .\PugPS\1.0.0\parser.ps1
$psCode = Convert-PugToPowerShell -Path "template.pug" -KebabCaseHTML $true| Parameter | Type | Req | Default | Description |
|---|---|---|---|---|
| -Path | string |
Yes* | - | Path to Pug Template file (Mandatory if not using pipeline). |
| -InputContent | string[] |
Yes* | - | The raw Pug template content (supports pipeline input). |
| -Extension | string |
No | 'pug' |
Extension for included files. |
| -BaseDir | string |
No | "" |
Root directory for absolute paths. |
| -Properties | bool |
No | $true |
Render boolean attributes as attr. |
| -VoidTagsSelfClosing | bool |
No | $false |
Render void tags with /. |
| -ContainerTagsSelfClosing | bool |
No | $false |
Render empty containers with /. |
| -KebabCaseHTML | bool |
No | $true |
Convert CamelCase tags to kebab-case. |
| -ErrorContextRange | int |
No | 2 |
Error context line count. |