docfx-toc-generator.psm1
function Get-FolderGrabCondition($folderName) { $ignoreItemName = ".nodoc" $IgnoreFolderDeafultList = ".\.git", ".\_site", ".\obj", ".\src" $notInListCondition = (-not $IgnoreFolderDeafultList.Contains($folderName)) $doesntHaveNoDocFileCondition = (-not [System.IO.File]::Exists([System.IO.Path]::Combine($folderName, $ignoreItemName))) return $notInListCondition -and $doesntHaveNoDocFileCondition } function Get-SubDocFolders($Path) { $dirs = [System.IO.Directory]::GetDirectories($Path, "*", [System.IO.SearchOption]::AllDirectories) return $dirs | where { Get-FolderGrabCondition $_ } } function Get-RootDocFolder($Path){ $dirs = [System.IO.Directory]::GetDirectories($Path, "*", [System.IO.SearchOption]::TopDirectoryOnly) return $dirs | where { Get-FolderGrabCondition $_ } } function Get-YamlFrontMatter([string]$mdContent, [string]$mdpath) { $lines = $mdContent -Split [System.Environment]::NewLine if (($lines | where {$_ -eq "---"}).Length -eq 2){ $firstIndex = $lines.IndexOf("---") + 1 $secondIndex = $lines[$firstIndex..$lines.Length].IndexOf("---") Write-Host "Indexing '$mdpath'..." -ForegroundColor DarkGray return [string]::Join([System.Environment]::NewLine, $lines[$firstIndex..$secondIndex]) } else{ Write-Host "Front-matter (Yaml meta-data) for '$mdpath' : NOT FOUND" -ForegroundColor DarkGray return "" } } function New-TocYaml($folder, $tocFolder){ $mdFiles = [System.IO.Directory]::GetFiles($folder, "*.md", [System.IO.SearchOption]::TopDirectoryOnly) $topLevelTocItems = New-Object Collections.Generic.List[Object] $mdFiles | % { if([System.IO.Path]::GetFileName($_) -ne "index.md"){ $tocItem = Get-MarkdownSingleTocItem $_ $tocfolder $topLevelTocItems.Add($tocItem) } } $subdocTopFolders = Get-RootDocFolder $folder $indexFiles = $subdocTopFolders | % { Join-Path $_ "index.md" } | where { [System.IO.File]::Exists($_) } $indexTocItems = New-Object Collections.Generic.List[Object] $indexFiles | % { $tocItem = Get-MarkdownSingleTocItem $_ $tocFolder $dirOfIndex = [System.IO.Path]::GetDirectoryName($_) $toc = New-TocYaml $dirOfIndex $tocFolder $items = $toc | Sort-Object -Property order -Descending $items = @($items) if($null -ne $items -and $null -ne $tocItem -and $items.Length -gt 0){ $tocItem.Add("items", @($items)) } $indexTocItems.Add($tocItem) } $result = ($topLevelTocItems + $indexTocItems) | Sort-Object -Property order -Descending $result = @($result) return ([Collections.Generic.List[Object]]$result) } function Get-MarkdownSingleTocItem([string]$markdownPath, $tocFolder){ $content = [System.IO.File]::ReadAllText($markdownPath) $frontMatter = Get-YamlFrontMatter $content $markdownPath if([string]::IsNullOrEmpty($frontMatter)){ return $null } $yaml = $frontMatter | ConvertFrom-Yaml $noName = $null -eq $yaml.name if($noName){ Write-Host "Front-matter of file '$markdownPath' needs a 'name' tag." -ForegroundColor Red return $null } $relPath = [System.IO.Path]::GetRelativePath($tocFolder, $markdownPath) $order = $yaml.order if($null -eq $order) { $order = 0 } return @{ "name" = $yaml.name; "href" = $relPath; "order" = $order } } function Build-TocHereRecursive { foreach ($docFolder in Get-RootDocFolder .) { Write-Host "==== Generating TOC for [$docFolder] ====================" -ForegroundColor DarkGray $raw = New-TocYaml $docFolder $docFolder $tocFile = ConvertTo-Yaml @($raw) $tocFile > (Join-Path $docFolder "toc.yml") Write-Host "==== End Generating for TOC [$docFolder] ================" -ForegroundColor DarkGray Write-Host } } Export-ModuleMember -Function Build-TocHereRecursive |