Commands/Publish-OpenPackage.ps1

function Publish-OpenPackage {
    <#
    .SYNOPSIS
        Publishes Open Package
    .DESCRIPTION
        Publishes Open Packages using any `OpenPackage.Publisher` or command.
    #>

    [CmdletBinding(PositionalBinding=$false,SupportsShouldProcess)]
    [Alias('Publish-OP', 'pbop', 'pbOpenPackage')]
    param(
    # The name of the Publisher, or a command or script block used to Publish.
    # One or more publishers may be provided. They will be processed in the order provided.
    [Parameter(Mandatory,Position=0)]
    [ArgumentCompleter({
        param ( $commandName,
              $parameterName,
              $wordToComplete,
              $commandAst,
              $fakeBoundParameters )            
        $typeData = Get-TypeData -TypeName OpenPackage.Publisher
        
        if (-not $wordToComplete) {
            $typeData.Members.Keys
        } else {
            $typeData.Members.Keys -match ([Regex]::Escape($wordTocomplete))
        }
    })]
    [PSObject[]]
    $Publisher,

    # The Any Positional arguments for the view
    [Parameter(Position=1,ValueFromRemainingArguments)]
    [Alias('Argument','Arguments','Args')]
    [PSObject[]]
    $ArgumentList,

    # Any input objects.
    [Parameter(ValueFromPipeline)]
    [Alias('Package')]
    [PSObject[]]
    $InputObject,
    
    # Any options to pass to the View
    [Alias('Options','Parameter','Parameters')]
    [Collections.IDictionary]
    $Option = [Ordered]@{}
    )

    # Gather all input
    $allInput = @($input)

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

    # Get the typedata that describes Publishers
    $typeData = Get-TypeData -TypeName OpenPackage.Publisher

    # Define a filter to run each publisher
    filter publish {
        $Publisher = $_
        # If the Publisher is a string
        if ($Publisher -is [string]) {
            # check for a Publisher with that name
            if ($typeData.Members[$Publisher].Script) {
                # if one is found, call it with the package and option
                $Publisher = $typeData.Members[$Publisher].Script
            } 
            elseif (
                $typeData.Members[$publisher].ReferencedMemberName -and 
                $typeData.Members[
                    "$($typeData.Members[$publisher].ReferencedMemberName)"
                ].Script
            ) {
                $Publisher = $typeData.Members[
                    "$($typeData.Members[$publisher].ReferencedMemberName)"
                ].Script
            }
            else {
                # Othewise, try to find a Publisher command
                $PublisherCommand = 
                    $ExecutionContext.SessionState.InvokeCommand.GetCommand(
                        $Publisher,'Cmdlet,Alias,Function'
                    )
                # If we found one, try to use it
                if ($PublisherCommand) {
                    $Publisher = $PublisherCommand
                } else {
                    # Otherwise, warn that Publisher is unknown
                    Write-Warning "Unknown Publisher $Publisher"
                    # and break out of the loop.
                    return
                }                    
            }
        }    

        # If this publisher is not a script block or command
        if ($Publisher -isnot [ScriptBlock] -and 
            $Publisher -isnot [Management.Automation.CommandInfo]
        ) {
            # write an error and return
            Write-Error "Publisher must be a name of a OpenPackage.Publisher method, ScriptBlock, or Command"
            return
        }
        
        # Get our command metadata.
        $commandMetaData =
            if ($Publisher -is [ScriptBlock]) {
                # If the Publisher is a scriptblock
                # make a temporary function
                $function:Publisher = $Publisher
                # get its metadata
                $ExecutionContext.SessionState.InvokeCommand.GetCommand('Publisher', 'Function') -as 
                    [Management.Automation.CommandMetaData]
                # and remove the temporary function
                Remove-Item 'function:Publisher'
            } else {
                # otherwise, just cast to command metadata
                $commandName = $Publisher.Name
                Publisher -as [Management.Automation.CommandMetaData]
            }

        # Once we have commandmetadata, we can find parameter names.
        $validParameterNames = @(
            $commandMetaData.Parameters.Keys
            $commandMetaData.Parameters.Values.Aliases
            if ($commandMetaData.SupportsShouldProcess) {
                'WhatIf'
                'Confirm'
            }
        )
        
        # We want to be forgiving with input, so copy the options
        $commandParameters = [Ordered]@{} + $Option
        if ($WhatIfPreference) { $commandParameters.WhatIf = $true}
        if ($PSBoundParameters['Confirm']) {
            $commandParameters.Confirm = $PSBoundParameters['Confirm']
        }
        # Check each key
        foreach ($key in @($commandParameters.Keys)) {
            # If we have valid parameter names
            if ($validParameterNames -and
                # and this isn't one of them,
                $validParameterNames -notcontains $key                     
            ) {
                # write a warning
                Write-Warning "Option $key not supported by $($commandName)"
                # and remove the key.
                $commandParameters.Remove($key)
            }
        }

        # If there was any input, pipe it into the publisher.
        if ($allInput) {
            # If there were arguments, pass them
            if ($ArgumentList) {
                $allInput | & $Publisher @ArgumentList @commandParameters
            } else {
                $allInput | & $Publisher @commandParameters
            }
        } else {
            if ($ArgumentList) {
                & $Publisher @ArgumentList @commandParameters
            } else {
                & $Publisher @commandParameters
            }    
        }
    }
 
    # Collect all the publishers
    @($Publisher) | 
        publish # and publish them.
}