Mastering Markdown

I've loved Markdown since the day it was a Daring Fireball post.
It's a simple rich text format that gets the job done, and it's used everywhere.
Markdown in PowerShell
Markdown is supported out of the box on PowerShell 6+, using the ConvertFrom-Markdown command.
Here's it in action:
"# Hello World" |
ConvertFrom-Markdown |
Select -Expand HTMLLike any other page in a static site, Markdown is just text.
And PowerShell is Pretty Good at manipulating text.
To make PowerShell that outputs markdown, just make simple scripts that spit out text.
Markdown Static Sites
One very simple use of this technique is making static sites with Markdown.
If we don't want to worry about look and feel too much, we can do this with the following pipeline:
"# Markdown" |
ConvertFrom-Markdown |
Select-Object -ExpandProperty Html >
./markdown.htmlIf we wanted to make a page for every file in the directory, we could:
foreach ($file in Get-ChildItem *.md -File) {
ConvertFrom-Markdown -LiteralPath $file.Fullname |
Select-Object -ExpandProperty Html > (
$file.Fullname -replace '\.md$', '.html'
)
}That's a static site generator in six lines of PowerShell!
Here's an even shorter version:
foreach ($file in Get-ChildItem *.md -File) {
$html = (ConvertFrom-Markdown -Path $file.Fullname).html
$html > ($file.Fullname -replace '\.md$', '.html')
}Now we've got a static site generator in four lines!
Static Sites are Simple (with PowerShell).
To make websites in PowerShell, all we need to do is loop over markdown and optionally add some layout.
Making Markdown
We can make markdown in PowerShell by just outputting text.
@(
"# Hello World"
"## How Are You?"
"Today is $([DateTime]::Now.ToShortDateString())"
) > ./example.mdEach line of output will become a line in the markdown file.
We can use conditionals if we want to. Let's switch it up by including the day of week.
@(
"# Hello World"
switch ([DateTime]::Now.DayOfWeek) {
Monday { "Just Another Manic Monday "}
Tuesday { "Taco Tuesday" }
Wednesday { "Halfway thru the week! "}
Thursday { "Almost Friday" }
Friday { "Happy Friday! "}
Saturday { "It's the weekend!"}
default { "It is $([DateTime]::Now.DayOfWeek)" }
}
) > ./example.mdMaking Markdown with Functions
We can make functions that output markdown.
Here's a simple one that outputs headings
function markdown.heading {
param(
[string]$Message = 'Hello World',
[ValidateRange(1,6)]$Level = 1
)
# Multiply our heading character by our level
# and put a space in between the heading and message
('#' * $level), $Message -join ' ''
}
markdown.heading "Markdown Functions"
markdown.heading "Are just functions" -Level 2
markdown.heading "That output markdown" -Level 3Since markdown functions are just PowerShell functions, we can put whatever we want in there.
function markdown.get.process {
# Markdown tables have a header row
"|Name|Id|"
# Followed by a row that aligns text
"|:-|-:|"
# Followed by any number of rows of data
foreach ($process in Get-Process) {
'|' + (
$process.Name, $process.Id -join '|'
) + '|'
}
}
markdown.get.process > ./process.mdNow we hopefully see how easy it is to make markdown in PowerShell.
Just spit out strings.
This is already probably cool enough, but why not make markdown into something we can query?
Making Markdown into XML
ConvertFrom-Markdown converts Markdown into HTML.
It's just a hop, skip, and a jump to make this markdown into XML.
Because all of our tags are perfectly balanced, we can make markdown in XML by just putting it into another element.
Cannonically, I prefer putting markdown into an <article> element
@(
"<article>"
("# Hello World" | ConvertFrom-Markdown).html
"</article>"
) -join '' -as [xml]That's it! We've turned a easy old markdown into hard-to-write XML.
Why is this useful?
Because now we can query markdown.
Markdown, XML, and XPath
To show this in action, let's start really simple:
Let's just get all of the nodes in some markdown
@(
"# Hello World"
"## Don't mind me"
"### Just about to turn markdown into XML"
"> This is pretty cool, right?"
) -join [Environment]::Newline |
ConvertFrom-Markdown |
Foreach-Object {
"<article>$($_.Html)</article>" -as [xml]
} |
Select-Xml //* Let's get all link hrefs in some markdown:
# Make some markdown
@(
"# Some Links"
"* StartAutomating on GitHub"
"* PoshWeb on GitHub"
"* MarkX"
) -join [Environment]::Newline |
# convert it from markdown
ConvertFrom-Markdown |
# turn it into xml
Foreach-Object {
"<article>$($_.Html)</article>" -as [xml]
} |
# pipe it to Select-Xml, picking out any `<a>` elements
Select-Xml //a |
Foreach-Object {
$_.Node.Href
}This is still the tip of the iceberg.
Turning Markdown into XML lets us query and manipulate Markdown in all sorts of interesting ways.
What can you do with Markdown and PowerShell? Almost anything.
Mark My Words
- Markdown is a simple rich text format.
- PowerShell is pretty perfect for making Markdown.
- XPath is excellent at extracting information from Markdown.
You can do a lot of cool things when you mix Markdown with PowerShell.
What do you want to try?