diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c7f186..55c1069 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,9 +5,40 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Removed + +- Removed `build.psd1` as it is no longer required to build the project. + ### Added - Added a devcontainer for development. +- Added private function `ConvertTo-WikiSidebarLinkName` that converts a + name to a format suitable for use as a Wiki sidebar link. +- New tasks: + - `Prepare_Markdown_FileNames_For_GitHub_Publish` - This task will prepare + the markdown file names for publishing to the GitHub Wiki by replacing + hyphens with spaces and converting Unicode hyphens to standard hyphens. + It can be controlled by parameter `ReplaceHyphen` in the task, which + defaults to `$true`. + - `Clean_WikiContent_For_GitHub_Publish` - This task will remove the top + level header from any markdown file where the top level header equals the + filename (converting Unicode hyphen to ASCII hyphen before comparison). + It can be controlled by parameter `RemoveTopLevelHeader` in the task, which + defaults to `$true`. + +### Changed + +- `New-GitHubWikiSidebar` + - Replaces ASCII hyphens for the Wiki sidebar. + - Replaces Unicode hyphens with standard hyphens for the Wiki sidebar. +- Task `Generate_Wiki_Content` + - Now calls `Prepare_Markdown_FileNames_For_GitHub_Publish` after the + markdown files and external help file for command help has been generated. + - Now calls `Clean_WikiContent_For_GitHub_Publish` as the last step to + remove the top level header from any markdown file where the top level + header equals the filename. +- Task `Generate_Markdown_For_Public_Commands` + - Verbose output of the markdown files that was created. ### Fixed diff --git a/README.md b/README.md index 970021e..6f1dcd3 100644 --- a/README.md +++ b/README.md @@ -136,6 +136,33 @@ BuildWorkflow: - Publish_GitHub_Wiki_Content ``` +### `Clean_WikiContent_For_GitHub_Publish` + +>[!IMPORTANT] +>This task does not work in Windows PowerShell due to it not supporting +>unicode in filenames. + +This build task will clean the markdown files for publishing to the GitHub Wiki. +It can be controlled by parameter `RemoveTopLevelHeader` in the task, which +defaults to `$true`. + +Below is an example how the build task can be used when a repository is +based on the [Sampler](https://github.com/gaelcolas/Sampler) project. + +```yaml +BuildWorkflow: + '.': + - build + + build: + - Clean + - Build_Module_ModuleBuilder + - Build_NestedModules_ModuleBuilder + - Create_changelog_release_output + - Generate_Markdown_For_Public_Commands + - Clean_WikiContent_For_GitHub_Publish +``` + ### `Copy_Source_Wiki_Folder` This build task will copy the content of the wiki source folder if it exist @@ -345,9 +372,11 @@ This is a metatask that runs the task (in order): - `Create_Wiki_Output_Folder` - `Generate_Markdown_For_Public_Commands` - `Generate_External_Help_File_For_Public_Commands` +- `Prepare_Markdown_FileNames_For_GitHub_Publish` - `Clean_Markdown_Of_Public_Commands` - `Generate_Markdown_For_DSC_Resources` - `Copy_Source_Wiki_Folder` +- `Clean_WikiContent_For_GitHub_Publish` Below is an example how the build task can be used when a repository is based on the [Sampler](https://github.com/gaelcolas/Sampler) project. @@ -430,6 +459,33 @@ BuildWorkflow: - Publish_GitHub_Wiki_Content ``` +### `Prepare_Markdown_FileNames_For_GitHub_Publish` + +>[!IMPORTANT] +>This task does not work in Windows PowerShell due to it not supporting +>unicode in filenames. + +This build task will replace the hyphen in the markdown filenames with the +unicode non-breaking hyphen. It can be controlled by parameter +`ReplaceHyphen` in the task, which defaults to `$true`. + +Below is an example how the build task can be used when a repository is +based on the [Sampler](https://github.com/gaelcolas/Sampler) project. + +```yaml +BuildWorkflow: + '.': + - build + + build: + - Clean + - Build_Module_ModuleBuilder + - Build_NestedModules_ModuleBuilder + - Create_changelog_release_output + - Generate_Markdown_For_Public_Commands + - Prepare_Markdown_FileNames_For_GitHub_Publish +``` + ### `Publish_GitHub_Wiki_Content` This build task runs the command `Publish-WikiContent`. The task will only diff --git a/source/Private/ConvertTo-WikiSidebarLinkName.ps1 b/source/Private/ConvertTo-WikiSidebarLinkName.ps1 new file mode 100644 index 0000000..b5ac28e --- /dev/null +++ b/source/Private/ConvertTo-WikiSidebarLinkName.ps1 @@ -0,0 +1,61 @@ +<# + .SYNOPSIS + Converts a name to a format suitable for use as a Wiki sidebar link. + + .DESCRIPTION + The ConvertTo-WikiSidebarLinkName function takes a string input and converts + it to a format that is suitable for use as a link name in a Wiki sidebar. It + replaces hyphens with spaces and converts Unicode hyphens to standard hyphens. + + .PARAMETER Name + The string to be converted. This parameter is mandatory and can be passed via + the pipeline. + + .EXAMPLE + PS C:\> ConvertTo-WikiSidebarLinkName -Name "My-Page-Name" + + Returns: "My Page Name" + + .EXAMPLE + PS C:\> ('Unicode{0}Hyphen' -f [System.Char]::ConvertFromUtf32(0x2011)) | ConvertTo-WikiSidebarLinkName + + Returns: "Unicode-Hyphen" + + .INPUTS + System.String + + .OUTPUTS + System.String + + .NOTES + This function is used internally by the New-GitHubWikiSidebar function to + format link names in the generated sidebar. +#> +function ConvertTo-WikiSidebarLinkName +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 0)] + [System.String] + $Name + ) + + process + { + if ($PSVersionTable.PSVersion -ge '6.0') + { + # Replace hyphens with spaces + $convertedName = $Name -replace '-', ' ' + + # Replace Unicode hyphen (U+2010) with a standard hyphen + $convertedName = $convertedName -replace [System.Char]::ConvertFromUtf32(0x2011), '-' + } + else + { + $convertedName = $Name + } + + return $convertedName + } +} diff --git a/source/Private/Task.Clean_WikiContent_For_GitHub_Publish.build.ps1 b/source/Private/Task.Clean_WikiContent_For_GitHub_Publish.build.ps1 new file mode 100644 index 0000000..9046694 --- /dev/null +++ b/source/Private/Task.Clean_WikiContent_For_GitHub_Publish.build.ps1 @@ -0,0 +1,16 @@ +<# + .SYNOPSIS + This is the alias to the build task Clean_WikiContent_For_GitHub_Publish + script file. + + .DESCRIPTION + This makes available the alias 'Task.Clean_WikiContent_For_GitHub_Publish' + that is exported in the module manifest so that the build task can be + correctly imported using for example Invoke-Build. + + .NOTES + This is using the pattern lined out in the Invoke-Build repository + https://github.com/nightroman/Invoke-Build/tree/master/Tasks/Import. +#> + +Set-Alias -Name 'Task.Clean_WikiContent_For_GitHub_Publish' -Value "$PSScriptRoot/tasks/Clean_WikiContent_For_GitHub_Publish.build.ps1" diff --git a/source/Private/Task.Prepare_Markdown_Filenames_For_GitHub_Publish.build.ps1 b/source/Private/Task.Prepare_Markdown_Filenames_For_GitHub_Publish.build.ps1 new file mode 100644 index 0000000..9579ce6 --- /dev/null +++ b/source/Private/Task.Prepare_Markdown_Filenames_For_GitHub_Publish.build.ps1 @@ -0,0 +1,16 @@ +<# + .SYNOPSIS + This is the alias to the build task Prepare_Markdown_Filenames_For_GitHub_Publish + script file. + + .DESCRIPTION + This makes available the alias 'Task.Prepare_Markdown_Filenames_For_GitHub_Publish' + that is exported in the module manifest so that the build task can be correctly + imported using for example Invoke-Build. + + .NOTES + This is using the pattern lined out in the Invoke-Build repository + https://github.com/nightroman/Invoke-Build/tree/master/Tasks/Import. +#> + +Set-Alias -Name 'Task.Prepare_Markdown_Filenames_For_GitHub_Publish' -Value "$PSScriptRoot/tasks/Prepare_Markdown_Filenames_For_GitHub_Publish.build.ps1" diff --git a/source/Public/New-GitHubWikiSidebar.ps1 b/source/Public/New-GitHubWikiSidebar.ps1 index 31d23b2..f751f06 100644 --- a/source/Public/New-GitHubWikiSidebar.ps1 +++ b/source/Public/New-GitHubWikiSidebar.ps1 @@ -169,7 +169,9 @@ Get-MarkdownMetadata -Path $($file.FullName) -ErrorAction 'Stop' foreach ($link in $sortedListItem) { - $null = $output.AppendLine('- [' + $link + '](' + $link + ')') + $linkName = ConvertTo-WikiSidebarLinkName -Name $link + + $null = $output.AppendLine('- [' + $linkName + '](' + $link + ')') } $null = $output.AppendLine() @@ -188,7 +190,9 @@ Get-MarkdownMetadata -Path $($file.FullName) -ErrorAction 'Stop' foreach ($link in $sidebarCategories.$category | Sort-Object) { - $null = $output.AppendLine('- [' + $link + '](' + $link + ')') + $linkName = ConvertTo-WikiSidebarLinkName -Name $link + + $null = $output.AppendLine('- [' + $linkName + '](' + $link + ')') } $null = $output.AppendLine() diff --git a/source/build.psd1 b/source/build.psd1 deleted file mode 100644 index 7093037..0000000 --- a/source/build.psd1 +++ /dev/null @@ -1,6 +0,0 @@ -@{ - Path = 'DscResource.DocGenerator.psd1' #or build breaks on Linux -} -# Waiting for ModuleBuilder to do away with this file -# when all parameters are provided to the function - diff --git a/source/tasks/Clean_WikiContent_For_GitHub_Publish.build.ps1 b/source/tasks/Clean_WikiContent_For_GitHub_Publish.build.ps1 new file mode 100644 index 0000000..ddd6cc4 --- /dev/null +++ b/source/tasks/Clean_WikiContent_For_GitHub_Publish.build.ps1 @@ -0,0 +1,142 @@ +<# + .SYNOPSIS + This is a build task that modifies the wiki content to enhance the content + for use in GitHub repository Wikis. + + .PARAMETER ProjectPath + The root path to the project. Defaults to $BuildRoot. + + .PARAMETER OutputDirectory + The base directory of all output. Defaults to folder 'output' relative to + the $BuildRoot. + + .PARAMETER BuiltModuleSubdirectory + Sub folder where you want to build the Module to (instead of $OutputDirectory/$ModuleName). + This is especially useful when you want to build DSC Resources, but you don't want the + `Get-DscResource` command to find several instances of the same DSC Resources because + of the overlapping $Env:PSmodulePath (`$buildRoot/output` for the built module and `$buildRoot/output/RequiredModules`). + + In most cases I would recommend against setting $BuiltModuleSubdirectory. + + .PARAMETER VersionedOutputDirectory + Whether the Module is built with its versioned Subdirectory, as you would see it on a System. + For instance, if VersionedOutputDirectory is $true, the built module's ModuleBase would be: `output/MyModuleName/2.0.1/` + + .PARAMETER ProjectName + The project name. Defaults to the empty string. + + .PARAMETER SourcePath + The path to the source folder name. Defaults to the empty string. + The task does not use this parameter, see the notes below. + + .PARAMETER DocOutputFolder + The path to the where the markdown documentation is written. Defaults to the + folder `./output/WikiContent`. + + .PARAMETER BuildInfo + The build info object from ModuleBuilder. Defaults to an empty hashtable. + + .NOTES + This is a build task that is primarily meant to be run by Invoke-Build but + wrapped by the Sampler project's build.ps1 (https://github.com/gaelcolas/Sampler). + + Parameter SourcePath is intentionally added to the task even if it is not used, + otherwise the tests fails. Most likely because the script Set-SamplerTaskVariable + expects the variable to always be available. +#> +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('DscResource.AnalyzerRules/Measure-ParameterBlockParameterAttribute', '', Justification = 'For boolean values when using (property $true $false) fails in conversion between string and boolean when environment variable is used if set as advanced parameter ([Parameter()])')] +param +( + [Parameter()] + [System.String] + $ProjectPath = (property ProjectPath $BuildRoot), + + [Parameter()] + [System.String] + $OutputDirectory = (property OutputDirectory (Join-Path $BuildRoot 'output')), + + [Parameter()] + [System.String] + $BuiltModuleSubdirectory = (property BuiltModuleSubdirectory ''), + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $VersionedOutputDirectory = (property VersionedOutputDirectory $true), + + [Parameter()] + [System.String] + $ProjectName = (property ProjectName ''), + + [Parameter()] + [System.String] + $SourcePath = (property SourcePath ''), + + [Parameter()] + [System.String] + $DocOutputFolder = (property DocOutputFolder 'WikiContent'), + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $RemoveTopLevelHeader = (property RemoveTopLevelHeader $true), + + [Parameter()] + [System.Collections.Hashtable] + $BuildInfo = (property BuildInfo @{ }) +) + +# Synopsis: Modifies the wiki content to enhance the content for use in GitHub repository Wikis. +Task Clean_WikiContent_For_GitHub_Publish { + if ($PSVersionTable.PSVersion -lt '6.0') + { + Write-Warning -Message 'This task is not supported in Windows PowerShell.' + + return + } + + # Get the values for task variables, see https://github.com/gaelcolas/Sampler#task-variables. + . Set-SamplerTaskVariable + + $DocOutputFolder = Get-SamplerAbsolutePath -Path $DocOutputFolder -RelativeTo $OutputDirectory + + "`tDocs output folder path = '$DocOutputFolder'" + '' + + if ($RemoveTopLevelHeader) + { + $markdownFiles = Get-ChildItem -Path $DocOutputFolder -Filter '*.md' + + Write-Build -Color 'Magenta' -Text 'Removing top level header from markdown files if it is the same as the filename.' + + $markdownFiles | + ForEach-Object -Process { + $content = Get-Content -Path $_.FullName -Raw + + $hasTopHeader = $content -match '(?m)^#\s+([^\r\n]+)' + + $baseNameWithoutNonBreakingHyphen = $_.BaseName -replace [System.Char]::ConvertFromUtf32(0x2011), '-' + + if ($hasTopHeader -and $Matches[1] -eq $baseNameWithoutNonBreakingHyphen) + { + Write-Build -Color DarkGray -Text ('Top level header is the same as the filename. Removing top level header from: {0}' -f $_.Name) + + <# + Remove only the top level header (# Header) and any empty lines + following it. The regex should only target the first header found, + without affecting later top level headers. + #> + $content = $content -replace '(?m)^#\s+(.*)\s*', '' + + # Save the updated content back to the file + Set-Content -Path $_.FullName -Value $content + } + elseif ($hasTopHeader) + { + Write-Build -Color DarkGray -Text ('Top level header is different from the filename. Skipping: {0}' -f $_.Name) + } + else + { + Write-Build -Color DarkGray -Text ('No top level header found in: {0}' -f $_.Name) + } + } + } +} diff --git a/source/tasks/Generate_Markdown_For_Public_Commands.build.ps1 b/source/tasks/Generate_Markdown_For_Public_Commands.build.ps1 index e08fede..0060128 100644 --- a/source/tasks/Generate_Markdown_For_Public_Commands.build.ps1 +++ b/source/tasks/Generate_Markdown_For_Public_Commands.build.ps1 @@ -169,7 +169,7 @@ Import-Module -name '$DependentModule' $generateMarkdownScript += @" `n# Import the module that help is generate for -`$importModule = Import-Module -Name '$ProjectName' -Passthru -ErrorAction 'Stop' +`$importModule = Import-Module -Name '$ProjectName' -PassThru -ErrorAction 'Stop' if (-not `$importModule) { @@ -212,7 +212,13 @@ New-MarkdownHelp @newMarkdownHelpParams The scriptblock is run in a separate process to avoid conflicts with other modules that are loaded in the current process. #> - & $pwshPath -Command $generateMarkdownScriptBlock -ExecutionPolicy 'ByPass' -NoProfile + $markdownFiles = & $pwshPath -Command $generateMarkdownScriptBlock -ExecutionPolicy 'ByPass' -NoProfile + + Write-Build -Color DarkGray -Text "Generated markdown files:" + + $markdownFiles | ForEach-Object -Process { + Write-Build -Color DarkGray -Text ("`t{0}" -f $_.FullName) + } if (-not $?) { @@ -220,6 +226,6 @@ New-MarkdownHelp @newMarkdownHelpParams } else { - Write-Build -Color 'Green' -Text 'Markdown for command documentation created for module '$ProjectName'.' + Write-Build -Color Green -Text 'Markdown for command documentation created for module '$ProjectName'.' } } diff --git a/source/tasks/Generate_Wiki_Content.build.ps1 b/source/tasks/Generate_Wiki_Content.build.ps1 index e6cb24c..237fa2f 100644 --- a/source/tasks/Generate_Wiki_Content.build.ps1 +++ b/source/tasks/Generate_Wiki_Content.build.ps1 @@ -84,4 +84,4 @@ param $BuildInfo = (property BuildInfo @{ }) ) -Task Generate_Wiki_Content Create_Wiki_Output_Folder, Generate_Markdown_For_Public_Commands, Generate_External_Help_File_For_Public_Commands, Clean_Markdown_Of_Public_Commands, Generate_Markdown_For_DSC_Resources, Copy_Source_Wiki_Folder +Task Generate_Wiki_Content Create_Wiki_Output_Folder, Generate_Markdown_For_Public_Commands, Generate_External_Help_File_For_Public_Commands, Prepare_Markdown_FileNames_For_GitHub_Publish, Clean_Markdown_Of_Public_Commands, Generate_Markdown_For_DSC_Resources, Copy_Source_Wiki_Folder, Clean_WikiContent_For_GitHub_Publish diff --git a/source/tasks/Prepare_Markdown_Filenames_For_GitHub_Publish.build.ps1 b/source/tasks/Prepare_Markdown_Filenames_For_GitHub_Publish.build.ps1 new file mode 100644 index 0000000..733375e --- /dev/null +++ b/source/tasks/Prepare_Markdown_Filenames_For_GitHub_Publish.build.ps1 @@ -0,0 +1,130 @@ +<# + .SYNOPSIS + This is a build task that modifies the markdown filenames to enhance the content + for use in GitHub repository Wikis. + + .PARAMETER ProjectPath + The root path to the project. Defaults to $BuildRoot. + + .PARAMETER OutputDirectory + The base directory of all output. Defaults to folder 'output' relative to + the $BuildRoot. + + .PARAMETER BuiltModuleSubdirectory + Sub folder where you want to build the Module to (instead of $OutputDirectory/$ModuleName). + This is especially useful when you want to build DSC Resources, but you don't want the + `Get-DscResource` command to find several instances of the same DSC Resources because + of the overlapping $Env:PSmodulePath (`$buildRoot/output` for the built module and `$buildRoot/output/RequiredModules`). + + In most cases I would recommend against setting $BuiltModuleSubdirectory. + + .PARAMETER VersionedOutputDirectory + Whether the Module is built with its versioned Subdirectory, as you would see it on a System. + For instance, if VersionedOutputDirectory is $true, the built module's ModuleBase would be: `output/MyModuleName/2.0.1/` + + .PARAMETER ProjectName + The project name. Defaults to the empty string. + + .PARAMETER SourcePath + The path to the source folder name. Defaults to the empty string. + The task does not use this parameter, see the notes below. + + .PARAMETER DocOutputFolder + The path to the where the markdown documentation is written. Defaults to the + folder `./output/WikiContent`. + + .PARAMETER ReplaceHyphen + Specifies if hyphens in the markdown filenames should be replaced with + non-breaking hyphens. Defaults to `$true`. + + .PARAMETER BuildInfo + The build info object from ModuleBuilder. Defaults to an empty hashtable. + + .NOTES + This is a build task that is primarily meant to be run by Invoke-Build but + wrapped by the Sampler project's build.ps1 (https://github.com/gaelcolas/Sampler). + + Parameter SourcePath is intentionally added to the task even if it is not used, + otherwise the tests fails. Most likely because the script Set-SamplerTaskVariable + expects the variable to always be available. +#> +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('DscResource.AnalyzerRules/Measure-ParameterBlockParameterAttribute', '', Justification = 'For boolean values when using (property $true $false) fails in conversion between string and boolean when environment variable is used if set as advanced parameter ([Parameter()])')] +param +( + [Parameter()] + [System.String] + $ProjectPath = (property ProjectPath $BuildRoot), + + [Parameter()] + [System.String] + $OutputDirectory = (property OutputDirectory (Join-Path $BuildRoot 'output')), + + [Parameter()] + [System.String] + $BuiltModuleSubdirectory = (property BuiltModuleSubdirectory ''), + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $VersionedOutputDirectory = (property VersionedOutputDirectory $true), + + [Parameter()] + [System.String] + $ProjectName = (property ProjectName ''), + + [Parameter()] + [System.String] + $SourcePath = (property SourcePath ''), + + [Parameter()] + [System.String] + $DocOutputFolder = (property DocOutputFolder 'WikiContent'), + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ReplaceHyphen = (property ReplaceHyphen $true), + + [Parameter()] + [System.Collections.Hashtable] + $BuildInfo = (property BuildInfo @{ }) +) + +# Synopsis: Modifies the markdown filenames to enhance the content for use in GitHub repository Wikis. +Task Prepare_Markdown_FileNames_For_GitHub_Publish { + if ($PSVersionTable.PSVersion -lt '6.0') + { + Write-Warning -Message 'This task is not supported in Windows PowerShell.' + + return + } + + # Get the values for task variables, see https://github.com/gaelcolas/Sampler#task-variables. + . Set-SamplerTaskVariable + + $DocOutputFolder = Get-SamplerAbsolutePath -Path $DocOutputFolder -RelativeTo $OutputDirectory + + "`tDocs output folder path = '$DocOutputFolder'" + "`tReplace Hyphen = '$ReplaceHyphen'" + '' + + if ($ReplaceHyphen) + { + $markdownFiles = Get-ChildItem -Path $DocOutputFolder -Filter '*.md' + + Write-Build -Color 'Magenta' -Text 'Replacing hyphens with non-breaking hyphens in markdown filenames.' + + # Replace the hyphen in the filename with the unicode non-breaking hyphen. + $markdownFiles | + Where-Object -Property 'Name' -Match '-' | + ForEach-Object -Process { + $newName = $_.Name -replace '-', [System.Char]::ConvertFromUtf32(0x2011) + + Write-Build -Color DarkGray -Text ('Renaming: {0} -> {1}' -f $_.Name, $newName) + + Rename-Item -Path $_.FullName -NewName $newName -Force + } + } + else + { + Write-Build -Color 'Yellow' -Text 'Skipping renaming hyphens in markdown filenames.' + } +} diff --git a/tests/unit/private/ConvertTo-WikiSidebarLinkName.Tests.ps1 b/tests/unit/private/ConvertTo-WikiSidebarLinkName.Tests.ps1 new file mode 100644 index 0000000..be4d68b --- /dev/null +++ b/tests/unit/private/ConvertTo-WikiSidebarLinkName.Tests.ps1 @@ -0,0 +1,101 @@ +#region HEADER +$script:projectPath = "$PSScriptRoot\..\..\.." | Convert-Path +$script:projectName = (Get-ChildItem -Path "$script:projectPath\*\*.psd1" | Where-Object -FilterScript { + ($_.Directory.Name -match 'source|src' -or $_.Directory.Name -eq $_.BaseName) -and + $(try + { + Test-ModuleManifest -Path $_.FullName -ErrorAction Stop + } + catch + { + $false + }) + }).BaseName + +$script:moduleName = Get-Module -Name $script:projectName -ListAvailable | Select-Object -First 1 +Remove-Module -Name $script:moduleName -Force -ErrorAction 'SilentlyContinue' + +Import-Module $script:moduleName -Force -ErrorAction 'Stop' +#endregion HEADER + +InModuleScope $script:moduleName { + Describe 'ConvertTo-WikiSidebarLinkName' { + Context 'When converting a simple hyphenated name' { + BeforeAll { + if ($PSVersionTable.PSVersion -ge '6.0') + { + $mockExpectedResult = 'My Page Name' + } + else + { + $mockExpectedResult = 'My-Page-Name' + } + } + + It 'Should replace hyphens with spaces' { + $result = ConvertTo-WikiSidebarLinkName -Name 'My-Page-Name' + $result | Should -Be $mockExpectedResult + } + } + + Context 'When converting a name with Unicode hyphens' { + BeforeAll { + if ($PSVersionTable.PSVersion -ge '6.0') + { + $mockExpectedResult = 'Unicode-Hyphen' + } + else + { + $mockExpectedResult = 'Unicode{0}Hyphen' -f [System.Char]::ConvertFromUtf32(0x2011) + } + } + + It 'Should replace Unicode hyphens with standard hyphens' { + $result = ConvertTo-WikiSidebarLinkName -Name ('Unicode{0}Hyphen' -f [System.Char]::ConvertFromUtf32(0x2011)) # Note: The hyphen here is a Unicode hyphen (U+2010) + $result | Should -Be $mockExpectedResult + } + } + + Context 'When the input is piped' { + BeforeAll { + if ($PSVersionTable.PSVersion -ge '6.0') + { + $mockExpectedResult = 'Piped Input' + } + else + { + $mockExpectedResult = 'Piped-Input' + } + } + + It 'Should process the piped input correctly' { + 'Piped-Input' | ConvertTo-WikiSidebarLinkName | Should -Be $mockExpectedResult + } + } + + Context 'When the input contains multiple types of hyphens' { + BeforeAll { + if ($PSVersionTable.PSVersion -ge '6.0') + { + $mockExpectedResult = 'Multiple-Hyphens Here' + } + else + { + $mockExpectedResult = 'Multiple{0}Hyphens-Here' -f [System.Char]::ConvertFromUtf32(0x2011) + } + } + + It 'Should replace all hyphens appropriately' { + $result = ConvertTo-WikiSidebarLinkName -Name ('Multiple{0}Hyphens-Here' -f [System.Char]::ConvertFromUtf32(0x2011)) # Contains both Unicode and standard hyphens + $result | Should -Be $mockExpectedResult + } + } + + Context 'When the input does not contain hyphens' { + It 'Should return the input unchanged' { + $result = ConvertTo-WikiSidebarLinkName -Name 'NoHyphensHere' + $result | Should -Be 'NoHyphensHere' + } + } + } +} diff --git a/tests/unit/public/New-GitHubWikiSidebar.Tests.ps1 b/tests/unit/public/New-GitHubWikiSidebar.Tests.ps1 index f39c5a0..0dd0cef 100644 --- a/tests/unit/public/New-GitHubWikiSidebar.Tests.ps1 +++ b/tests/unit/public/New-GitHubWikiSidebar.Tests.ps1 @@ -20,6 +20,15 @@ Import-Module $script:moduleName -Force -ErrorAction 'Stop' Describe 'New-GitHubWikiSidebar' { BeforeAll { + if ($PSVersionTable.PSVersion -ge '6.0') + { + $mockHyphen = [System.Char]::ConvertFromUtf32(0x2011) + } + else + { + $mockHyphen = '-' + } + $documentationPath = "$($TestDrive.FullName)/WikiContent" $outputFilePath = $documentationPath | Join-Path -ChildPath 'CustomSidebar.md' @@ -41,7 +50,7 @@ Category: Help topics # RandomHelpTopic '@ - Set-Content -Path "$($TestDrive.FullName)/WikiContent/Get-Something.md" -Value @' + Set-Content -Path ("$($TestDrive.FullName)/WikiContent/Get{0}Something.md" -f $mockHyphen) -Value @' --- Type: Command Category: Commands @@ -75,7 +84,7 @@ Category: Resources ### Commands -- [Get-Something](Get-Something) +- [Get-Something](Get{0}Something) ### Help topics @@ -84,12 +93,14 @@ Category: Resources ### Resources - [MockResource](MockResource) -'@ -replace '\r?\n', "`r`n" +'@ + $script:mockWikiContentOutput = $script:mockWikiContentOutput -replace '\r?\n', "`r`n" + $script:mockWikiContentOutput = $script:mockWikiContentOutput -f $mockHyphen } + It 'Should not throw any exceptions and call Out-File with correct parameters' { { - # New-GitHubWikiSidebar -DocumentationPath $documentationPath -SidebarFileName 'CustomSidebar.md' -Force } | Should -Not -Throw diff --git a/tests/unit/tasks/Clean_WikiContent_For_GitHub_Publish.Tests.ps1 b/tests/unit/tasks/Clean_WikiContent_For_GitHub_Publish.Tests.ps1 new file mode 100644 index 0000000..5b7ee54 --- /dev/null +++ b/tests/unit/tasks/Clean_WikiContent_For_GitHub_Publish.Tests.ps1 @@ -0,0 +1,71 @@ +#region HEADER +$script:projectPath = "$PSScriptRoot\..\..\.." | Convert-Path +$script:projectName = (Get-ChildItem -Path "$script:projectPath\*\*.psd1" | Where-Object -FilterScript { + ($_.Directory.Name -match 'source|src' -or $_.Directory.Name -eq $_.BaseName) -and + $(try + { + Test-ModuleManifest -Path $_.FullName -ErrorAction Stop + } + catch + { + $false + }) + }).BaseName + +$script:moduleName = Get-Module -Name $script:projectName -ListAvailable | Select-Object -First 1 +Remove-Module -Name $script:moduleName -Force -ErrorAction 'SilentlyContinue' + +Import-Module $script:moduleName -Force -ErrorAction 'Stop' +#endregion HEADER + +Describe 'Clean_WikiContent_For_GitHub_Publish' { + BeforeAll { + Mock -Command Get-BuiltModuleVersion -MockWith { + return [PSCustomObject]@{ + Version = '1.0.0-preview1' + PreReleaseString = 'preview1' + ModuleVersion = '1.0.0' + } + } + + Mock -CommandName Get-SamplerBuiltModuleManifest + Mock -CommandName Get-SamplerBuiltModuleBase -MockWith { + return $TestDrive.FullName + } + + New-Item -Path "$($TestDrive.FullName)/WikiContent" -ItemType 'Directory' -Force | Out-Null + + Set-Content -Path "$($TestDrive.FullName)/WikiContent/Get-Something.md" -Value 'Mock markdown file 1' + + Set-Content -Path "$($TestDrive.FullName)/WikiContent/home.md" -Value 'Mock markdown file 1' + } + + It 'Should export the build script alias' { + $buildTaskName = 'Clean_WikiContent_For_GitHub_Publish' + $buildScriptAliasName = 'Task.{0}' -f $buildTaskName + + $script:buildScript = Get-Command -Name $buildScriptAliasName -Module $script:projectName + + $script:buildScript.Name | Should -Be $buildScriptAliasName + $script:buildScript.ReferencedCommand | Should -Be ('{0}.build.ps1' -f $buildTaskName) + } + + It 'Should reference an existing build script' { + Test-Path -Path $script:buildScript.Definition | Should -BeTrue + } +5 + It 'Should run the build task without throwing' { + { + $taskParameters = @{ + ProjectName = 'MockModule' + ProjectPath = $TestDrive.FullName + OutputDirectory = $TestDrive.FullName + # Using the markdown created when the project was built. + DocOutputFolder = $TestDrive.FullName | Join-Path -ChildPath 'WikiContent' + SourcePath = "$($TestDrive.FullName)/source" + } + + Invoke-Build -Task $buildTaskName -File $script:buildScript.Definition @taskParameters + } | Should -Not -Throw + } +} diff --git a/tests/unit/tasks/Prepare_Markdown_Filenames_For_GitHub_Publish.Tests.ps1 b/tests/unit/tasks/Prepare_Markdown_Filenames_For_GitHub_Publish.Tests.ps1 new file mode 100644 index 0000000..62ac069 --- /dev/null +++ b/tests/unit/tasks/Prepare_Markdown_Filenames_For_GitHub_Publish.Tests.ps1 @@ -0,0 +1,71 @@ +#region HEADER +$script:projectPath = "$PSScriptRoot\..\..\.." | Convert-Path +$script:projectName = (Get-ChildItem -Path "$script:projectPath\*\*.psd1" | Where-Object -FilterScript { + ($_.Directory.Name -match 'source|src' -or $_.Directory.Name -eq $_.BaseName) -and + $(try + { + Test-ModuleManifest -Path $_.FullName -ErrorAction Stop + } + catch + { + $false + }) + }).BaseName + +$script:moduleName = Get-Module -Name $script:projectName -ListAvailable | Select-Object -First 1 +Remove-Module -Name $script:moduleName -Force -ErrorAction 'SilentlyContinue' + +Import-Module $script:moduleName -Force -ErrorAction 'Stop' +#endregion HEADER + +Describe 'Prepare_Markdown_Filenames_For_GitHub_Publish' { + BeforeAll { + Mock -Command Get-BuiltModuleVersion -MockWith { + return [PSCustomObject]@{ + Version = '1.0.0-preview1' + PreReleaseString = 'preview1' + ModuleVersion = '1.0.0' + } + } + + Mock -CommandName Get-SamplerBuiltModuleManifest + Mock -CommandName Get-SamplerBuiltModuleBase -MockWith { + return $TestDrive.FullName + } + + New-Item -Path "$($TestDrive.FullName)/WikiContent" -ItemType 'Directory' -Force | Out-Null + + Set-Content -Path "$($TestDrive.FullName)/WikiContent/Get-Something.md" -Value 'Mock markdown file 1' + + Set-Content -Path "$($TestDrive.FullName)/WikiContent/home.md" -Value 'Mock markdown file 1' + } + + It 'Should export the build script alias' { + $buildTaskName = 'Prepare_Markdown_Filenames_For_GitHub_Publish' + $buildScriptAliasName = 'Task.{0}' -f $buildTaskName + + $script:buildScript = Get-Command -Name $buildScriptAliasName -Module $script:projectName + + $script:buildScript.Name | Should -Be $buildScriptAliasName + $script:buildScript.ReferencedCommand | Should -Be ('{0}.build.ps1' -f $buildTaskName) + } + + It 'Should reference an existing build script' { + Test-Path -Path $script:buildScript.Definition | Should -BeTrue + } +5 + It 'Should run the build task without throwing' { + { + $taskParameters = @{ + ProjectName = 'MockModule' + ProjectPath = $TestDrive.FullName + OutputDirectory = $TestDrive.FullName + # Using the markdown created when the project was built. + DocOutputFolder = $TestDrive.FullName | Join-Path -ChildPath 'WikiContent' + SourcePath = "$($TestDrive.FullName)/source" + } + + Invoke-Build -Task $buildTaskName -File $script:buildScript.Definition @taskParameters + } | Should -Not -Throw + } +}