Some Powershell scripts for creating a new Jekyll blog post and for adding an additional post in a series of posts using the previous post’s Front Matter using the same Title but requiring a new Subtitle.

This site is built using Jekyll as a static web site. When authoring blog posts on this site, the posts are written as Markdown text files with Front Matter meta-data at the top. The site is then reposited to Azure Devops where it is built and published to Azure as a Blob Storage Static Website Some of that Front Matter is standard, some of it custom depending upon the post’s context. Authoring is done as a Visual Studio Code project. Sometime ago, a Powershell script was created that prompts for the Front Matter properties, adds some set site fixed properties and then generates the post file with the Front Matter at the top using a filename created from the Front Matter properties. Recently a similar Powershell script was created to clone an existing post using the same Front Matter except for the Subtitle.

Nb The scripts are placed in the scripts/ directory but run from the root of the site’s root. eg:
scripts/new-post.ps1
and
scripts/clone.ps1

---
layout: postpage
title: Jekyll
subtitle: New post and Clone PS scripts
category: web
tags: jekyll powershell
excerpt_separator: <!--more-->
date: 2023-09-11 22:48:25
author: me
disqus: 1
--- 

The generated Front Matter for this post

A. Create a new post Powershell script

1. The meta-information

This is prompted for when the script first runs and is used to generate the Front Matter.

param (
  [Parameter(Mandatory)]
    [string]$title, 
  [Parameter(Mandatory)]
    [string]$subtitle,
  [Parameter(Mandatory)]
    [string]$cat, 
  [Parameter(Mandatory)]
    [string]$tags,
    [string]$author = 'me',
    [string]$disqus = '1'
)

2. Get new post filename from parameters etc.

$cat=$cat.ToLower()
$tags=$tags.ToLower()

# Assumes run from root of Jekyll project
$sections = $pwd.Path + '\_data\sections.yml'
if ( Test-Path $sections ) 
{ 

  $titlex = $title.Replace( ' ', '_')

  # Use a single character if no subtitle
  $subtitlex  = $subtitle.Replace( ' ', '_')
  If ($subtitle.Length -lt 2)
  {
    $subtitlex = '';
    $subtitle  = '';
  }



  $createDate=(Get-Date).ToString("yyyy-MM-dd")
  $createTime=(Get-Date).ToString("HH:mm:ss")

  If ([string]::IsNullOrEmpty($subtitle))
  {
    $filename = $createDate + '-' +  $titlex +  '-' +  $cat + ".md"
  }
  Else
  {
    
    $filename = $createDate + '-' +  $titlex +  '-' +  $subtitlex +  '-' +  $cat + ".md"
  }

  $filename = '.\_Posts\' + $filename

  Write-Output $filename

3. Generate the new post


  # Create new file
  New-Item $filename

  ## Write Front Matter
  Set-Content $filename '---'
  Add-Content $filename 'layout: postpage'

  $line = 'title: ' + $title
  Add-Content $filename  $line

  If (![string]::IsNullOrEmpty($subtitle))
  {
    $line = 'subtitle: ' + $subtitle
    Add-Content $filename  $line
  }

  $line = 'category: ' + $cat
  Add-Content $filename  $line
  $line = 'tags: ' + $tags
  Add-Content $filename  $line
  $line = 'date: ' + $createDate + ' ' + $createTime
  Add-Content $filename  $line
  $line = 'author: ' + $author
  Add-Content $filename  $line
  $line = 'excerpt_separator: # more '
  Add-Content $filename $line
  $line = 'disqus: ' + $disqus
  Add-Content $filename  $line
  Add-Content $filename '---'
  # Got Front Matter

  # Add summary section
  Add-Content $filename ''
  Add-Content $filename '_Insert summary here_'
  Add-Content $filename '# more '
  Add-Content $filename ''

  # Display file
  Get-Content $filename
  # Load the new post into VS Code 
  code $filename
}
else 
{
    write-Output Run from root of Jekyll Project
}

