PSDocs.psm1
# Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # # PSDocs module # Set-StrictMode -Version latest; [PSDocs.Configuration.PSDocumentOption]::UseExecutionContext($ExecutionContext); [PSDocs.Configuration.PSDocumentOption]::UseCurrentCulture(); $Script:UTF8_NO_BOM = New-Object -TypeName System.Text.UTF8Encoding -ArgumentList $False; # # Localization # Import-LocalizedData -BindingVariable LocalizedHelp -FileName 'PSDocs.Resources.psd1' -ErrorAction SilentlyContinue; if ($Null -eq (Get-Variable -Name LocalizedHelp -ErrorAction SilentlyContinue)) { Import-LocalizedData -BindingVariable LocalizedHelp -FileName 'PSDocs.Resources.psd1' -UICulture 'en-US' -ErrorAction SilentlyContinue; } # # Public functions # #region Cmdlets # .ExternalHelp PSDocs-Help.xml function Invoke-PSDocument { [CmdletBinding(DefaultParameterSetName = 'Input')] param ( [Parameter(Mandatory = $True, ParameterSetName = 'InputPath')] [Alias('f')] [String[]]$InputPath, [Parameter(Mandatory = $False)] [Alias('m')] [String[]]$Module, # The name of the document [Parameter(Mandatory = $False)] [Alias('n')] [String[]]$Name, [Parameter(Mandatory = $False)] [String[]]$Tag, [Parameter(Mandatory = $False)] [String[]]$InstanceName, [Parameter(Mandatory = $False, ValueFromPipeline = $True, ParameterSetName = 'Input')] [PSObject]$InputObject, # The path to look for document definitions in [Parameter(Position = 0, Mandatory = $False)] [PSDefaultValue(Help = '.')] [Alias('p')] [String[]]$Path = $PWD, [Parameter(Mandatory = $False)] [Alias('InputFormat')] [ValidateSet('None', 'Yaml', 'Json', 'PowerShellData', 'Detect')] [PSDocs.Configuration.InputFormat]$Format = [PSDocs.Configuration.InputFormat]::Detect, # The output path to save generated documentation [Parameter(Mandatory = $False)] [String]$OutputPath = $PWD, [Parameter(Mandatory = $False)] [Switch]$PassThru, [Parameter(Mandatory = $False)] [PSDocs.Configuration.PSDocumentOption]$Option, [Parameter(Mandatory = $False)] [PSDocs.Configuration.MarkdownEncoding]$Encoding = [PSDocs.Configuration.MarkdownEncoding]::Default, [Parameter(Mandatory = $False)] [String[]]$Culture, [Parameter(Mandatory = $False)] [String[]]$Convention ) begin { Write-Verbose -Message "[Invoke-PSDocument]::BEGIN"; $pipelineReady = $False; # Check if the path is a directory if (!(Test-Path -Path $Path)) { Write-Error -Message $LocalizedHelp.PathNotFound -ErrorAction Stop; return; } # Get parameter options, which will override options from other sources $optionParams = @{ }; if ($PSBoundParameters.ContainsKey('Option')) { $optionParams['Option'] = $Option; } # Get an options object $Option = New-PSDocumentOption @optionParams; # Discover scripts in the specified paths $sourceParams = @{ }; if ($PSBoundParameters.ContainsKey('Path')) { $sourceParams['Path'] = $Path; } if ($PSBoundParameters.ContainsKey('Module')) { $sourceParams['Module'] = $Module; } if ($sourceParams.Count -eq 0) { $sourceParams['Path'] = $Path; } $sourceParams['Option'] = $Option; [PSDocs.Pipeline.Source[]]$sourceFiles = GetSource @sourceParams -Verbose:$VerbosePreference; # Check that some matching script files were found if ($Null -eq $sourceFiles) { Write-Warning -Message $LocalizedHelp.SourceNotFound; return; # continue causes issues with Pester } $isDeviceGuard = IsDeviceGuardEnabled; # If DeviceGuard is enabled, force a contrained execution environment if ($isDeviceGuard) { $Option.Execution.LanguageMode = [PSDocs.Configuration.LanguageMode]::ConstrainedLanguage; } # Get parameter options, which will override options from other sources if ($PSBoundParameters.ContainsKey('Name')) { $Option.Document.Include = $Name; } if ($PSBoundParameters.ContainsKey('Tag')) { $Option.Document.Tag = $Tag; } if ($PSBoundParameters.ContainsKey('Format')) { $Option.Input.Format = $Format; } if ($PSBoundParameters.ContainsKey('OutputPath') -and !$PassThru) { $Option.Output.Path = $OutputPath; } if ($PSBoundParameters.ContainsKey('Culture')) { $Option.Output.Culture = $Culture; } if ($PSBoundParameters.ContainsKey('Encoding')) { $Option.Markdown.Encoding = $Encoding; } $builder = [PSDocs.Pipeline.PipelineBuilder]::Invoke($sourceFiles, $Option, $PSCmdlet, $ExecutionContext); $builder.InstanceName($InstanceName); $builder.Convention($Convention); if ($PSBoundParameters.ContainsKey('InputPath')) { $builder.InputPath($InputPath); } try { $pipeline = $builder.Build(); if ($Null -ne $pipeline) { $pipeline.Begin(); $pipelineReady = $True; } } catch { throw $_.Exception.GetBaseException(); } } process { if ($pipelineReady) { try { # Process pipeline objects $pipeline.Process($InputObject); } catch { $pipeline.Dispose(); throw; } } } end { if ($pipelineReady) { try { $pipeline.End(); } finally { $pipeline.Dispose(); } } Write-Verbose -Message "[Invoke-PSDocument]::END"; } } # .ExternalHelp PSDocs-Help.xml function Get-PSDocument { [CmdletBinding()] [OutputType([PSDocs.Definitions.IDocumentDefinition])] param ( [Parameter(Mandatory = $False)] [Alias('m')] [String[]]$Module, [Parameter(Mandatory = $False)] [Switch]$ListAvailable, # Filter to documents with the following names [Parameter(Mandatory = $False)] [Alias('n')] [String[]]$Name, # A list of paths to check for definitions [Parameter(Mandatory = $False, Position = 0)] [Alias('p')] [String[]]$Path = $PWD, [Parameter(Mandatory = $False)] [PSDocs.Configuration.PSDocumentOption]$Option ) begin { Write-Verbose -Message "[Get-PSDocument]::BEGIN"; $pipelineReady = $False; # Get parameter options, which will override options from other sources $optionParams = @{ }; if ($PSBoundParameters.ContainsKey('Option')) { $optionParams['Option'] = $Option; } # Get an options object $Option = New-PSDocumentOption @optionParams; # Discover scripts in the specified paths $sourceParams = @{ }; if ($PSBoundParameters.ContainsKey('Path')) { $sourceParams['Path'] = $Path; } if ($PSBoundParameters.ContainsKey('Module')) { $sourceParams['Module'] = $Module; } if ($PSBoundParameters.ContainsKey('ListAvailable')) { $sourceParams['ListAvailable'] = $ListAvailable; } if ($sourceParams.Count -eq 0) { $sourceParams['Path'] = $Path; } $sourceParams['Option'] = $Option; [PSDocs.Pipeline.Source[]]$sourceFiles = GetSource @sourceParams -Verbose:$VerbosePreference; # Check that some matching script files were found if ($Null -eq $sourceFiles) { Write-Verbose -Message $LocalizedHelp.SourceNotFound; return; # continue causes issues with Pester } Write-Verbose -Message "[Get-PSDocument] -- Found $($sourceFiles.Length) source file(s)"; $isDeviceGuard = IsDeviceGuardEnabled; # If DeviceGuard is enabled, force a contrained execution environment if ($isDeviceGuard) { $Option.Execution.LanguageMode = [PSDocs.Configuration.LanguageMode]::ConstrainedLanguage; } # Get parameter options, which will override options from other sources if ($PSBoundParameters.ContainsKey('Name')) { $Option.Document.Include = $Name; } $builder = [PSDocs.Pipeline.PipelineBuilder]::Get($sourceFiles, $Option, $PSCmdlet, $ExecutionContext); try { $pipeline = $builder.Build(); if ($Null -ne $pipeline) { $pipeline.Begin(); $pipelineReady = $True; } } catch { throw $_.Exception.GetBaseException(); } } end { if ($pipelineReady) { try { $pipeline.End(); } finally { $pipeline.Dispose(); } } Write-Verbose -Message "[Get-PSDocument]::END"; } } # .ExternalHelp PSDocs-Help.xml function Get-PSDocumentHeader { [CmdletBinding()] param ( [Parameter(Mandatory = $False, ValueFromPipelineByPropertyName = $True)] [Alias('FullName')] [String]$Path = $PWD ) process { $filteredItems = Get-ChildItem -Path (Join-Path -Path $Path -ChildPath '*') -File; foreach ($item in $filteredItems) { ReadYamlHeader -Path $item.FullName -Verbose:$VerbosePreference; } } } # .ExternalHelp PSDocs-Help.xml function New-PSDocumentOption { [CmdletBinding(DefaultParameterSetName = 'FromPath')] [OutputType([PSDocs.Configuration.PSDocumentOption])] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Creates an in memory object only')] param ( [Parameter(Position = 0, Mandatory = $False, ParameterSetName = 'FromPath')] [String]$Path = $PWD, [Parameter(Mandatory = $True, ParameterSetName = 'FromOption')] [PSDocs.Configuration.PSDocumentOption]$Option, [Parameter(Mandatory = $True, ParameterSetName = 'FromDefault')] [Switch]$Default, # Options # Sets the Input.Format option [Parameter(Mandatory = $False)] [Alias('InputFormat')] [ValidateSet('None', 'Yaml', 'Json', 'PowerShellData', 'Detect')] [PSDocs.Configuration.InputFormat]$Format = [PSDocs.Configuration.InputFormat]::Detect, # Sets the Input.ObjectPath option [Parameter(Mandatory = $False)] [String]$InputObjectPath, # Sets the Input.PathIgnore option [Parameter(Mandatory = $False)] [String[]]$InputPathIgnore, # Sets the Markdown.Encoding option [Parameter(Mandatory = $False)] [Alias('MarkdownEncoding')] [PSDocs.Configuration.MarkdownEncoding]$Encoding = [PSDocs.Configuration.MarkdownEncoding]::Default, # Sets the Output.Culture option [Parameter(Mandatory = $False)] [Alias('OutputCulture')] [String[]]$Culture, # Sets the Output.Path option [Parameter(Mandatory = $False)] [String]$OutputPath ) begin { Write-Verbose -Message "[New-PSDocumentOption] BEGIN::"; # Get parameter options, which will override options from other sources $optionParams = @{ }; $optionParams += $PSBoundParameters; # Remove invalid parameters if ($optionParams.ContainsKey('Path')) { $optionParams.Remove('Path'); } if ($optionParams.ContainsKey('Option')) { $optionParams.Remove('Option'); } if ($optionParams.ContainsKey('Default')) { $optionParams.Remove('Default'); } if ($optionParams.ContainsKey('Verbose')) { $optionParams.Remove('Verbose'); } if ($PSBoundParameters.ContainsKey('Option')) { $Option = [PSDocs.Configuration.PSDocumentOption]::FromFileOrEmpty($Option, $Path); } elseif ($PSBoundParameters.ContainsKey('Path')) { Write-Verbose -Message "Attempting to read: $Path"; $Option = [PSDocs.Configuration.PSDocumentOption]::FromFile($Path); } elseif ($PSBoundParameters.ContainsKey('Default')) { $Option = [PSDocs.Configuration.PSDocumentOption]::FromDefault(); } else { Write-Verbose -Message "Attempting to read: $Path"; $Option = [PSDocs.Configuration.PSDocumentOption]::FromFileOrEmpty($Option, $Path); } } end { # Options $Option | SetOptions @optionParams -Verbose:$VerbosePreference; Write-Verbose -Message "[New-PSDocumentOption] END::"; } } #endregion Cmdlets # # Internal language keywords # #region Keywords function Export-PSDocumentConvention { [CmdletBinding()] [OutputType([void])] param ( [Parameter(Position = 0, Mandatory = $True)] [String]$Name, [Parameter(Mandatory = $False)] [ScriptBlock]$Begin, [Parameter(Position = 1, Mandatory = $True)] [ScriptBlock]$Process, [Parameter(Mandatory = $False)] [ScriptBlock]$End ) begin { # This is just a stub to improve authoring and discovery Write-Error -Message $LocalizedHelp.KeywordOutsideEngine -Category InvalidOperation; } } # Implement the Document keyword function Document { [CmdletBinding()] [OutputType([void])] param ( [Parameter(Position = 0, Mandatory = $True)] [String]$Name, [Parameter(Mandatory = $False)] [String[]]$Tag, [Parameter(Position = 1, Mandatory = $True)] [ScriptBlock]$Body, [Parameter(Mandatory = $False)] [ScriptBlock]$If, [Parameter(Mandatory = $False)] [String[]]$With ) begin { # This is just a stub to improve authoring and discovery Write-Error -Message $LocalizedHelp.KeywordOutsideEngine -Category InvalidOperation; } } # Implement the Section keyword function Section { [CmdletBinding()] [OutputType([PSObject])] param ( # The name of the Section [Parameter(Position = 0, Mandatory = $True)] [String]$Name, # A script block with the body of the Section [Parameter(Position = 1, Mandatory = $True)] [ScriptBlock]$Body, # Optionally a condition that must be met prior to including the Section [Parameter(Mandatory = $False)] [Alias('When')] [ScriptBlock]$If, # Optionally create a section block even when it is empty [Parameter(Mandatory = $False)] [Switch]$Force = $False ) begin { # This is just a stub to improve authoring and discovery Write-Error -Message $LocalizedHelp.KeywordOutsideEngine -Category InvalidOperation; } } function Title { [CmdletBinding()] [OutputType([void])] param ( [Parameter(Position = 0, Mandatory = $True)] [AllowEmptyString()] [String]$Content ) begin { # This is just a stub to improve authoring and discovery Write-Error -Message $LocalizedHelp.KeywordOutsideEngine -Category InvalidOperation; } } function Code { [CmdletBinding()] [OutputType([PSDocs.Models.Code])] param ( # Body of the code block [Parameter(Position = 0, Mandatory = $True, ParameterSetName = 'Default', ValueFromPipeline = $True)] [Parameter(Position = 1, Mandatory = $True, ParameterSetName = 'InfoString', ValueFromPipeline = $True)] [ScriptBlock]$Body, [Parameter(Mandatory = $True, ParameterSetName = 'StringDefault', ValueFromPipeline = $True)] [Parameter(Mandatory = $True, ParameterSetName = 'StringInfoString', ValueFromPipeline = $True)] [String]$BodyString, # Info-string [Parameter(Position = 0, Mandatory = $True, ParameterSetName = 'InfoString')] [Parameter(Position = 0, Mandatory = $True, ParameterSetName = 'StringInfoString')] [String]$Info ) begin { # This is just a stub to improve authoring and discovery Write-Error -Message $LocalizedHelp.KeywordOutsideEngine -Category InvalidOperation; } } function Note { [CmdletBinding(DefaultParameterSetName = 'ScriptBlock')] [OutputType([PSDocs.Models.BlockQuote])] param ( [Parameter(Position = 0, Mandatory = $True, ParameterSetName = 'ScriptBlock')] [ScriptBlock]$Body, [Parameter(Mandatory = $True, ValueFromPipeline = $True, ParameterSetName = 'Text')] [String]$Text ) begin { # This is just a stub to improve authoring and discovery Write-Error -Message $LocalizedHelp.KeywordOutsideEngine -Category InvalidOperation; } } function Warning { [CmdletBinding(DefaultParameterSetName = 'ScriptBlock')] [OutputType([PSDocs.Models.BlockQuote])] param ( [Parameter(Position = 0, Mandatory = $True, ParameterSetName = 'ScriptBlock')] [ScriptBlock]$Body, [Parameter(Mandatory = $True, ValueFromPipeline = $True, ParameterSetName = 'Text')] [String]$Text ) begin { # This is just a stub to improve authoring and discovery Write-Error -Message $LocalizedHelp.KeywordOutsideEngine -Category InvalidOperation; } } function BlockQuote { [CmdletBinding()] [OutputType([PSDocs.Models.BlockQuote])] param ( [Parameter(Mandatory = $True, ValueFromPipeline = $True)] [String]$Text, [Parameter(Mandatory = $False)] [String]$Info, [Parameter(Mandatory = $False)] [String]$Title ) begin { # This is just a stub to improve authoring and discovery Write-Error -Message $LocalizedHelp.KeywordOutsideEngine -Category InvalidOperation; } } function Include { [CmdletBinding()] [OutputType([PSDocs.Models.Include])] param ( [Parameter(Position = 0, Mandatory = $True)] [String]$FileName, [Parameter(Mandatory = $False)] [String]$BaseDirectory = $PWD, [Parameter(Mandatory = $False)] [String]$Culture = $Culture, [Parameter(Mandatory = $False)] [Switch]$UseCulture = $False, [Parameter(Mandatory = $False)] [System.Collections.IDictionary]$Replace ) begin { # This is just a stub to improve authoring and discovery Write-Error -Message $LocalizedHelp.KeywordOutsideEngine -Category InvalidOperation; } } function Metadata { [CmdletBinding()] [OutputType([void])] param ( [Parameter(Position = 0, Mandatory = $True)] [AllowNull()] [System.Collections.IDictionary]$Body ) begin { # This is just a stub to improve authoring and discovery Write-Error -Message $LocalizedHelp.KeywordOutsideEngine -Category InvalidOperation; } } function Table { [CmdletBinding()] [OutputType([PSDocs.Models.Table])] param ( [Parameter(Mandatory = $False, ValueFromPipeline = $True)] [AllowNull()] [Object]$InputObject, [Parameter(Mandatory = $False, Position = 0)] [Object[]]$Property ) begin { # This is just a stub to improve authoring and discovery Write-Error -Message $LocalizedHelp.KeywordOutsideEngine -Category InvalidOperation; } } #endregion Keywords # # Helper functions # function SetOptions { [CmdletBinding()] [OutputType([PSDocs.Configuration.PSDocumentOption])] param ( [Parameter(Mandatory = $True, ValueFromPipeline = $True)] [PSDocs.Configuration.PSDocumentOption]$InputObject, # Options # Sets the Input.Format option [Parameter(Mandatory = $False)] [Alias('InputFormat')] [ValidateSet('None', 'Yaml', 'Json', 'PowerShellData', 'Detect')] [PSDocs.Configuration.InputFormat]$Format = [PSDocs.Configuration.InputFormat]::Detect, # Sets the Input.ObjectPath option [Parameter(Mandatory = $False)] [String]$InputObjectPath, # Sets the Input.PathIgnore option [Parameter(Mandatory = $False)] [String[]]$InputPathIgnore, # Sets the Markdown.Encoding option [Parameter(Mandatory = $False)] [ValidateSet('Default', 'UTF8', 'UTF7', 'Unicode', 'UTF32', 'ASCII')] [PSDocs.Configuration.MarkdownEncoding]$Encoding = 'Default', # Sets the Output.Culture option [Parameter(Mandatory = $False)] [String[]]$Culture, # Sets the Output.Path option [Parameter(Mandatory = $False)] [String]$OutputPath ) process { # Options # Sets option Input.Format if ($PSBoundParameters.ContainsKey('Format')) { $InputObject.Input.Format = $Format; } # Sets option Input.ObjectPath if ($PSBoundParameters.ContainsKey('InputObjectPath')) { $InputObject.Input.ObjectPath = $InputObjectPath; } # Sets option Input.Encoding if ($PSBoundParameters.ContainsKey('InputPathIgnore')) { $InputObject.Input.PathIgnore = $InputPathIgnore; } # Sets option Markdown.Encoding if ($PSBoundParameters.ContainsKey('Encoding')) { $InputObject.Markdown.Encoding = $Encoding; } # Sets option Output.Culture if ($PSBoundParameters.ContainsKey('Culture')) { $InputObject.Output.Culture = $Culture; } # Sets option Output.Path if ($PSBoundParameters.ContainsKey('OutputPath')) { $InputObject.Output.Path = $OutputPath; } return $InputObject; } } function InitDocumentContext { [CmdletBinding()] param () process { if ($Null -eq (Get-Variable -Name DocumentBody -Scope Script -ErrorAction SilentlyContinue)) { $Script:DocumentBody = @{ }; } } } # Get a list of document script files in the matching paths function GetSource { [CmdletBinding()] [OutputType([PSDocs.Pipeline.Source])] param ( [Parameter(Mandatory = $False)] [String[]]$Path, [Parameter(Mandatory = $False)] [String[]]$Module, [Parameter(Mandatory = $False)] [Switch]$ListAvailable, [Parameter(Mandatory = $False)] [String]$Culture, [Parameter(Mandatory = $False)] [Switch]$PreferPath = $False, [Parameter(Mandatory = $False)] [Switch]$PreferModule = $False, [Parameter(Mandatory = $True)] [PSDocs.Configuration.PSDocumentOption]$Option ) process { $builder = [PSDocs.Pipeline.PipelineBuilder]::Source($Option, $PSCmdlet, $ExecutionContext); if ($PSBoundParameters.ContainsKey('Path')) { try { $builder.Directory($Path); } catch { throw $_.Exception.GetBaseException(); } } $moduleParams = @{}; if ($PSBoundParameters.ContainsKey('Module')) { $moduleParams['Name'] = $Module; # Determine if module should be automatically loaded if (GetAutoloadPreference) { foreach ($m in $Module) { if ($Null -eq (GetModule -Name $m)) { LoadModule -Name $m -Verbose:$VerbosePreference; } } } } if ($PSBoundParameters.ContainsKey('ListAvailable')) { $moduleParams['ListAvailable'] = $ListAvailable.ToBool(); } if ($moduleParams.Count -gt 0 -or $PreferModule) { $modules = @(GetModule @moduleParams); $builder.Module($modules); } $builder.Build(); } } function GetAutoloadPreference { [CmdletBinding()] [OutputType([System.Boolean])] param () process { $v = Microsoft.PowerShell.Utility\Get-Variable -Name 'PSModuleAutoLoadingPreference' -ErrorAction SilentlyContinue; return ($Null -eq $v) -or ($v.Value -eq [System.Management.Automation.PSModuleAutoLoadingPreference]::All); } } function GetModule { [CmdletBinding()] [OutputType([System.Management.Automation.PSModuleInfo])] param ( [Parameter(Mandatory = $False)] [String[]]$Name, [Parameter(Mandatory = $False)] [Switch]$ListAvailable = $False ) process { $moduleResults = (Microsoft.PowerShell.Core\Get-Module @PSBoundParameters | Microsoft.PowerShell.Core\Where-Object -FilterScript { 'PSDocs-documents' -in $_.Tags } | Microsoft.PowerShell.Utility\Group-Object -Property Name) if ($Null -ne $moduleResults) { foreach ($m in $moduleResults) { @($m.Group | Microsoft.PowerShell.Utility\Sort-Object -Descending -Property Version)[0]; } } } } function LoadModule { [CmdletBinding()] [OutputType([void])] param ( [Parameter(Mandatory = $True)] [String]$Name ) process{ $Null = GetModule -Name $Name -ListAvailable | Microsoft.PowerShell.Core\Import-Module -Global; } } function ReadYamlHeader { [CmdletBinding()] [OutputType([System.Collections.Hashtable])] param ( [Parameter(Mandatory = $True)] [String]$Path ) process { # Read the file $content = Get-Content -Path $Path -Raw; # Detect Yaml header if (![String]::IsNullOrEmpty($content) -and $content -match '^(---(\r|\n|\r\n)(?<yaml>([A-Z0-9]{1,}:[A-Z0-9 ]{1,}(\r|\n|\r\n){0,}){1,})(\r|\n|\r\n)---(\r|\n|\r\n))') { Write-Verbose -Message "[Doc][Toc]`t-- Reading Yaml header: $Path"; # Extract yaml header key value pair [String[]]$yamlHeader = $Matches.yaml -split "`n"; $result = @{ }; # Read key values into hashtable foreach ($item in $yamlHeader) { $kv = $item.Split(':', 2, [System.StringSplitOptions]::RemoveEmptyEntries); Write-Debug -Message "Found yaml keypair from: $item"; if ($kv.Length -eq 2) { $result[$kv[0].Trim()] = $kv[1].Trim(); } } # Emit result to the pipeline return $result; } } } function IsDeviceGuardEnabled { [CmdletBinding()] [OutputType([System.Boolean])] param () process { if ((Get-Variable -Name IsMacOS -ErrorAction Ignore) -or (Get-Variable -Name IsLinux -ErrorAction Ignore)) { return $False; } # PowerShell 6.0.x does not support Device Guard if ($PSVersionTable.PSVersion -ge '6.0' -and $PSVersionTable.PSVersion -lt '6.1') { return $False; } return [System.Management.Automation.Security.SystemPolicy]::GetSystemLockdownPolicy() -eq [System.Management.Automation.Security.SystemEnforcementMode]::Enforce; } } function InitEditorServices { [CmdletBinding()] param () process { Export-ModuleMember -Function @( 'Section' 'Table' 'Metadata' 'Title' 'Code' 'BlockQuote' 'Note' 'Warning' 'Include' 'Export-PSDocumentConvention' ); # Export variables Export-ModuleMember -Variable @( 'PSDocs' ); } } # # Editor services # # Define variables and types [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignment', '', Justification = 'Variable is used for editor discovery only.')] [PSDocs.Runtime.PSDocs]$PSDocs = [PSDocs.Runtime.PSDocs]::new(); if ($Null -ne (Get-Variable -Name psEditor -ErrorAction Ignore)) { InitEditorServices; } # # Export module # Export-ModuleMember -Function @( 'Document' 'Invoke-PSDocument' 'Get-PSDocument' 'Get-PSDocumentHeader' 'New-PSDocumentOption' ); # EOM |