Alt3.Docusaurus.Powershell.psm1
#Region 'PREFIX' 0 Set-StrictMode -Version Latest $PSDefaultParameterValues['*:ErrorAction'] = 'Stop' # full stop on first error #EndRegion 'PREFIX' #Region '.\Private\GetCustomEditUrl.ps1' 0 function GetCustomEditUrl() { <# .SYNOPSIS Returns the `custom_edit_url` for the given .md file. .DESCRIPTION Generates a URL pointing to the Powershell source file that was used to generate the markdown file. .NOTES - URLs for non-monolithic modules point to a .ps1 file with same name as the markdown file - URLs for monolithic modules will always point to a .psm1 with same name as passed module #> param( [Parameter(Mandatory = $True)][string]$Module, [Parameter(Mandatory = $True)][System.IO.FileSystemInfo]$MarkdownFile, [Parameter(Mandatory = $False)][string]$EditUrl, [switch]$Monolithic ) # return "false" so Docusaurus will not render the `Edit this page` button if (-not($EditUrl)) { return } # point to the function source file for non-monlithic modules if (-not($Monolithic)) { $command = [System.IO.Path]::GetFileNameWithoutExtension($MarkdownFile) return $EditUrl + '/' + $command + ".ps1" } # point to the module source file for monolithic modules if (Test-Path $Module) { $Module = [System.IO.Path]::GetFileNameWithoutExtension($Module) } return $EditUrl + '/' + $Module + ".psm1" } #EndRegion '.\Private\GetCustomEditUrl.ps1' 38 #Region '.\Private\GetMdxFilePath.ps1' 0 function GetMdxFilePath() { <# .SYNOPSIS Returns the .mdx file path for a given .md file. #> param( [Parameter(Mandatory = $True)][System.IO.FileSystemInfo]$MarkdownFile ) Join-Path $MarkdownFile.DirectoryName -ChildPath "$([System.IO.Path]::GetFileNameWithoutExtension($MarkdownFile.Name)).mdx" } #EndRegion '.\Private\GetMdxFilePath.ps1' 11 #Region '.\Private\NewSidebarIncludeFile.ps1' 0 function NewSidebarIncludeFile() { <# .SYNOPSIS Generates a `.js` file holding an array with all .mdx 'ids` to be imported in Docusaurus `sidebar.js`. .LINK https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-powershell-1.0/ff730948(v=technet.10) #> param( [Parameter(Mandatory = $True)][string]$OutputFolder, [Parameter(Mandatory = $True)][string]$Sidebar, [Parameter(Mandatory = $True)][Object]$MarkdownFiles ) # generate a list of Powershell commands by stripping .md from the generated PlatyPs files [array]$commands = $MarkdownFiles | Select-Object @{ Name = "PowershellCommand"; Expression={ "'$Sidebar/" + [System.IO.Path]::GetFileNameWithoutExtension($_) + "'" } } | Select-Object -Expand PowershellCommand # generate content using Here-String block $content = @" /** * Import this file in your Docusaurus ``sidebars.js`` file. * * Auto-generated by Alt3.Powershell.Docusaurus. * * Copyright (c) 2019-present, ALT3 B.V. * * Licensed under the MIT license. */ module.exports = [ $($commands -Join ",`n ") ]; "@ # generate file path, convert relative outputfolder to absolute if needed if (-Not([System.IO.Path]::IsPathRooted($OutputFolder))) { $outputFolder = Join-Path "$(Get-Location)" -ChildPath $OutputFolder } $filePath = Join-Path -Path $OutputFolder -ChildPath "docusaurus.sidebar.js" # create the file $fileEncoding = New-Object System.Text.UTF8Encoding $False [System.IO.File]::WriteAllLines($filePath, $content, $fileEncoding) # add created file to output Get-Item $filePath } #EndRegion '.\Private\NewSidebarIncludeFile.ps1' 48 #Region '.\Private\RemoveMarkdownHeaderOne.ps1' 0 function RemoveMarkdownHeaderOne() { <# .SYNOPSIS Removes the H1 element from the markdown content because Docusaurus already generates H1 using the `title` front matter. #> param( [Parameter(Mandatory = $True)][System.IO.FileSystemInfo]$MarkdownFile ) $content = (Get-Content -Path $MarkdownFile.FullName -Raw).TrimEnd() $regex = '\n#{1}\s.+\n\r' $newContent = [regex]::replace($content, $regex, '') # replace file (UTF-8 without BOM) $fileEncoding = New-Object System.Text.UTF8Encoding $False [System.IO.File]::WriteAllLines($markdownFile.FullName, $newContent, $fileEncoding) } #EndRegion '.\Private\RemoveMarkdownHeaderOne.ps1' 19 #Region '.\Private\SetMarkdownFrontMatter.ps1' 0 function SetMarkdownFrontMatter() { <# .SYNOPSIS Replaces PlatyPS generated front matter with Docusaurus compatible front matter. .LINK https://www.apharmony.com/software-sagacity/2014/08/multi-line-regular-expression-replace-in-powershell/ #> param( [Parameter(Mandatory = $True)][System.IO.FileSystemInfo]$MarkdownFile, [Parameter(Mandatory = $False)][string]$CustomEditUrl, [Parameter(Mandatory = $False)][string]$MetaDescription, [Parameter(Mandatory = $False)][array]$MetaKeywords, [switch]$HideTitle, [switch]$HideTableOfContents ) $powershellCommandName = [System.IO.Path]::GetFileNameWithoutExtension($markdownFile.Name) # prepare front matter $newFrontMatter = [System.Collections.ArrayList]::new() $newFrontMatter.Add("---") | Out-Null $newFrontMatter.Add("id: $($powershellCommandName)") | Out-Null $newFrontMatter.Add("title: $($powershellCommandName)") | Out-Null if ($MetaDescription) { $description = [regex]::replace($MetaDescription, '%1', $powershellCommandName) $newFrontMatter.Add("description: $($description)") | Out-Null } if ($MetaKeywords) { $newFrontMatter.Add("keywords:") | Out-Null $MetaKeywords | ForEach-Object { $newFrontMatter.Add(" - $($_)") | Out-Null } } $newFrontMatter.Add("hide_title: $(if ($HideTitle) {"true"} else {"false"})") | Out-Null $newFrontMatter.Add("hide_table_of_contents: $(if ($HideTableOfContents) {"true"} else {"false"})") | Out-Null if ($EditUrl) { $newFrontMatter.Add("custom_edit_url: $($EditUrl)") | Out-Null } $newFrontMatter.Add("---") | Out-Null # replace front matter $content = (Get-Content -Path $MarkdownFile.FullName -Raw).TrimEnd() $regex = "(?sm)^(---)(.+)^(---).$\n" $newContent = $content -replace $regex, ($newFrontMatter | Out-String) # replace file (UTF-8 without BOM) $fileEncoding = New-Object System.Text.UTF8Encoding $False [System.IO.File]::WriteAllLines($markdownFile.FullName, $newContent, $fileEncoding) } #EndRegion '.\Private\SetMarkdownFrontMatter.ps1' 56 #Region '.\Private\UpdateMarkdownBackticks.ps1' 0 function UpdateMarkdownBackticks() { <# .SYNOPSIS Replaces platyPS-produced "escaped backticks" with normal backticks so markdown gets rendered as expected. #> param( [Parameter(Mandatory = $True)][System.IO.FileSystemInfo]$MarkdownFile ) $content = (Get-Content -Path $MarkdownFile.FullName -Raw).TrimEnd() $regex = '\\`' $newContent = [regex]::replace($content, $regex, '`') # replace file (UTF-8 without BOM) $fileEncoding = New-Object System.Text.UTF8Encoding $False [System.IO.File]::WriteAllLines($markdownFile.FullName, $newContent, $fileEncoding) } #EndRegion '.\Private\UpdateMarkdownBackticks.ps1' 19 #Region '.\Private\UpdateMarkdownCodeBlocks.ps1' 0 function UpdateMarkdownCodeBlocks() { <# .SYNOPSIS Add `powershell` syntax highlighting to generated code blocks. .NOTES 1. unfortunately we need to do this because PlatyPS does not add the language (design choice) 2. @todo change regex so it will match on \n as well (now only works on CRLF files) #> param( [Parameter(Mandatory = $True)][System.IO.FileSystemInfo]$MarkdownFile ) $content = (Get-Content -Path $MarkdownFile.FullName -Raw).TrimEnd() # this regex replaces all code blocks without a language (test on https://regex101.com using /$regex/g) $regex = '(```)\r((?:(?!```)[\s\S])+)(```)\r' $newContent = [regex]::replace($content, $regex, '```powershell$2```') # replace file (UTF-8 without BOM) $fileEncoding = New-Object System.Text.UTF8Encoding $False [System.IO.File]::WriteAllLines($markdownFile.FullName, $newContent, $fileEncoding) } #EndRegion '.\Private\UpdateMarkdownCodeBlocks.ps1' 24 #Region '.\Public\New-DocusaurusHelp.ps1' 0 function New-DocusaurusHelp() { <# .SYNOPSIS Generates Get-Help documentation in Docusaurus compatible `.mdx` format. .DESCRIPTION The `New-DocusaurusHelp` cmdlet generates Get-Help documentation in Docusaurus compatible format by creating an `.mdx` file for each command exported by the module, enriched with command-specific front matter variables. Also creates a `sidebar.js` file for simplified integration into the Docusaurus sidebar menu. .OUTPUTS System.Object .EXAMPLE New-DocusaurusHelp -Module Alt3.Docusaurus.Powershell -EditUrl "https://github.com/alt3/Docusaurus.Powershell/edit/master/source/Public" .PARAMETER Module Specifies the module this cmdlet will generate Docusaurus documentation for. You may specify a module name, a `.psd1` file or a `.psm1` file. .PARAMETER OutputFolder Specifies the folder where the Docusaurus sidebar subfolder will be created. Optional, defaults to `docusaurus/docs`, case sensitive. .PARAMETER Sidebar Specifies the subfolder where the Get-Help `.mdx` files for the module will be created. Optional, defaults to `commands`, case sensitive. .PARAMETER Exclude Optional array with command names to exclude. .PARAMETER MetaDescription Optional string that will be inserted into Docusaurus front matter to be used as html meta tag 'description'. If placeholder `%1` is detected in the string, it will be replaced by the command name. .PARAMETER MetaKeywords Optional array of keywords inserted into Docusaurus front matter to be used as html meta tag `keywords`. .PARAMETER EditUrl Specifies the URL prefixed to all Docusaurus `custom_edit_url` front matter variables. Optional, defaults to `null`. .PARAMETER HideTitle Sets the Docusaurus front matter variable `hide_title`. Optional, defaults to `false`. .PARAMETER HideTableOfContents Sets the Docusaurus front matter variable `hide_table_of_contents`. Optional, defaults to `false`. .PARAMETER Monolithic Use this optional argument if the Powershell module source is monolithic. Will point all `custom_edit_url` front matter variables to the `.psm1` file. .NOTES Please note that Docusaurus v2 is an early and alpha version, just like this module. .LINK https://v2.docusaurus.io/ .LINK https://github.com/PowerShell/platyPS #> [cmdletbinding()] param( [Parameter(Mandatory = $True)][string]$Module, [Parameter(Mandatory = $False)][string]$OutputFolder = "docusaurus/docs", [Parameter(Mandatory = $False)][string]$Sidebar = "commands", [Parameter(Mandatory = $False)][array]$Exclude = @(), [Parameter(Mandatory = $False)][string]$MetaDescription, [Parameter(Mandatory = $False)][array]$MetaKeywords = @(), [Parameter(Mandatory = $False)][string]$EditUrl, [switch]$HideTitle, [switch]$HideTableOfContents, [switch]$Monolithic ) # make sure the passed module is valid if (Test-Path($Module)) { Import-Module $Module -Force -Global $Module = [System.IO.Path]::GetFileNameWithoutExtension($Module) } if (-Not(Get-Module -Name $Module)) { $Module = $Module throw "New-DocusaurusHelp: Specified module '$Module' is not loaded" } # markdown for the module will be isolated in a subfolder $markdownFolder = Join-Path -Path $OutputFolder -ChildPath $Sidebar # generate PlatyPs markdown files New-MarkdownHelp -Module $Module -OutputFolder $markdownFolder -Force | Out-Null # remove excluded files $Exclude | ForEach-Object { $excludedFile = Join-Path -Path $markdownFolder -ChildPath "$($_).md" if (Test-Path -Path $excludedFile) { Remove-Item -Path $excludedFile } } # process remaining files $markdownFiles = Get-ChildItem -Path $markdownFolder -Filter *.md # update generated markdown file(s) to make them Docusaurus compatible ForEach ($markdownFile in $markdownFiles) { $customEditUrl = GetCustomEditUrl -Module $Module -MarkdownFile $markdownFile -EditUrl $EditUrl -Monolithic:$Monolithic $frontMatterArgs = @{ MarkdownFile = $markdownFile MetaDescription = $metaDescription CustomEditUrl = $customEditUrl MetaKeywords = $metaKeywords HideTitle = $HideTitle HideTableOfContents = $HideTableOfContents } SetMarkdownFrontMatter @frontmatterArgs RemoveMarkdownHeaderOne -MarkdownFile $markdownFile UpdateMarkdownCodeBlocks -MarkdownFile $markdownFile UpdateMarkdownBackticks -MarkdownFile $markdownFile # rename to .mdx $mdxFilePath = GetMdxFilePath -MarkdownFile $markdownFile Move-Item -Path $markdownFile.FullName -Destination $mdxFilePath -Force | Out-Null # output .mdx item so end-user can post-process files as they see fit Get-Item $mdxFilePath } # generate the `.js` file used for the docusaurus sidebar NewSidebarIncludeFile -MarkdownFiles $markdownFiles -OutputFolder $markdownFolder -Sidebar $Sidebar } #EndRegion '.\Public\New-DocusaurusHelp.ps1' 144 |