B. Clone Front Matter from an existing Post Powershell script

1. Get Front Matter and new post filename from existing post

# Popup menu of existing posts. Can filter therein. 
$filenameIn = Get-ChildItem .\_posts | Out-GridView -Title 'Choose a file'  -OutputMode Single | ForEach-Object { $_.FullName }

# Parse existing post 
$inFront Matter = $false
foreach($line in Get-Content $filenameIn) 
{
    #  Lines '---' start and end existing post's Front Matter 
    if($line -match '---')
    {      
        if($inFront Matter)
        {
            break
        }
        else
        {
            $inFront Matter=$true
        }
    }
    else
    {
        if($inFront Matter)
        {
            # Get Front Matter properties and values 
            $parts = $line -split ':'
            switch ($parts[0])
            {
                "title" {$title = $parts[1].Trim()}
                "subtitle" {$subtitle = $parts[1].Trim()}
                "category" {$category = $parts[1].Trim()}
                "tags" {$tags = $parts[1].Trim()}
                "author" {$author = $parts[1].Trim()}
            }
        }
    }
}
# Title is unchanged but get new Subtitle for new post 
Write-Host "Title: $title"
$prompt = "Enter SubTitle ($subtitle)"
$subtitle = Read-Host $prompt

# Get new filename 
$createDate=(Get-Date).ToString("yyyy-MM-dd")
$createTime=(Get-Date).ToString("HH:mm:ss")
$filename = $createDate + '-' +  $title +  '-' +  $subtitle +  '-' +  $category + ".md"
$filename = '.\_posts\' + $filename

Write-Output $filename

2. Generate the new post


# Create the new file 
New-Item $filename
$inFront Matter = $false

# Parse the existing post again 
foreach($line in Get-Content $filenameIn) 
{
    if($line -match '---')
    {
        if($inFront Matter)
        {
            # If second '---' stop Front Matter 
            Add-Content $filename $line
            break
        }
        else
        {
            # If first '---' start Front Matter 
            Set-Content $filename $line
            $inFront Matter=$true
        }
    }
    else
    {
        if($inFront Matter)
        {
            # Get a new Subtitle 
            if( $line -like "subtitle:*")
            {
                If (![string]::IsNullOrEmpty($subtitle))
                {
                    $line = 'subtitle: ' + $subtitle
                    Add-Content $filename  $line
                }
            }
            elseif( $line -like "date:*")
            {
                # New date in Front Matter 
                $line = 'date: ' + $createDate + ' ' + $createTime
                Add-Content $filename  $line
            }
            else
            {
                # Otherwise just copy the Front Matter line 
                Add-Content $filename $line
            }
        }
    }
}
# After the Front Matter add post summary location
Add-Content $filename ''
Add-Content $filename '_Insert summary here_'
Add-Content $filename '# more '
Add-Content $filename ''

# Display the new post 
Get-Content $filename
# Load the new post into VS Code
code $filename

Footnote

A little bit on analysis!

When the previous post was created by cloning a prior post with the clone script as above, the new post was not listed at the top of the list of posts on the blog site’s index page when published. It could though be found by searching, especially by doing a category search. There was a hint which did made sense later once the issue was solved but could have been used as a clue to solving the problem: The [Next] link from the new post pointed to an older post. Being the latest post [Next] shouldn’t point to any post! The fault turned out to be that the date specified in the Front Matter. Whilst the new date for the cloned post was used in the filename, it wasn’t updated in the Front Matter. The original post’s date was used. When run locally using jekyll serve the post links on the index page are sorted in reverse date order as per the post filename which includes the date. When published to Azure as a Blob Storage Static Website, the Front Matter date is used for sorting posts on the index page. When the Front Matter was fixed wrt date the latest post was placed first on the site’s index page.


 TopicSubtopic
  Next: > Wilderness Labs
<  Prev:   Aged Care Independent Living
   
 This Category Links 
Category:Web Sites Index:Web Sites
  Next: > Blazor Server Development
<  Prev:   GPS