diff --git a/.github/actions/update-index/src/Helper.psm1 b/.github/actions/update-index/src/Helper.psm1 index dbba6f8..25b10ec 100644 --- a/.github/actions/update-index/src/Helper.psm1 +++ b/.github/actions/update-index/src/Helper.psm1 @@ -34,29 +34,40 @@ function Show-RepoList { ) LogGroup "Connect to organization [$Owner]" { - Connect-GitHubApp -Organization $Owner -Default + $currentContext = Get-GitHubContext -ErrorAction SilentlyContinue + if ($null -eq $currentContext) { + Connect-GitHubApp -Organization $Owner -Default + } elseif ($currentContext.AuthType -eq 'App') { + Connect-GitHubApp -Organization $Owner -Default + } else { + Write-Output "Using existing GitHub context [$($currentContext.Name)] with auth type [$($currentContext.AuthType)]" + } Get-GitHubContext | Select-Object * | Format-List | Out-String } LogGroup "Get repositories for organization [$Owner]" { - $rawRepos = Get-GitHubRepository -Organization $Owner -AdditionalProperty 'description' + $rawRepos = Get-GitHubRepository -Owner $Owner Write-Output "Found $($rawRepos.Count) repositories" $repos = $rawRepos | ForEach-Object { $rawRepo = $_ $rawRepo.CustomProperties | Where-Object { $_.Name -eq 'Type' } | ForEach-Object { $type = $_.Value [pscustomobject]@{ - Name = $rawRepo.Name - Owner = $Owner - Type = $type - Description = $rawRepo.Description + Name = $rawRepo.Name + Owner = $Owner + Type = $type + Description = $rawRepo.Description + DefaultBranch = $rawRepo.DefaultBranch + Stars = $rawRepo.Stargazers + OpenIssuesCount = $rawRepo.OpenIssues + HtmlUrl = $rawRepo.Url } } } | Sort-Object Type, Name $repos | Format-Table -AutoSize } - $repos | Group-Object -Property Type + $repos } function Update-MDSection { @@ -117,6 +128,458 @@ function Update-MDSection { } } +function Get-TemplateContent { + <# + .SYNOPSIS + Reads a template file as raw text. + + .DESCRIPTION + Loads a UTF-8 template file from disk and returns the complete content as a string. + #> + [OutputType([string])] + [CmdletBinding()] + param( + [Parameter(Mandatory)] + [string] $Path + ) + + Get-Content -Path $Path -Raw +} + +function Get-PropertyValue { + <# + .SYNOPSIS + Gets the first non-empty property value from an object. + + .DESCRIPTION + Evaluates the provided property names in order and returns the first property + value that exists and is not null/whitespace. Returns the default value otherwise. + #> + [OutputType([object])] + [CmdletBinding()] + param( + [Parameter(Mandatory)] + [object] $InputObject, + + [Parameter(Mandatory)] + [string[]] $Names, + + [Parameter()] + [object] $Default = $null + ) + + foreach ($name in $Names) { + $property = $InputObject.PSObject.Properties[$name] + if ($null -eq $property) { + continue + } + if ($null -eq $property.Value) { + continue + } + $value = [string]$property.Value + if ([string]::IsNullOrWhiteSpace($value)) { + continue + } + return $property.Value + } + + return $Default +} + +function Invoke-GitHubApi { + <# + .SYNOPSIS + Invokes a GitHub REST API GET request. + + .DESCRIPTION + Calls the GitHub module API wrapper, auto-selects anonymous mode when no context + is configured, normalizes wrapped responses, and treats HTTP 404 as missing data. + #> + [OutputType([object])] + [CmdletBinding()] + param( + [Parameter(Mandatory)] + [string] $Uri + ) + + try { + $apiParameters = @{ + Method = 'GET' + Uri = $Uri + ErrorAction = 'Stop' + } + + $availableContexts = Get-GitHubContext -ListAvailable -ErrorAction SilentlyContinue + if ($null -eq $availableContexts -or $availableContexts.Count -eq 0) { + $apiParameters.Anonymous = $true + } + + $rawResponse = GitHub\Invoke-GitHubAPI @apiParameters + if ($null -eq $rawResponse) { + return $null + } + + if ($rawResponse -is [array] -and $rawResponse.Count -gt 0 -and $rawResponse[0].PSObject.Properties['Response']) { + $payloadItems = @() + foreach ($item in $rawResponse) { + if ($null -eq $item.Response) { + continue + } + + if ($item.Response -is [array]) { + $payloadItems += $item.Response + } else { + $payloadItems += , $item.Response + } + } + + if ($payloadItems.Count -eq 0) { + return $null + } + if ($payloadItems.Count -eq 1) { + return $payloadItems[0] + } + + return $payloadItems + } + + if ($rawResponse.PSObject.Properties['Response']) { + return $rawResponse.Response + } + + return $rawResponse + } catch { + $statusCode = $null + if ($_.Exception.Response) { + $statusCode = $_.Exception.Response.StatusCode.value__ + } + $exceptionMessage = [string]$_.Exception.Message + $errorText = $_ | Out-String + if ( + $statusCode -eq 404 -or + $exceptionMessage -match '\b404\b' -or + $exceptionMessage -match 'Not Found' -or + $errorText -match 'StatusCode\s*:\s*404' -or + $errorText -match '\(404\)' + ) { + return $null + } + + Write-Warning "GitHub API call failed for [$Uri]: $($_.Exception.Message)" + return $null + } +} + +function Get-RepositoryReadmeContent { + <# + .SYNOPSIS + Gets a repository README as plain text. + + .DESCRIPTION + Downloads the repository README from GitHub and decodes the returned + Base64 content to UTF-8 text. + #> + [OutputType([string])] + [CmdletBinding()] + param( + [Parameter(Mandatory)] + [string] $Owner, + [Parameter(Mandatory)] + [string] $Name + ) + + $uri = "https://api.github.com/repos/$Owner/$Name/readme" + $response = Invoke-GitHubApi -Uri $uri + if ($null -eq $response) { + return '' + } + + $encodedContent = Get-PropertyValue -InputObject $response -Names @('content') + if ([string]::IsNullOrWhiteSpace([string]$encodedContent)) { + return '' + } + + $cleanContent = ([string]$encodedContent).Replace("`n", '').Replace("`r", '') + [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($cleanContent)) +} + +function Get-MarkdownSummary { + <# + .SYNOPSIS + Extracts a short summary from markdown content. + + .DESCRIPTION + Removes common markdown formatting and returns the first non-empty paragraph, + suitable for compact previews. + #> + [OutputType([string])] + [CmdletBinding()] + param( + [Parameter()] + [string] $Markdown + ) + + if ([string]::IsNullOrWhiteSpace($Markdown)) { + return '' + } + + $text = $Markdown + $text = [regex]::Replace($text, '(?s)```.*?```', ' ') + $text = [regex]::Replace($text, '(?m)^!\[[^\]]*\]\([^\)]*\)\s*$', '') + $text = [regex]::Replace($text, '(?m)^#+\s+', '') + $text = [regex]::Replace($text, '\[([^\]]+)\]\([^\)]+\)', '$1') + $text = [regex]::Replace($text, '(?m)^\s*>+\s*', '') + $text = [regex]::Replace($text, '[*_`~]', '') + $text = [regex]::Replace($text, '\r?\n', "`n") + + foreach ($paragraph in ($text -split "`n`n")) { + $candidate = [regex]::Replace($paragraph, '\s+', ' ').Trim() + if (-not [string]::IsNullOrWhiteSpace($candidate)) { + return $candidate + } + } + + '' +} + +function ConvertTo-HtmlAttributeValue { + <# + .SYNOPSIS + Converts text to a safe HTML attribute preview value. + + .DESCRIPTION + Normalizes whitespace, truncates to a max length, and escapes special HTML + characters for use in attributes such as title. + #> + [OutputType([string])] + [CmdletBinding()] + param( + [Parameter()] + [string] $Value, + [Parameter()] + [int] $MaxLength = 160 + ) + + if ([string]::IsNullOrWhiteSpace($Value)) { + return '' + } + + $singleLine = [regex]::Replace($Value, '\s+', ' ').Trim() + if ($singleLine.Length -gt $MaxLength) { + $singleLine = $singleLine.Substring(0, $MaxLength - 1).TrimEnd() + '...' + } + + $singleLine = $singleLine.Replace('&', '&') + $singleLine = $singleLine.Replace('"', '"') + $singleLine = $singleLine.Replace('<', '<') + $singleLine = $singleLine.Replace('>', '>') + $singleLine +} + +function Get-OpenItemCount { + <# + .SYNOPSIS + Gets the open issue or pull request count for a repository. + + .DESCRIPTION + Uses GitHub search API with a repository/type/state query and returns + the total count. + #> + [OutputType([int])] + [CmdletBinding()] + param( + [Parameter(Mandatory)] + [string] $Owner, + [Parameter(Mandatory)] + [string] $Name, + [Parameter(Mandatory)] + [ValidateSet('issue', 'pr')] + [string] $Type + ) + + $query = [uri]::EscapeDataString("repo:$Owner/$Name type:$Type state:open") + $uri = "https://api.github.com/search/issues?q=$query&per_page=1" + $response = Invoke-GitHubApi -Uri $uri + if ($null -eq $response) { + return 0 + } + + [int](Get-PropertyValue -InputObject $response -Names @('total_count') -Default 0) +} + +function Get-RepositoryVersion { + <# + .SYNOPSIS + Gets a repository's latest version identifier. + + .DESCRIPTION + Returns the latest release tag/name when available, otherwise falls back + to the most recent tag, or N/A. + #> + [OutputType([string])] + [CmdletBinding()] + param( + [Parameter(Mandatory)] + [string] $Owner, + [Parameter(Mandatory)] + [string] $Name + ) + + $latestReleaseUri = "https://api.github.com/repos/$Owner/$Name/releases/latest" + $latestRelease = Invoke-GitHubApi -Uri $latestReleaseUri + if ($null -ne $latestRelease) { + $releaseName = Get-PropertyValue -InputObject $latestRelease -Names @('tag_name', 'name') + if (-not [string]::IsNullOrWhiteSpace([string]$releaseName)) { + return [string]$releaseName + } + } + + $latestTagUri = "https://api.github.com/repos/$Owner/$Name/tags?per_page=1" + $latestTags = Invoke-GitHubApi -Uri $latestTagUri + if ($null -eq $latestTags -or $latestTags.Count -eq 0) { + return 'N/A' + } + + [string](Get-PropertyValue -InputObject $latestTags[0] -Names @('name') -Default 'N/A') +} + +function Get-WorkflowReference { + <# + .SYNOPSIS + Gets the Process-PSModule workflow reference used by a repository. + + .DESCRIPTION + Scans common workflow entry files on the default branch and extracts the + `@ref` from `uses: PSModule/Process-PSModule/...@ref` if present. + #> + [OutputType([string])] + [CmdletBinding()] + param( + [Parameter(Mandatory)] + [string] $Owner, + [Parameter(Mandatory)] + [string] $Name, + [Parameter(Mandatory)] + [string] $DefaultBranch + ) + + foreach ($workflowPath in @('.github/workflows/workflow.yml', '.github/workflows/workflow.yaml')) { + $encodedRef = [uri]::EscapeDataString($DefaultBranch) + $uri = "https://api.github.com/repos/$Owner/$Name/contents/${workflowPath}?ref=$encodedRef" + $response = Invoke-GitHubApi -Uri $uri + if ($null -eq $response) { + continue + } + + $content = Get-PropertyValue -InputObject $response -Names @('content') + if ([string]::IsNullOrWhiteSpace([string]$content)) { + continue + } + + $decoded = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String(([string]$content).Replace("`n", '').Replace("`r", ''))) + $match = [regex]::Match($decoded, '(?m)uses:\s*PSModule/Process-PSModule/.+?@(?[^\s#]+)') + if ($match.Success) { + return $match.Groups['ref'].Value + } + } + + 'N/A' +} + +function Get-ProcessReferenceStatus { + <# + .SYNOPSIS + Computes status of a Process-PSModule workflow reference. + + .DESCRIPTION + Classifies a workflow reference value relative to the latest available + Process-PSModule version. + #> + [OutputType([string])] + [CmdletBinding()] + param( + [Parameter()] + [string] $Reference, + [Parameter()] + [string] $LatestVersion + ) + + if ([string]::IsNullOrWhiteSpace($Reference) -or $Reference -eq 'N/A') { + return 'not-configured' + } + + if ($Reference -match '^[0-9a-f]{7,40}$') { + return 'sha-pinned' + } + + if ([string]::IsNullOrWhiteSpace($LatestVersion) -or $LatestVersion -eq 'N/A') { + return 'unknown' + } + + $referenceNormalized = $Reference.TrimStart('v') + $latestNormalized = $LatestVersion.TrimStart('v') + if ($referenceNormalized -eq $latestNormalized) { + return 'up-to-date' + } + + $referenceVersion = $null + $latestVersionParsed = $null + $hasReferenceVersion = [version]::TryParse(($referenceNormalized -replace '-.*$'), [ref]$referenceVersion) + $hasLatestVersion = [version]::TryParse(($latestNormalized -replace '-.*$'), [ref]$latestVersionParsed) + if ($hasReferenceVersion -and $hasLatestVersion) { + if ($referenceVersion -lt $latestVersionParsed) { + return 'behind' + } + return 'ahead' + } + + 'behind' +} + +function New-ModuleCatalogPage { + <# + .SYNOPSIS + Creates or updates a generated module catalog page. + + .DESCRIPTION + Builds markdown content from module metadata and writes it to the + target page path. + #> + [CmdletBinding(SupportsShouldProcess)] + param( + [Parameter(Mandatory)] + [string] $Path, + [Parameter(Mandatory)] + [pscustomobject] $ModuleData + ) + + $content = @" +# $($ModuleData.Name) + +> This page is generated from repository metadata by the docs index pipeline. + +- Repository: [$($ModuleData.Owner)/$($ModuleData.Name)](https://github.com/$($ModuleData.Owner)/$($ModuleData.Name)) +- Description: $($ModuleData.Description) +- Version: `$($ModuleData.Version)` +- Process-PSModule: `$($ModuleData.ProcessReference)` (`$($ModuleData.ProcessStatus)`) +- Open issues: [$($ModuleData.Issues)](https://github.com/$($ModuleData.Owner)/$($ModuleData.Name)/issues) +- Open PRs: [$($ModuleData.PullRequests)](https://github.com/$($ModuleData.Owner)/$($ModuleData.Name)/pulls) +- Stars: [$($ModuleData.Stars)](https://github.com/$($ModuleData.Owner)/$($ModuleData.Name)/stargazers) + +## About + +$($ModuleData.About) + +## README + +[View source README](https://github.com/$($ModuleData.Owner)/$($ModuleData.Name)#readme) +"@ + + if ($PSCmdlet.ShouldProcess($Path, 'Write module catalog page')) { + Set-Content -Path $Path -Value $content + } +} + function Update-ActionList { <# .SYNOPSIS @@ -182,52 +645,103 @@ function Update-ModuleList { Updates the PowerShell modules list section in the documentation. .DESCRIPTION - Generates an HTML table of all PowerShell module repositories from the module's repo list, - including GitHub and PowerShell Gallery badges, and updates the MODULE_LIST section in - the PowerShell Modules index markdown file. - - .EXAMPLE - Update-ModuleList - - Regenerates the module table and writes it to docs\PowerShell\Modules\index.md. + Generates an enriched HTML table for PSModule module repositories and writes + repository-specific catalog pages that summarize README and module metadata. #> [CmdletBinding(SupportsShouldProcess)] - param() + param( + [Parameter()] + [object[]] $Repos = @() + ) - $moduleTableRowTemplate = @' - - {{ NAME }} - {{ DESCRIPTION }} -
- GitHub Issues - GitHub Pull Requests - GitHub Stars - GitHub Watchers - GitHub Forks - PowerShell Gallery Downloads - - - GitHub release (with filter) - PowerShell Gallery Version - - -'@ + if ($Repos.Count -eq 0) { + $Repos = Show-RepoList + } + + $moduleCatalogTemplateVersion = 'v2' + $moduleCatalogTemplateFolder = Join-Path (Join-Path $PSScriptRoot '..') 'templates\module-catalog' + $moduleCatalogRowTemplatePath = Join-Path $moduleCatalogTemplateFolder "$moduleCatalogTemplateVersion-row.html" + $moduleCatalogTableTemplatePath = Join-Path $moduleCatalogTemplateFolder "$moduleCatalogTemplateVersion-table.html" + $moduleCatalogRowTemplate = Get-TemplateContent -Path $moduleCatalogRowTemplatePath + $moduleCatalogTableTemplate = Get-TemplateContent -Path $moduleCatalogTableTemplatePath + + $moduleRepos = $Repos | Where-Object { + $_.Type -eq 'Module' -and $_.Owner -eq 'PSModule' + } | Sort-Object Name + + $catalogFolderPath = Join-Path 'src\docs\Modules\Catalog' 'Repositories' + if (-not (Test-Path $catalogFolderPath)) { + $null = New-Item -Path $catalogFolderPath -ItemType Directory + } + + $processLatestVersion = Get-RepositoryVersion -Owner 'PSModule' -Name 'Process-PSModule' $moduleTableRows = '' - $repos | Where-Object { $_.Type -eq 'Module' } | ForEach-Object { - $moduleTableRows += $moduleTableRowTemplate.replace('{{ OWNER }}', $_.Owner).replace('{{ NAME }}', $_.Name).replace('{{ DESCRIPTION }}', $_.Description).TrimEnd() + + foreach ($repo in $moduleRepos) { + $owner = [string](Get-PropertyValue -InputObject $repo -Names @('Owner') -Default 'PSModule') + $name = [string](Get-PropertyValue -InputObject $repo -Names @('Name') -Default '') + if ([string]::IsNullOrWhiteSpace($name)) { + continue + } + + $description = [string](Get-PropertyValue -InputObject $repo -Names @('Description') -Default 'No description available.') + if ([string]::IsNullOrWhiteSpace($description)) { + $description = 'No description available.' + } + + $defaultBranch = [string](Get-PropertyValue -InputObject $repo -Names @('DefaultBranch', 'default_branch') -Default 'main') + if ([string]::IsNullOrWhiteSpace($defaultBranch)) { + $defaultBranch = 'main' + } + + $readmeContent = Get-RepositoryReadmeContent -Owner $owner -Name $name + $aboutSummary = Get-MarkdownSummary -Markdown $readmeContent + if ([string]::IsNullOrWhiteSpace($aboutSummary)) { + $aboutSummary = $description + } + + $titleSummary = ConvertTo-HtmlAttributeValue -Value $aboutSummary + $version = Get-RepositoryVersion -Owner $owner -Name $name + $processReference = Get-WorkflowReference -Owner $owner -Name $name -DefaultBranch $defaultBranch + $processStatus = Get-ProcessReferenceStatus -Reference $processReference -LatestVersion $processLatestVersion + $issues = Get-OpenItemCount -Owner $owner -Name $name -Type issue + $pullRequests = Get-OpenItemCount -Owner $owner -Name $name -Type pr + $stars = [int](Get-PropertyValue -InputObject $repo -Names @('Stars', 'stargazers_count', 'StargazersCount') -Default 0) + + $modulePageFileName = "$name.md" + $modulePagePath = Join-Path $catalogFolderPath $modulePageFileName + $modulePageRelativeLink = "./Repositories/$modulePageFileName" + + $moduleData = [pscustomobject]@{ + Owner = $owner + Name = $name + Description = $description + Version = $version + ProcessReference = $processReference + ProcessStatus = $processStatus + Issues = $issues + PullRequests = $pullRequests + Stars = $stars + About = $aboutSummary + } + New-ModuleCatalogPage -Path $modulePagePath -ModuleData $moduleData + + $moduleTableRow = $moduleCatalogRowTemplate + $moduleTableRow = $moduleTableRow.Replace('{{ MODULE_PAGE_LINK }}', $modulePageRelativeLink) + $moduleTableRow = $moduleTableRow.Replace('{{ TITLE_SUMMARY }}', $titleSummary) + $moduleTableRow = $moduleTableRow.Replace('{{ NAME }}', $name) + $moduleTableRow = $moduleTableRow.Replace('{{ VERSION }}', $version) + $moduleTableRow = $moduleTableRow.Replace('{{ PROCESS_REFERENCE }}', $processReference) + $moduleTableRow = $moduleTableRow.Replace('{{ PROCESS_STATUS }}', $processStatus) + $moduleTableRow = $moduleTableRow.Replace('{{ OWNER }}', $owner) + $moduleTableRow = $moduleTableRow.Replace('{{ ISSUES }}', [string]$issues) + $moduleTableRow = $moduleTableRow.Replace('{{ PULL_REQUESTS }}', [string]$pullRequests) + $moduleTableRow = $moduleTableRow.Replace('{{ STARS }}', [string]$stars) + $moduleTableRows += $moduleTableRow.TrimEnd() $moduleTableRows += [Environment]::NewLine } - $moduleTable = @" - - - - - - -$moduleTableRows
NameDescriptionVersion
- -"@ + $moduleTable = $moduleCatalogTableTemplate.Replace('{{ ROWS }}', $moduleTableRows.TrimEnd()) Update-MDSection -Path '.\src\docs\Modules\Catalog\index.md' -Name 'MODULE_CATALOG' -Content $moduleTable } diff --git a/.github/actions/update-index/src/main.ps1 b/.github/actions/update-index/src/main.ps1 index c2d68fb..81fc345 100644 --- a/.github/actions/update-index/src/main.ps1 +++ b/.github/actions/update-index/src/main.ps1 @@ -1,6 +1,6 @@ Import-Module -Name (Join-Path $PSScriptRoot 'Helper.psm1') -Show-RepoList +$repos = Show-RepoList # Update-ActionList # Update-FunctionAppList -Update-ModuleList +Update-ModuleList -Repos $repos diff --git a/.github/actions/update-index/templates/module-catalog/v1-row.html b/.github/actions/update-index/templates/module-catalog/v1-row.html new file mode 100644 index 0000000..5350c3b --- /dev/null +++ b/.github/actions/update-index/templates/module-catalog/v1-row.html @@ -0,0 +1,17 @@ + + + {{ NAME }} + {{ DESCRIPTION }} +
+ GitHub Issues + GitHub Pull Requests + GitHub Stars + GitHub Watchers + GitHub Forks + PowerShell Gallery Downloads + + + GitHub release (with filter) + PowerShell Gallery Version + + diff --git a/.github/actions/update-index/templates/module-catalog/v1-table.html b/.github/actions/update-index/templates/module-catalog/v1-table.html new file mode 100644 index 0000000..932250e --- /dev/null +++ b/.github/actions/update-index/templates/module-catalog/v1-table.html @@ -0,0 +1,9 @@ + + + + + + + + +{{ ROWS }}
NameDescriptionVersion
diff --git a/.github/actions/update-index/templates/module-catalog/v2-row.html b/.github/actions/update-index/templates/module-catalog/v2-row.html new file mode 100644 index 0000000..4621275 --- /dev/null +++ b/.github/actions/update-index/templates/module-catalog/v2-row.html @@ -0,0 +1,9 @@ + + + {{ NAME }} + {{ VERSION }} + {{ PROCESS_REFERENCE }}
{{ PROCESS_STATUS }} + {{ ISSUES }} + {{ PULL_REQUESTS }} + {{ STARS }} + diff --git a/.github/actions/update-index/templates/module-catalog/v2-table.html b/.github/actions/update-index/templates/module-catalog/v2-table.html new file mode 100644 index 0000000..2429e73 --- /dev/null +++ b/.github/actions/update-index/templates/module-catalog/v2-table.html @@ -0,0 +1,12 @@ + + + + + + + + + + + +{{ ROWS }}
NameVersionProcess versionIssuesPull requestsStars
diff --git a/.github/workflows/Docs.yml b/.github/workflows/Docs.yml index bdccaf0..1cd4c08 100644 --- a/.github/workflows/Docs.yml +++ b/.github/workflows/Docs.yml @@ -2,6 +2,8 @@ name: Docs on: workflow_dispatch: + schedule: + - cron: '*/5 * * * *' push: branches: - main @@ -28,6 +30,7 @@ permissions: jobs: lint: name: Lint + if: github.event_name == 'pull_request' runs-on: ubuntu-24.04 permissions: contents: read diff --git a/src/docs/Modules/Catalog/index.md b/src/docs/Modules/Catalog/index.md index f43062d..5db88f7 100644 --- a/src/docs/Modules/Catalog/index.md +++ b/src/docs/Modules/Catalog/index.md @@ -14,7 +14,7 @@ Each module page should capture: ## Catalog generation -The module list is intended to be generated from repository metadata and refreshed automatically. +The module list and linked module pages are generated from PSModule repository metadata and README content, then refreshed automatically. diff --git a/src/docs/Modules/index.md b/src/docs/Modules/index.md index 2989ec8..e1e1bbb 100644 --- a/src/docs/Modules/index.md +++ b/src/docs/Modules/index.md @@ -16,6 +16,6 @@ This section is the local source of truth for: - [Module types](Module-Types.md) - [Test Specification](Test-Specification.md) - [Versioning](Versioning.md) -- [Catalog](Catalog/index.md) +- [Catalog](Catalog/index.md) (auto-generated from PSModule repo metadata, release data, and README summaries) - [Process-PSModule](Process-PSModule/index.md) - [Dashboard Extension](Dashboard-Extension/index.md) diff --git a/src/docs/assets/images/module-catalog/githubissues.svg b/src/docs/assets/images/module-catalog/githubissues.svg new file mode 100644 index 0000000..9ff6364 --- /dev/null +++ b/src/docs/assets/images/module-catalog/githubissues.svg @@ -0,0 +1 @@ + diff --git a/src/docs/assets/images/module-catalog/githubpullrequests.svg b/src/docs/assets/images/module-catalog/githubpullrequests.svg new file mode 100644 index 0000000..21a334a --- /dev/null +++ b/src/docs/assets/images/module-catalog/githubpullrequests.svg @@ -0,0 +1 @@ + diff --git a/src/docs/assets/images/module-catalog/githubstars.svg b/src/docs/assets/images/module-catalog/githubstars.svg new file mode 100644 index 0000000..9073165 --- /dev/null +++ b/src/docs/assets/images/module-catalog/githubstars.svg @@ -0,0 +1 @@ + diff --git a/src/docs/assets/images/module-catalog/githubtags.svg b/src/docs/assets/images/module-catalog/githubtags.svg new file mode 100644 index 0000000..d20df96 --- /dev/null +++ b/src/docs/assets/images/module-catalog/githubtags.svg @@ -0,0 +1 @@ + diff --git a/src/docs/assets/images/module-catalog/package-variant-closed-check.svg b/src/docs/assets/images/module-catalog/package-variant-closed-check.svg new file mode 100644 index 0000000..f3dc43d --- /dev/null +++ b/src/docs/assets/images/module-catalog/package-variant-closed-check.svg @@ -0,0 +1 @@ + \ No newline at end of file