public/ConvertTo-HugoFormat.ps1

function ConvertTo-HugoFormat {
    <#
    .SYNOPSIS
        Converts PlatyPS-generated Markdown files to Hugo-compatible format.

    .DESCRIPTION
        ConvertTo-HugoFormat reads PlatyPS Markdown files and rewrites them with:

        - Hugo front matter (title, weight) replacing PlatyPS YAML metadata
        - Module index pages renamed to _index.md (Hugo branch bundle convention)
        - SYNTAX section cleaned up (removes __AllParameterSets subheading)
        - ALIASES section cleaned up (removes unresolved {{...}} placeholders)
        - Optional root content/_index.md generated from the module page (-RootIndex)

        The output is ready to drop into a Hugo content directory. Module pages
        receive chapter: true so the Relearn theme treats them as section headings.

    .PARAMETER Path
        Path to one or more PlatyPS Markdown files, or a directory containing them.
        Accepts pipeline input.

    .PARAMETER OutputFolder
        Destination folder for the converted files. Created automatically if it
        does not exist.

    .PARAMETER RootIndex
        When processing a directory, also generate a root content/_index.md one
        level above OutputFolder. The file is built from the module page title,
        description, and the synopsis of each cmdlet page. Has no effect when
        processing individual files.

    .PARAMETER Force
        Overwrite existing output files without prompting.

    .PARAMETER PassThru
        Emit the generated FileInfo objects to the pipeline.

    .EXAMPLE
        ```powershell
        $hugoParams = @{
            Path = '.\help\markdown\PlatyPS.Hosting'
            OutputFolder = '.\hugo\content\PlatyPS.Hosting'
            RootIndex = $true
        }
        ConvertTo-HugoFormat @hugoParams
        ```

        Converts all PlatyPS Markdown files and also generates .\hugo\content\_index.md
        from the module description and cmdlet synopses.

    .EXAMPLE
        ```powershell
        Get-Item .\help\markdown\MyModule\New-Widget.md |
            ConvertTo-HugoFormat -OutputFolder .\hugo\content\MyModule -PassThru
        ```

        Converts a single file and returns the resulting FileInfo to the pipeline.
    #>

    [CmdletBinding(HelpUri = 'https://steviecoaster.github.io/PlatyPS.Hosting/PlatyPS.Hosting/ConvertTo-HugoFormat/',SupportsShouldProcess)]
    param(
        [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
        [Alias('FullName')]
        [string[]]
        $Path,

        [Parameter(Mandatory)]
        [string]
        $OutputFolder,

        [switch]
        $Force,

        [switch]
        $RootIndex,

        [switch]
        $PassThru
    )

    begin {
        if (-not (Test-Path $OutputFolder)) {
            $null = New-Item $OutputFolder -ItemType Directory -Force
        }

        # Cmdlet pages start at weight 2; module page is always weight 1
        $weight = 2

        # Accumulated data for optional root _index.md
        $rootModuleTitle       = $null
        $rootModuleDescription = $null
        $rootCmdletRows        = [System.Collections.Generic.List[string]]::new()
    }

    process {
        foreach ($p in $Path) {
            $resolved = Get-Item -LiteralPath $p -ErrorAction Stop

            $files = if ($resolved.PSIsContainer) {
                Get-ChildItem -LiteralPath $resolved.FullName -Filter '*.md'
            }
            else {
                $resolved
            }

            foreach ($file in $files) {
                $raw = Get-Content -LiteralPath $file.FullName -Raw

                # Split YAML front matter from body
                if ($raw -notmatch '(?s)\A---\r?\n(.+?)\r?\n---\r?\n(.*)') {
                    Write-Warning "Skipping $($file.Name): no YAML front matter found."
                    continue
                }

                $yamlBlock = $Matches[1]
                $body      = $Matches[2]

                # Extract the fields we need from PlatyPS front matter
                $docType = if ($yamlBlock -match '(?m)^document type:\s*(.+)$') { $Matches[1].Trim() } else { 'cmdlet' }
                $title   = if ($yamlBlock -match '(?m)^title:\s*(.+)$')         { $Matches[1].Trim() } else { $file.BaseName }

                # Build Hugo front matter
                $isModule = $docType -eq 'module'

                $hugoFrontMatter = if ($isModule) {
                    @"
---
title: "$title"
weight: 1
chapter: true
---
"@

                }
                else {
                    $fm = @"
---
title: "$title"
weight: $weight
---
"@

                    $weight++
                    $fm
                }

                # Remove ### __AllParameterSets subheading from SYNTAX section
                $body = $body -replace '(?m)^### __AllParameterSets\r?\n', ''

                # Replace the unresolved PlatyPS alias placeholder with "None"
                $body = $body -replace '(?m)^This cmdlet has the following aliases,\r?\n\s*\{\{Insert list of aliases\}\}', 'None'

                # Collect data for optional root _index.md
                if ($RootIndex -and $resolved.PSIsContainer) {
                    if ($isModule) {
                        $rootModuleTitle = $title
                        # Grab the Description body (text between ## Description and the next ##)
                        if ($body -match '(?s)## Description\r?\n\r?\n(.+?)(?=\r?\n## |\z)') {
                            $rootModuleDescription = $Matches[1].Trim()
                        }
                    }
                    else {
                        # Grab synopsis (first non-blank line after ## SYNOPSIS)
                        $synopsis = if ($body -match '(?m)^## SYNOPSIS\r?\n\r?\n(.+)$') { $Matches[1].Trim() } else { '' }
                        $sectionName = Split-Path $OutputFolder -Leaf
                        $rootCmdletRows.Add("| [$title]($sectionName/$title) | $synopsis |")
                    }
                }

                # Determine output filename
                $outName = if ($isModule) { '_index.md' } else { $file.Name }
                $outPath = Join-Path $OutputFolder $outName

                if ((Test-Path $outPath) -and -not $Force) {
                    Write-Warning "Skipping existing file (use -Force to overwrite): $outPath"
                    continue
                }

                if ($PSCmdlet.ShouldProcess($outPath, 'Write Hugo Markdown')) {
                    ($hugoFrontMatter + "`n" + $body.TrimStart()) |
                        Set-Content -LiteralPath $outPath -Encoding utf8NoBOM

                    if ($PassThru) {
                        Get-Item -LiteralPath $outPath
                    }
                }
            }
        }
    }

    end {
        if (-not $RootIndex -or -not $rootModuleTitle) { return }

        $siteContentRoot = Split-Path $OutputFolder -Parent
        $rootIndexPath   = Join-Path $siteContentRoot '_index.md'

        if ((Test-Path $rootIndexPath) -and -not $Force) {
            Write-Warning "Skipping existing root index (use -Force to overwrite): $rootIndexPath"
            return
        }

        $cmdletTable = @(
            '| Command | Description |'
            '|---------|-------------|'
        ) + $rootCmdletRows | Out-String -Width 9999

        $rootContent = @"
---
title: "$rootModuleTitle"
weight: 1
---

$rootModuleDescription

## Commands

$($cmdletTable.Trim())
"@


        if ($PSCmdlet.ShouldProcess($rootIndexPath, 'Write Hugo root _index.md')) {
            $rootContent | Set-Content -LiteralPath $rootIndexPath -Encoding utf8NoBOM

            if ($PassThru) {
                Get-Item -LiteralPath $rootIndexPath
            }
        }
    }
}