Types/OpenPackage.View/Tree.md.ps1

<#
.SYNOPSIS
    Shows a markdown package tree
.DESCRIPTION
    Shows a package tree as markdown.
.NOTES
    Will ignore any input that is not a package
#>

[OutputType('text/markdown')]
param(
# Any input.
# If this is not a package, or does not contain a package, the input will be ignored.
[Parameter(ValueFromPipeline)]
[Alias('Package')]
[PSObject]
$InputObject,
    
# The file pattern. All files that match this pattern will be urn.
[string]
$FilePattern = '.'
)

$allInput = @($input)
if ((-not $allInput) -and $InputObject) {
    $allInput += $InputObject
}


filter toIndex {
    $in = $_
    
    if ($in -is [Collections.IDictionary]) {        
        $in.GetEnumerator() | . toIndex            
    } elseif ($in.Key -is [string]) {        
        $prefix = "$(' ' * $depth * 2)* "
        $depth++    
        if ($in.Value -is  [Collections.IDictionary]) {
            if (
                $in.Value.Keys -match 'index\..+?$' -and
                $in.Value.Values.Uri
            ) {
                $prefix + "[$($in.Key)]($(
                    $rootUrl +
                        @(
                            @($in.Value.Values.Uri) -match 'index\..+?$'
                        )[0] -replace 'index\..+?$'
                ))"

            } else {
                $prefix + $in.Key
            }
            
            $in.Value | . toIndex
        } elseif ($in.Value.Uri) {
            $prefix + "[$($in.Key)]($($rootUrl)$($in.Value.Uri))"
        } elseif ($in.Value.FullName) {
            $prefix + "[$($in.Key)]($($in.Value.FullName))"
        } else {
            $prefix + $in.Key
        }
        $depth--
    }
    
}

foreach ($in in $allInput) {
    $fileTree = $null
    $rootUrl = ''
    if ($in.GetTree) {
        $fileTree = $in.GetTree($FilePattern)
    }
    if ($in.Package.GetTree) {
        $fileTree = $in.Package.GetTree($FilePattern)        
    }
    if ($in.Url) {
        $rootUrl = $in.Url
    }
    
    if ($in -is [IO.DirectoryInfo]) {
        $filelist = @(Get-ChildItem -Path $in -File -Recurse)
        $fileTree = [Ordered]@{}
        foreach ($fileInfo in $filelist) {
            $relativePath = $fileInfo.FullName.Substring($in.FullName.Length + 1)
            $pointer = $fileTree
            $hierarchy = @($relativePath -split '[\\/]')
            for ($index = 0; $index -lt ($hierarchy.Length - 1); $index++) {
                $subdirectory = $hierarchy[$index]
                if (-not $pointer[$subdirectory]) {
                    $pointer[$subdirectory] = [Ordered]@{}
                }
                $pointer = $pointer[$subdirectory]
            }
            $pointer[$hierarchy[-1]] = $fileInfo
        }
    }
    
    if (-not $fileTree.Count) {
        continue
    }
    @(
        $depth = 0
        $fileTree | toIndex        
    ) -join [Environment]::NewLine |
        Add-Member NoteProperty Package $in -Force -PassThru |
        Add-Member NoteProperty FilePattern $in -Force -PassThru |
        . {
            process {
                $_.pstypenames.add('text/markdown')
                $_
            }
        }
}