Public/Test-PCWordTheme.ps1

function Test-PCWordTheme {
    <#
    .SYNOPSIS
        Reports which renderer roles a theme document can satisfy.

    .DESCRIPTION
        Opens the theme and resolves every style role the renderer uses: Title, Heading 1 to 9, Body, Caption,
        Figure, List Paragraph, Quote, Code, TOC Heading, Table, Hyperlink and the code character style.
        Required roles that are missing fail the test. Optional roles that are missing are listed so you know
        which fallbacks the renderer will use.

    .PARAMETER Path
        The theme .docx.
    #>

    [CmdletBinding()]
    [OutputType([pscustomobject])]
    param(
        [Parameter(Mandatory, Position = 0, ValueFromPipeline)]
        [string]$Path
    )

    process {
        $full = (Resolve-Path -LiteralPath $Path -ErrorAction Stop).Path
        $doc = [DocumentFormat.OpenXml.Packaging.WordprocessingDocument]::Open($full, $false)
        try {
            $theme = [PowerCraft.Word.Core.Theme.ThemeDocument]::new($doc.MainDocumentPart)
            $required = @('Heading1', 'Caption', 'Body')
            $roles = [Enum]::GetValues([PowerCraft.Word.Core.Theme.StyleRole])
            $resolved = @{}
            foreach ($role in $roles) { $resolved[[string]$role] = $theme.Resolve($role) }
            $missingRequired = @($required | Where-Object { -not $resolved[$_] })
            $missingOptional = @($roles | ForEach-Object { [string]$_ } | Where-Object { -not $resolved[$_] -and $_ -notin $required })
            [pscustomobject]@{
                Path            = $full
                IsValid         = ($missingRequired.Count -eq 0)
                MissingRequired = $missingRequired
                MissingOptional = $missingOptional
                Resolved        = $resolved
                ContentWidthEmu = $theme.ContentWidthEmu
            }
        }
        finally {
            $doc.Dispose()
        }
    }
}