├── ExampleHtmlOutput.png
├── ExampleJsonOutput.png
├── ExampleTextOutput.png
├── ExampleWordOutput.png
├── PScriboExample.docx
├── Tests
├── TestImage.jpg
├── TestImage.png
├── Plugins
│ ├── Html
│ │ ├── Out-HtmlLineBreak.Tests.ps1
│ │ ├── Out-HtmlBlankLine.Tests.ps1
│ │ ├── Out-HtmlPageBreak.Tests.ps1
│ │ └── Out-HtmlStyle.Tests.ps1
│ ├── Text
│ │ ├── Out-TextImage.Tests.ps1
│ │ ├── Out-TextBlankLine.Tests.ps1
│ │ ├── Out-TextLineBreak.Tests.ps1
│ │ └── Out-TextPageBreak.Tests.ps1
│ ├── Json
│ │ ├── Out-JsonTOC.Tests.ps1
│ │ ├── Out-JsonDocument.Tests.ps1
│ │ ├── Out-JsonTable.Tests.ps1
│ │ └── Out-JsonSection.Tests.ps1
│ ├── Word
│ │ ├── ConvertTo-WordColor.Tests.ps1
│ │ ├── Out-WordPageBreak.Tests.ps1
│ │ └── Out-WordBlankLine.Tests.ps1
│ └── Xml
│ │ └── Out-XmlDocument.Tests.ps1
├── Linting
│ └── PSScriptAnalyzer.Tests.ps1
└── Unit
│ ├── Resolve-ImageUri.Tests.ps1
│ ├── Get-UriBytes.Tests.ps1
│ ├── ConvertTo-Image.Tests.ps1
│ ├── Test-PScriboStyleColor.Tests.ps1
│ ├── BlankLine.Tests.ps1
│ ├── Get-PScriboImage.Tests.ps1
│ ├── LineBreak.Tests.ps1
│ ├── PageBreak.Tests.ps1
│ ├── Image.Tests.ps1
│ └── TOC.Tests.ps1
├── Examples
├── Example31.jpg
├── Example19.ps1
├── Example14.ps1
├── Example11.ps1
├── Example20.ps1
├── Example10.ps1
├── Example22.ps1
├── Example18.ps1
├── Example24.ps1
├── Example12.ps1
├── Example13.ps1
├── Example40.ps1
├── Example07.ps1
├── Example05.ps1
├── Example44.ps1
├── Example02.ps1
├── Example30.ps1
├── Example25.ps1
├── Example17.ps1
├── Example33.ps1
├── Example23.ps1
├── Example15.ps1
├── Example03.ps1
├── Example01.ps1
├── Example28.ps1
├── Example27.ps1
├── Example16.ps1
├── Example21.ps1
├── Example29.ps1
├── Example36.ps1
├── Example06.ps1
├── Example41.ps1
├── Example42.ps1
├── Example04.ps1
├── Example39.ps1
└── Example34.ps1
├── Src
├── Plugins
│ ├── Html
│ │ ├── Out-HtmlLineBreak.ps1
│ │ ├── Out-HtmlBlankLine.ps1
│ │ ├── New-PScriboHtmlOption.ps1
│ │ ├── Out-HtmlTable.ps1
│ │ ├── Get-HtmlCanvasHeight.ps1
│ │ ├── Out-HtmlImage.ps1
│ │ ├── Get-HtmlTableCaption.ps1
│ │ ├── Get-HtmlTablePaddingStyle.ps1
│ │ ├── Get-HtmlTableColGroup.ps1
│ │ ├── Out-HtmlTOC.ps1
│ │ ├── Get-HtmlTableStyle.ps1
│ │ ├── Get-HtmlTableDiv.ps1
│ │ ├── Get-HtmlListItemInlineStyle.ps1
│ │ ├── Out-HtmlPageBreak.ps1
│ │ └── Get-HtmlStyle.ps1
│ ├── Json
│ │ ├── Out-JsonTOC.ps1
│ │ ├── Get-JsonTableCaption.ps1
│ │ ├── New-PScriboJsonOption.ps1
│ │ ├── Out-JsonTable.ps1
│ │ └── Out-JsonParagraph.ps1
│ ├── Word
│ │ ├── ConvertTo-WordColor.ps1
│ │ ├── Out-WordBlankLine.ps1
│ │ ├── Out-WordPageBreak.ps1
│ │ ├── Get-WordListLevel.ps1
│ │ ├── Out-WordLineBreak.ps1
│ │ ├── Get-WordSettingsDocument.ps1
│ │ ├── Get-WordParagraphRun.ps1
│ │ ├── Get-WordTableConditionalFormattingValue.ps1
│ │ ├── Get-WordStyleRunPr.ps1
│ │ ├── Get-WordNumberingDocument.ps1
│ │ └── Get-WordTableRenderWidthMm.ps1
│ ├── Text
│ │ ├── Out-TextBlankLine.ps1
│ │ ├── Out-TextLineBreak.ps1
│ │ ├── Out-TextPageBreak.ps1
│ │ ├── Out-Textimage.ps1
│ │ ├── Get-PScriboListItemMaximumLength.ps1
│ │ ├── Get-TextTableCaption.ps1
│ │ ├── ConvertTo-IndentedString.ps1
│ │ ├── ConvertTo-JustifiedString.ps1
│ │ ├── Out-TextParagraph.ps1
│ │ ├── Out-TextTOC.ps1
│ │ └── New-PScriboTextOption.ps1
│ └── Xml
│ │ ├── Out-XmlImage.ps1
│ │ ├── Out-XmlParagraph.ps1
│ │ └── Out-XmlTable.ps1
├── Private
│ ├── Get-PScriboPlugin.ps1
│ ├── ConvertTo-In.ps1
│ ├── Test-PScriboStyle.ps1
│ ├── ConvertTo-Pt.ps1
│ ├── Test-PScriboStyleColor.ps1
│ ├── ConvertTo-Twips.ps1
│ ├── Resolve-PScriboToken.ps1
│ ├── ConvertTo-Octips.ps1
│ ├── ConvertTo-Px.ps1
│ ├── Resolve-ImageUri.ps1
│ ├── ConvertTo-Image.ps1
│ ├── ConvertTo-InvariantCultureString.ps1
│ ├── Invoke-PScriboSection.ps1
│ ├── New-PScriboBlankLine.ps1
│ ├── New-PScriboLineBreak.ps1
│ ├── Get-PScriboDocumentStyle.ps1
│ ├── ConvertTo-Em.ps1
│ ├── New-PScriboPageBreak.ps1
│ ├── ConvertTo-PScriboPreformattedTable.ps1
│ ├── Set-PScriboSectionBreakEnd.ps1
│ ├── Write-PScriboProcessSectionId.ps1
│ ├── Get-UriBytes.ps1
│ ├── New-PScriboListReference.ps1
│ ├── Copy-Object.ps1
│ ├── New-PScriboTOC.ps1
│ ├── ConvertTo-Mm.ps1
│ ├── ConvertTo-RomanNumeral.ps1
│ ├── New-PScriboFormattedTableRowCell.ps1
│ ├── Get-PScriboImage.ps1
│ ├── ConvertTo-PSObjectKeyedListTable.ps1
│ ├── Invoke-PScriboSectionLevel.ps1
│ ├── New-PScriboHeaderFooter.ps1
│ ├── Merge-PScriboPluginOption.ps1
│ ├── Invoke-PScriboListLevel.ps1
│ ├── Get-PScriboHeaderFooter.ps1
│ ├── Get-ImageMimeType.ps1
│ ├── New-PScriboFormattedTableRow.ps1
│ ├── ConvertFrom-NumberStyle.ps1
│ └── New-PScriboParagraph.ps1
└── Public
│ ├── BlankLine.ps1
│ ├── PageBreak.ps1
│ ├── LineBreak.ps1
│ ├── TOC.ps1
│ └── Set-Style.ps1
├── en-US
├── about_PScriboPlugins.help.txt
├── about_HtmlPlugin.help.txt
├── about_WordPlugin.help.txt
├── about_PScribo.help.txt
└── about_JsonPlugin.help.txt
├── Pscribo.nuspec
├── LICENSE
├── PScribo.psm1
└── PScribo.psd1
/ExampleHtmlOutput.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iainbrighton/PScribo/HEAD/ExampleHtmlOutput.png
--------------------------------------------------------------------------------
/ExampleJsonOutput.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iainbrighton/PScribo/HEAD/ExampleJsonOutput.png
--------------------------------------------------------------------------------
/ExampleTextOutput.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iainbrighton/PScribo/HEAD/ExampleTextOutput.png
--------------------------------------------------------------------------------
/ExampleWordOutput.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iainbrighton/PScribo/HEAD/ExampleWordOutput.png
--------------------------------------------------------------------------------
/PScriboExample.docx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iainbrighton/PScribo/HEAD/PScriboExample.docx
--------------------------------------------------------------------------------
/Tests/TestImage.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iainbrighton/PScribo/HEAD/Tests/TestImage.jpg
--------------------------------------------------------------------------------
/Tests/TestImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iainbrighton/PScribo/HEAD/Tests/TestImage.png
--------------------------------------------------------------------------------
/Examples/Example31.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iainbrighton/PScribo/HEAD/Examples/Example31.jpg
--------------------------------------------------------------------------------
/Src/Plugins/Html/Out-HtmlLineBreak.ps1:
--------------------------------------------------------------------------------
1 | function Out-HtmlLineBreak
2 | {
3 | <#
4 | .SYNOPSIS
5 | Output formatted Html line break.
6 | #>
7 | [CmdletBinding()]
8 | [OutputType([System.String])]
9 | param ( )
10 | process
11 | {
12 | return '
from PScribo.Table object.
6 |
7 | .NOTES
8 | One table is output per table row with the -List parameter.
9 | #>
10 | [CmdletBinding()]
11 | [OutputType([System.String])]
12 | param
13 | (
14 | [Parameter(Mandatory, ValueFromPipeline)]
15 | [ValidateNotNull()]
16 | [System.Management.Automation.PSObject] $Table
17 | )
18 | process
19 | {
20 | [System.Text.StringBuilder] $tableBuilder = New-Object -TypeName 'System.Text.StringBuilder'
21 | $formattedTable = Get-HtmlTable -Table $Table
22 | [ref] $null = $tableBuilder.Append($formattedTable)
23 | return $tableBuilder.ToString()
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Src/Plugins/Word/Out-WordBlankLine.ps1:
--------------------------------------------------------------------------------
1 | function Out-WordBlankLine
2 | {
3 | <#
4 | .SYNOPSIS
5 | Output formatted Word xml blank line (empty paragraph).
6 | #>
7 | [CmdletBinding()]
8 | param
9 | (
10 | [Parameter(Mandatory, ValueFromPipeline)]
11 | [System.Management.Automation.PSObject] $BlankLine,
12 |
13 | [Parameter(Mandatory)]
14 | [System.Xml.XmlDocument] $XmlDocument,
15 |
16 | [Parameter(Mandatory)]
17 | [System.Xml.XmlElement] $Element
18 | )
19 | process
20 | {
21 | $xmlns = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'
22 | for ($i = 0; $i -lt $BlankLine.LineCount; $i++) {
23 | [ref] $null = $Element.AppendChild($XmlDocument.CreateElement('w', 'p', $xmlns))
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Src/Plugins/Json/Out-JsonTable.ps1:
--------------------------------------------------------------------------------
1 | function Out-JsonTable
2 | {
3 | <#
4 | .SYNOPSIS
5 | Output formatted Json table.
6 | #>
7 | [CmdletBinding()]
8 | [OutputType([System.String])]
9 | param
10 | (
11 | [Parameter(Mandatory, ValueFromPipeline)]
12 | [System.Management.Automation.PSObject] $Table
13 | )
14 | begin
15 | {
16 | ## Initializing table object
17 | $tableBuilder = [System.Collections.ArrayList]::new()
18 | }
19 | process
20 | {
21 | if ($Table.HasCaption)
22 | {
23 | [ref] $null = $tableBuilder.Add((Get-JsonTableCaption -Table $Table))
24 | }
25 |
26 | [ref] $null = $tableBuilder.Add(($Table.Rows | Select-Object -Property * -ExcludeProperty '*__Style'))
27 |
28 | return $tableBuilder
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Src/Plugins/Xml/Out-XmlImage.ps1:
--------------------------------------------------------------------------------
1 | function Out-XmlImage
2 | {
3 | <#
4 | .SYNOPSIS
5 | Output embedded Xml image.
6 | #>
7 | [CmdletBinding()]
8 | param
9 | (
10 | ## PScribo Image object
11 | [Parameter(Mandatory, ValueFromPipeline)]
12 | [ValidateNotNull()]
13 | [System.Management.Automation.PSObject] $Image
14 | )
15 | process
16 | {
17 | $imageElement = $xmlDocument.CreateElement('image')
18 | [ref] $null = $imageElement.SetAttribute('text', $Image.Text)
19 | [ref] $null = $imageElement.SetAttribute('mimeType', $Image.MimeType)
20 | $imageBase64 = [System.Convert]::ToBase64String($Image.Bytes)
21 | [ref] $null = $imageElement.AppendChild($xmlDocument.CreateTextNode($imageBase64))
22 |
23 | return $imageElement
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Src/Plugins/Html/Get-HtmlCanvasHeight.ps1:
--------------------------------------------------------------------------------
1 | function Get-HtmlCanvasHeight
2 | {
3 | <#
4 | .SYNOPSIS
5 | Calculates the usable document canvas height.
6 | #>
7 | [CmdletBinding()]
8 | param
9 | (
10 | [Parameter(Mandatory)]
11 | [System.String] $Orientation
12 | )
13 | process
14 | {
15 | if ($Orientation -eq 'Portrait')
16 | {
17 | $pageHeight = $Document.Options['PageHeight']
18 | return ($pageHeight - $Document.Options['MarginTop'] - $Document.Options['MarginBottom']) -as [System.Int32]
19 | }
20 | else
21 | {
22 | $pageHeight = $Document.Options['PageWidth']
23 | return ($pageHeight - $Document.Options['MarginTop'] - (($Document.Options['MarginBottom'] * 1.5) -as [System.Int32]))
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Tests/Unit/Get-UriBytes.Tests.ps1:
--------------------------------------------------------------------------------
1 | $here = Split-Path -Path $MyInvocation.MyCommand.Path -Parent
2 | $testRoot = Split-Path -Path $here -Parent
3 | $moduleRoot = Split-Path -Path $testRoot -Parent
4 | Import-Module -Name "$moduleRoot\PScribo.psm1" -Force
5 |
6 | InModuleScope -ModuleName 'PScribo' -ScriptBlock {
7 |
8 | $testRoot = Split-Path -Path $PSScriptRoot -Parent;
9 |
10 | Describe -Name 'Get-UriBytes' -Fixture {
11 |
12 | It "returns 'System.Byte[]' type" {
13 |
14 | $testPath = Join-Path -Path $testRoot -ChildPath 'TestImage.jpg'
15 | $testUri = Resolve-ImageUri -Path $testPath
16 |
17 | $result = Get-UriBytes -Uri $testUri
18 |
19 | $result -is [System.Object[]] | Should Be $true
20 | $result[0] -is [System.Byte] | Should Be $true
21 | }
22 |
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Src/Plugins/Text/Out-TextPageBreak.ps1:
--------------------------------------------------------------------------------
1 | function Out-TextPageBreak
2 | {
3 | <#
4 | .SYNOPSIS
5 | Output formatted line break text.
6 | #>
7 | [CmdletBinding()]
8 | [OutputType([System.String])]
9 | param ( )
10 | process
11 | {
12 | $pagebreakBuilder = New-Object -TypeName System.Text.StringBuilder
13 |
14 | $isFirstPage = $currentPageNumber -eq 1
15 | $pageFooter = Out-TextHeaderFooter -Footer -FirstPage:$isFirstPage
16 | [ref] $null = $pageBreakBuilder.Append($pageFooter)
17 |
18 | $script:currentPageNumber++
19 | [ref] $null = $pagebreakBuilder.Append((Out-TextLineBreak)).AppendLine()
20 |
21 | $pageHeader = Out-TextHeaderFooter -Header
22 | [ref] $null = $pageBreakBuilder.Append($pageHeader)
23 |
24 | return $pageBreakBuilder.ToString()
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Tests/Plugins/Html/Out-HtmlBlankLine.Tests.ps1:
--------------------------------------------------------------------------------
1 | $here = Split-Path -Path $MyInvocation.MyCommand.Path -Parent;
2 | $pluginRoot = Split-Path -Path $here -Parent;
3 | $testRoot = Split-Path -Path $pluginRoot -Parent;
4 | $moduleRoot = Split-Path -Path $testRoot -Parent;
5 | Import-Module "$moduleRoot\PScribo.psm1" -Force;
6 |
7 | InModuleScope 'PScribo' {
8 |
9 | Describe 'Plugins\Html\Out-HtmlBlankLine' {
10 |
11 | ## Scaffold new document to initialise options/styles
12 | $pscriboDocument = Document -Name 'Test' -ScriptBlock { };
13 |
14 | It 'creates a single
html tag' {
15 | BlankLine | Out-HtmlBlankLine | Should BeExactly '
'
16 | }
17 |
18 | It 'creates two
html tags' {
19 | BlankLine -Count 2 | Out-HtmlBlankLine | Should BeExactly '
'
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/Tests/Unit/ConvertTo-Image.Tests.ps1:
--------------------------------------------------------------------------------
1 | $here = Split-Path -Path $MyInvocation.MyCommand.Path -Parent
2 | $testRoot = Split-Path -Path $here -Parent
3 | $moduleRoot = Split-Path -Path $testRoot -Parent
4 | Import-Module -Name "$moduleRoot\PScribo.psm1" -Force
5 |
6 | InModuleScope -ModuleName 'PScribo' -ScriptBlock {
7 |
8 | $testRoot = Split-Path -Path $PSScriptRoot -Parent
9 |
10 | Describe -Name 'ConvertTo-Image' -Fixture {
11 |
12 | It "returns 'System.Drawing.Image' type" {
13 | $testPath = Join-Path -Path $testRoot -ChildPath 'TestImage.jpg'
14 | $testUri = Resolve-ImageUri -Path $testPath
15 | $testBytes = Get-UriBytes -Uri $testUri
16 |
17 | $result = ConvertTo-Image -Bytes $testBytes
18 |
19 | $result -is [System.Drawing.Image] | Should Be $true
20 | }
21 |
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Src/Plugins/Text/Out-Textimage.ps1:
--------------------------------------------------------------------------------
1 | function Out-TextImage
2 | {
3 | <#
4 | .SYNOPSIS
5 | Output formatted image text.
6 | #>
7 | [CmdletBinding()]
8 | [OutputType([System.String])]
9 | param
10 | (
11 | [Parameter(Mandatory, ValueFromPipeline)]
12 | [ValidateNotNull()]
13 | [System.Management.Automation.PSObject] $Image
14 | )
15 | begin
16 | {
17 | ## Fix Set-StrictMode
18 | if (-not (Test-Path -Path Variable:\Options))
19 | {
20 | $options = New-PScriboTextOption
21 | }
22 | }
23 | process
24 | {
25 | $convertToAlignedStringParams = @{
26 | InputObject = '[Image Text="{0}"]' -f $Image.Text
27 | Width = $options.TextWidth
28 | }
29 |
30 | return (ConvertTo-AlignedString @convertToAlignedStringParams)
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Src/Private/ConvertTo-Image.ps1:
--------------------------------------------------------------------------------
1 | function ConvertTo-Image
2 | {
3 | <#
4 | .SYNOPSIS
5 | Creates an image from a byte[]
6 | #>
7 | [CmdletBinding()]
8 | [OutputType([System.Drawing.Image])]
9 | param
10 | (
11 | [Parameter(Mandatory, ValueFromPipeline)]
12 | [System.Byte[]] $Bytes
13 | )
14 | process
15 | {
16 | try
17 | {
18 | [System.IO.MemoryStream] $memoryStream = New-Object -TypeName 'System.IO.MemoryStream' -ArgumentList @(,$Bytes)
19 | [System.Drawing.Image] $image = [System.Drawing.Image]::FromStream($memoryStream)
20 | Write-Output -InputObject $image
21 | }
22 | catch
23 | {
24 | $_
25 | }
26 | finally
27 | {
28 | if ($null -ne $memoryStream)
29 | {
30 | $memoryStream.Close()
31 | }
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Src/Private/ConvertTo-InvariantCultureString.ps1:
--------------------------------------------------------------------------------
1 | function ConvertTo-InvariantCultureString
2 | {
3 | <#
4 | .SYNOPSIS
5 | Convert to a number to a string with a culture-neutral representation #6, #42.
6 | #>
7 | [CmdletBinding()]
8 | param
9 | (
10 | ## The sinle/double
11 | [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
12 | [System.Object] $Object,
13 |
14 | ## Format string
15 | [Parameter(ValueFromPipelineByPropertyName)]
16 | [System.String] $Format
17 | )
18 | process
19 | {
20 | if ($PSBoundParameters.ContainsKey('Format'))
21 | {
22 | return $Object.ToString($Format, [System.Globalization.CultureInfo]::InvariantCulture);
23 | }
24 | else
25 | {
26 | return $Object.ToString([System.Globalization.CultureInfo]::InvariantCulture);
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Src/Private/Invoke-PScriboSection.ps1:
--------------------------------------------------------------------------------
1 | function Invoke-PScriboSection
2 | {
3 | <#
4 | .SYNOPSIS
5 | Processes the document/TOC section versioning each level, i.e. 1.2.2.3
6 |
7 | .NOTES
8 | This is an internal function and should not be called directly.
9 | #>
10 | [CmdletBinding()]
11 | param ( )
12 | process
13 | {
14 | $majorNumber = 1;
15 | foreach ($s in $pscriboDocument.Sections)
16 | {
17 | if ($s.Type -like '*.Section')
18 | {
19 | if ($pscriboDocument.Options['ForceUppercaseSection'])
20 | {
21 | $s.Name = $s.Name.ToUpper();
22 | }
23 | if (-not $s.IsExcluded)
24 | {
25 | Invoke-PScriboSectionLevel -Section $s -Number $majorNumber;
26 | $majorNumber++;
27 | }
28 | }
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Src/Private/New-PScriboBlankLine.ps1:
--------------------------------------------------------------------------------
1 | function New-PScriboBlankLine
2 | {
3 | <#
4 | .SYNOPSIS
5 | Initializes a new PScribo blank line break.
6 |
7 | .NOTES
8 | This is an internal function and should not be called directly.
9 | #>
10 | [CmdletBinding()]
11 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions','')]
12 | [OutputType([System.Management.Automation.PSCustomObject])]
13 | param
14 | (
15 | [Parameter(ValueFromPipeline)]
16 | [System.UInt32] $Count = 1
17 | )
18 | process
19 | {
20 | $typeName = 'PScribo.BlankLine';
21 | $pscriboDocument.Properties['BlankLines']++;
22 | $pscriboBlankLine = [PSCustomObject] @{
23 | Id = [System.Guid]::NewGuid().ToString();
24 | LineCount = $Count;
25 | Type = $typeName;
26 | }
27 | return $pscriboBlankLine;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Src/Private/New-PScriboLineBreak.ps1:
--------------------------------------------------------------------------------
1 | function New-PScriboLineBreak
2 | {
3 | <#
4 | .SYNOPSIS
5 | Initializes a new PScribo line break object.
6 |
7 | .NOTES
8 | This is an internal function and should not be called directly.
9 | #>
10 | [CmdletBinding()]
11 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions','')]
12 | [OutputType([System.Management.Automation.PSCustomObject])]
13 | param
14 | (
15 | [Parameter(Position = 0)]
16 | [ValidateNotNullOrEmpty()]
17 | [System.String] $Id = [System.Guid]::NewGuid().ToString()
18 | )
19 | process
20 | {
21 | $typeName = 'PScribo.LineBreak';
22 | $pscriboDocument.Properties['LineBreaks']++;
23 | $pscriboLineBreak = [PSCustomObject] @{
24 | Id = $Id;
25 | Type = $typeName;
26 | }
27 | return $pscriboLineBreak;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Src/Private/Get-PScriboDocumentStyle.ps1:
--------------------------------------------------------------------------------
1 | function Get-PScriboDocumentStyle
2 | {
3 | <#
4 | .SYNOPSIS
5 | Returns document style or table style.
6 |
7 | .NOTES
8 | Enables testing without having to generate a mock document object!
9 | #>
10 | [CmdletBinding()]
11 | param
12 | (
13 | [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName, ParameterSetName = 'Style')]
14 | [System.String] $Style,
15 |
16 | [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName, ParameterSetName = 'TableStyle')]
17 | [System.String] $TableStyle
18 | )
19 | process
20 | {
21 | if ($PSCmdlet.ParameterSetName -eq 'Style')
22 | {
23 | return $Document.Styles[$Style]
24 | }
25 | elseif ($PSCmdlet.ParameterSetName -eq 'TableStyle')
26 | {
27 | return $Document.TableStyles[$TableStyle]
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Src/Private/ConvertTo-Em.ps1:
--------------------------------------------------------------------------------
1 | function ConvertTo-Em
2 | {
3 | <#
4 | .SYNOPSIS
5 | Convert pixels or millimeters into EMU
6 | #>
7 | [CmdletBinding()]
8 | [OutputType([System.Single])]
9 | param
10 | (
11 | [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'Pixel')]
12 | [Alias('px')]
13 | [System.Single] $Pixel,
14 |
15 | [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'Millimeter')]
16 | [Alias('mm','Millimetre')]
17 | [System.Single] $Millimeter
18 | )
19 | process
20 | {
21 | if ($PSCmdlet.ParameterSetName -eq 'Pixel')
22 | {
23 | $em = $pixel * 9525
24 | return [System.Math]::Round($em, 0)
25 | }
26 | elseif ($PSCmdlet.ParameterSetName -eq 'Millimeter')
27 | {
28 | $em = $Millimeter / 4.23333333333333
29 | return [System.Math]::Round($em, 2)
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Examples/Example19.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding()]
2 | param (
3 | [System.String[]] $Format = 'Html',
4 | [System.String] $Path = '~\Desktop',
5 | [System.Management.Automation.SwitchParameter] $PassThru
6 | )
7 |
8 | Import-Module PScribo -Force -Verbose:$false
9 |
10 | $example19 = Document -Name 'PScribo Example 19' {
11 |
12 | <#
13 | Column widths can also be specified on -List tables. The total of the
14 | column widths must still total 100 (%), but only 2 widths are supported.
15 |
16 | NOTE: -List view also supports the standard 'Table' -Width parameter.
17 |
18 | The following example creates a table for the first 5 services
19 | registered on the local machine, and sets the first (property) column
20 | to 40% and the second (value) column to 60%.
21 | #>
22 | Get-Service | Select-Object -First 5 | Table -List -ColumnWidths 40,60
23 | }
24 | $example19 | Export-Document -Path $Path -Format $Format -PassThru:$PassThru
25 |
--------------------------------------------------------------------------------
/Examples/Example14.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding()]
2 | param (
3 | [System.String[]] $Format = 'Html',
4 | [System.String] $Path = '~\Desktop',
5 | [System.Management.Automation.SwitchParameter] $PassThru
6 | )
7 |
8 | Import-Module PScribo -Force -Verbose:$false
9 |
10 | $example14 = Document -Name 'PScribo Example 14' {
11 |
12 | <#
13 | By default, tables are configured to use 100% of available width. You can
14 | override the table width, by specifying the -Width parameter on the 'Table'
15 | cmdlet. The width is always set as a percentage of available space between
16 | the left and right page margins (adjusting for indentation).
17 |
18 | The following example creates a table with its with set at 66% of the available
19 | space.
20 | #>
21 | Get-Service | Table -Columns Name,DisplayName,Status -Headers 'Name','Display Name','State' -Width 66
22 | }
23 | $example14 | Export-Document -Path $Path -Format $Format -PassThru:$PassThru
24 |
--------------------------------------------------------------------------------
/Pscribo.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | pscribo
5 | PScribo
6 | 0.0.0
7 | Iain Brighton
8 | Virtual Engine
9 | PScribo documentation Powershell module/framework.
10 | PScribo is a documentation domain-specific language (DSL) for PowerShell, used to create a 'document' in a standardised format.
11 | http://github.com/iainbrighton/PScribo
12 | (c) 2025 Iain Brighton. All rights reserved.
13 | MIT
14 | false
15 | VirtualEngine PScribo Powershell Documentation Framework Virtual Engine Word Html
16 |
17 |
18 |
--------------------------------------------------------------------------------
/Src/Private/New-PScriboPageBreak.ps1:
--------------------------------------------------------------------------------
1 | function New-PScriboPageBreak
2 | {
3 | <#
4 | .SYNOPSIS
5 | Creates a PScribo page break object.
6 |
7 | .NOTES
8 | This is an internal function and should not be called directly.
9 | #>
10 | [CmdletBinding()]
11 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions','')]
12 | [OutputType([System.Management.Automation.PSCustomObject])]
13 | param
14 | (
15 | [Parameter(Position = 0)]
16 | [ValidateNotNullOrEmpty()]
17 | [System.String] $Id = [System.Guid]::NewGuid().ToString()
18 | )
19 | process
20 | {
21 | $typeName = 'PScribo.PageBreak';
22 | $pscriboDocument.Properties['PageBreaks']++;
23 | $pscriboDocument.Properties['Pages']++;
24 | $pscriboPageBreak = [PSCustomObject] @{
25 | Id = $Id;
26 | Type = $typeName;
27 | }
28 | return $pscriboPageBreak;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Src/Plugins/Word/Out-WordPageBreak.ps1:
--------------------------------------------------------------------------------
1 | function Out-WordPageBreak
2 | {
3 | <#
4 | .SYNOPSIS
5 | Output formatted Word page break.
6 | #>
7 | [CmdletBinding()]
8 | [OutputType([System.Xml.XmlElement])]
9 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter','PageBreak')]
10 | param
11 | (
12 | [Parameter(Mandatory, ValueFromPipeline)]
13 | [System.Management.Automation.PSObject] $PageBreak,
14 |
15 | [Parameter(Mandatory)]
16 | [System.Xml.XmlDocument] $XmlDocument
17 | )
18 | process
19 | {
20 | $xmlns = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'
21 | $p = $XmlDocument.CreateElement('w', 'p', $xmlns)
22 | $r = $p.AppendChild($XmlDocument.CreateElement('w', 'r', $xmlns))
23 | $br = $r.AppendChild($XmlDocument.CreateElement('w', 'br', $xmlns))
24 | [ref] $null = $br.SetAttribute('type', $xmlns, 'page')
25 |
26 | return $p
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Src/Plugins/Html/Out-HtmlImage.ps1:
--------------------------------------------------------------------------------
1 | function Out-HtmlImage
2 | {
3 | <#
4 | .SYNOPSIS
5 | Output embedded Html image.
6 | #>
7 | [CmdletBinding()]
8 | param
9 | (
10 | ## PScribo Image object
11 | [Parameter(Mandatory, ValueFromPipeline)]
12 | [ValidateNotNull()]
13 | [System.Management.Automation.PSObject] $Image
14 | )
15 | process
16 | {
17 | [System.Text.StringBuilder] $imageBuilder = New-Object -TypeName 'System.Text.StringBuilder'
18 | [ref] $null = $imageBuilder.AppendFormat('', $Image.Align).AppendLine()
19 | $imageBase64 = [System.Convert]::ToBase64String($Image.Bytes)
20 | [ref] $null = $imageBuilder.AppendFormat('

', $Image.MimeType, $imageBase64, $Image.Text, $Image.Height, $Image.Width).AppendLine()
21 | [ref] $null = $imageBuilder.AppendLine('
')
22 | return $imageBuilder.ToString()
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Tests/Plugins/Text/Out-TextBlankLine.Tests.ps1:
--------------------------------------------------------------------------------
1 | $here = Split-Path -Path $MyInvocation.MyCommand.Path -Parent;
2 | $pluginRoot = Split-Path -Path $here -Parent;
3 | $testRoot = Split-Path -Path $pluginRoot -Parent;
4 | $moduleRoot = Split-Path -Path $testRoot -Parent;
5 | Import-Module "$moduleRoot\PScribo.psm1" -Force;
6 |
7 | InModuleScope 'PScribo' {
8 |
9 | Describe 'Plugins\Text\Out-TextBlankLine' {
10 |
11 | ## Scaffold document options
12 | $pscriboDocument = Document -Name 'TestDocument' -ScriptBlock {};
13 |
14 | It 'Defaults to a single blank line' {
15 | $expected = [System.Environment]::NewLine
16 |
17 | $l = BlankLine | Out-TextBlankLine
18 |
19 | $l | Should Be $expected
20 | }
21 |
22 | It 'Creates 3 blank lines' {
23 | $expected = '{0}{0}{0}' -f [System.Environment]::NewLine
24 |
25 | $l = BlankLine -Count 3 | Out-TextBlankLine
26 |
27 | $l | Should Be $expected
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Tests/Unit/Test-PScriboStyleColor.Tests.ps1:
--------------------------------------------------------------------------------
1 | $here = Split-Path -Path $MyInvocation.MyCommand.Path -Parent;
2 | $testRoot = Split-Path -Path $here -Parent;
3 | $moduleRoot = Split-Path -Path $testRoot -Parent;
4 | Import-Module "$moduleRoot\PScribo.psm1" -Force;
5 |
6 | InModuleScope 'PScribo' {
7 |
8 | Describe 'Test-PScriboStyleColor' {
9 |
10 | It 'tests valid html color code' {
11 | Test-PscriboStyleColor -Color '012345' | Should Be $true
12 | Test-PscriboStyleColor -Color '#012345' | Should Be $true
13 | Test-PscriboStyleColor -Color '#D3D' | Should Be $true
14 | Test-PscriboStyleColor -Color D3D | Should Be $true
15 | }
16 |
17 | It 'tests invalid length html color code' {
18 | Test-PscriboStyleColor -Color abcd | Should Be $false
19 | Test-PscriboStyleColor -Color 1abcdef | Should Be $false
20 | }
21 |
22 | It 'tests invalid html color code' {
23 | Test-PscriboStyleColor -Color ghi | Should Be $false
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Src/Private/ConvertTo-PScriboPreformattedTable.ps1:
--------------------------------------------------------------------------------
1 | function ConvertTo-PScriboPreformattedTable
2 | {
3 | <#
4 | .SYNOPSIS
5 | Creates a formatted table based upon table type for plugin output/rendering.
6 |
7 | .NOTES
8 | Maintains backwards compatibility with other plugins that do not require styling/formatting.
9 | #>
10 | [CmdletBinding()]
11 | [OutputType([System.Management.Automation.PSObject])]
12 | param
13 | (
14 | [Parameter(Mandatory, ValueFromPipeline)]
15 | [System.Management.Automation.PSObject] $Table
16 | )
17 | process
18 | {
19 | if ($Table.IsKeyedList)
20 | {
21 | Write-Output -InputObject (ConvertTo-PScriboFormattedKeyedListTable -Table $Table)
22 | }
23 | elseif ($Table.IsList)
24 | {
25 | Write-Output -InputObject (ConvertTo-PScriboFormattedListTable -Table $Table)
26 | }
27 | else
28 | {
29 | Write-Output -InputObject (ConvertTo-PScriboFormattedTable -Table $Table)
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Examples/Example11.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding()]
2 | param (
3 | [System.String[]] $Format = 'Html',
4 | [System.String] $Path = '~\Desktop',
5 | [System.Management.Automation.SwitchParameter] $PassThru
6 | )
7 |
8 | Import-Module PScribo -Force -Verbose:$false
9 |
10 | $example11 = Document -Name 'PScribo Example 11' {
11 |
12 | <#
13 | As the 'Table' keyword supports pipeline input, you can use the standard
14 | Powershell 'Sort-Object', 'Group-Object', 'Select-Object' and 'Where-Object'
15 | cmdlets etc. to filter, sort and/or group the input into the 'Table' cmdlet.
16 |
17 | The following example creates a table of services, displaying the service
18 | names, display names and service statuses.
19 |
20 | NOTE: Due the the length of the table cell content, text output may be
21 | truncated due to limitations/implementation of the 'Format-Table' cmdlet.
22 | #>
23 | Get-Service | Select-Object Name,DisplayName,Status | Table
24 | }
25 | $example11 | Export-Document -Path $Path -Format $Format -PassThru:$PassThru
26 |
--------------------------------------------------------------------------------
/Src/Plugins/Text/Get-PScriboListItemMaximumLength.ps1:
--------------------------------------------------------------------------------
1 | function Get-PScriboListItemMaximumLength
2 | {
3 | <#
4 | .SYNOPSIS
5 | Renders a List's item numbers to determine the maximum string/render width.
6 | #>
7 | [CmdletBinding()]
8 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter','NumberStyle')]
9 | param
10 | (
11 | [Parameter(Mandatory, ValueFromPipeline)]
12 | [System.Management.Automation.PSObject] $List,
13 |
14 | [Parameter(Mandatory, ValueFromPipelineByPropertyName)]
15 | [System.Management.Automation.PSObject] $NumberStyle
16 | )
17 | process
18 | {
19 | $List.Items |
20 | Where-Object { $_.Type -eq 'PScribo.Item' } |
21 | ForEach-Object {
22 | $number = ConvertFrom-NumberStyle -Value $_.Index -NumberStyle $numberStyle
23 | Write-Output -InputObject $number.Length
24 | } |
25 | Measure-Object -Maximum |
26 | Select-Object -ExpandProperty Maximum
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Tests/Unit/BlankLine.Tests.ps1:
--------------------------------------------------------------------------------
1 | $here = Split-Path -Path $MyInvocation.MyCommand.Path -Parent;
2 | $testRoot = Split-Path -Path $here -Parent;
3 | $moduleRoot = Split-Path -Path $testRoot -Parent;
4 | Import-Module "$moduleRoot\PScribo.psm1" -Force;
5 |
6 | InModuleScope 'PScribo' {
7 |
8 | Describe 'BlankLine' {
9 | $pscriboDocument = Document 'ScaffoldDocument' {}
10 |
11 | It 'returns a PSCustomObject object' {
12 | $b = BlankLine
13 |
14 | $b.GetType().Name | Should Be 'PSCustomObject'
15 | }
16 |
17 | It 'creates a PScribo.BlankLine type' {
18 | $b = BlankLine
19 |
20 | $b.Type | Should Be 'PScribo.BlankLine'
21 | }
22 |
23 | It 'creates blank line with no parameters' {
24 | $b = BlankLine
25 |
26 | $b.LineCount | Should Be 1
27 | }
28 |
29 | It 'creates blank line by named -Count parameter' {
30 | $count = 2
31 |
32 | $b = BlankLine -Count $count
33 |
34 | $b.LineCount | Should Be $count
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Src/Private/Set-PScriboSectionBreakEnd.ps1:
--------------------------------------------------------------------------------
1 | function Set-PScriboSectionBreakEnd
2 | {
3 | <#
4 | .SYNOPSIS
5 | Sets the IsSectionBreakEnd on the last (nested) paragraph/subsection (required by Word plugin)
6 | #>
7 | [CmdletBinding()]
8 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions','')]
9 | param
10 | (
11 | [Parameter(Mandatory, ValueFromPipeline)]
12 | [System.Management.Automation.PSObject] $Section
13 | )
14 | process
15 | {
16 | $Section.Sections |
17 | Where-Object { $_.Type -in 'PScribo.Section','PScribo.Paragraph','PScribo.Table' } |
18 | Select-Object -Last 1 | ForEach-Object {
19 | if ($PSItem.Type -in 'PScribo.Paragraph','PScribo.Table')
20 | {
21 | $PSItem.IsSectionBreakEnd = $true
22 | }
23 | else
24 | {
25 | Set-PScriboSectionBreakEnd -Section $PSItem
26 | }
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Src/Plugins/Text/Get-TextTableCaption.ps1:
--------------------------------------------------------------------------------
1 | function Get-TextTableCaption
2 | {
3 | <#
4 | .SYNOPSIS
5 | Generates html caption from a PScribo.Table object.
6 | #>
7 | [CmdletBinding()]
8 | [OutputType([System.String])]
9 | param
10 | (
11 | [Parameter(Mandatory, ValueFromPipeline)]
12 | [ValidateNotNull()]
13 | [System.Management.Automation.PSObject] $Table
14 | )
15 | begin
16 | {
17 | ## Fix Set-StrictMode
18 | if (-not (Test-Path -Path Variable:\Options))
19 | {
20 | $options = New-PScriboTextOption;
21 | }
22 | }
23 | process
24 | {
25 | $tableStyle = Get-PScriboDocumentStyle -TableStyle $Table.Style
26 | $convertToAlignedStringParams = @{
27 | InputObject = '{0} {1} {2}' -f $tableStyle.CaptionPrefix, $Table.CaptionNumber, $Table.Caption
28 | Width = $options.TextWidth
29 | Tabs = $Table.Tabs
30 | Align = $tableStyle.Align
31 | }
32 | return (ConvertTo-AlignedString @convertToAlignedStringParams)
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Examples/Example20.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding()]
2 | param (
3 | [System.String[]] $Format = 'Html',
4 | [System.String] $Path = '~\Desktop',
5 | [System.Management.Automation.SwitchParameter] $PassThru
6 | )
7 |
8 | Import-Module PScribo -Force -Verbose:$false
9 |
10 | $example20 = Document -Name 'PScribo Example 20' {
11 |
12 | <#
13 | Hashtables can also be used in -List view along with the -Width
14 | and -ColumnWidths parameters.
15 |
16 | The following example creates three tables (one per hashtable) in -List
17 | view, from a collection of manually constructed hashtables
18 | #>
19 | $hashtableArray = @(
20 | [Ordered] @{ 'Column 1' = 'Some random text'; 'Column2' = 345; 'Custom Property' = $true; }
21 | [Ordered] @{ 'Column 1' = 'Random some text'; 'Column2' = 16; 'Custom Property' = $false; }
22 | [Ordered] @{ 'Column 1' = 'Text random some'; 'Column2' = 1GB; 'Custom Property' = $true; }
23 | )
24 | Table -Hashtable $hashtableArray -Width 50 -ColumnWidths 40,60 -List
25 | }
26 | $example20 | Export-Document -Path $Path -Format $Format -PassThru:$PassThru
27 |
--------------------------------------------------------------------------------
/Src/Plugins/Json/Out-JsonParagraph.ps1:
--------------------------------------------------------------------------------
1 | function Out-JsonParagraph
2 | {
3 | <#
4 | .SYNOPSIS
5 | Output formatted paragraph run.
6 | #>
7 | [CmdletBinding()]
8 | [OutputType([System.String])]
9 | param
10 | (
11 | [Parameter(Mandatory, ValueFromPipeline)]
12 | [ValidateNotNull()]
13 | [System.Management.Automation.PSObject] $Paragraph
14 | )
15 | begin
16 | {
17 | ## Initializing string object
18 | [System.Text.StringBuilder] $paragraphBuilder = New-Object -TypeName 'System.Text.StringBuilder'
19 | }
20 | process
21 | {
22 | foreach ($paragraphRun in $Paragraph.Sections)
23 | {
24 | $text = Resolve-PScriboToken -InputObject $paragraphRun.Text
25 | [ref] $null = $paragraphBuilder.Append($text)
26 |
27 | if (($paragraphRun.IsParagraphRunEnd -eq $false) -and
28 | ($paragraphRun.NoSpace -eq $false))
29 | {
30 | [ref] $null = $paragraphBuilder.Append(' ')
31 | }
32 | }
33 |
34 |
35 | return $paragraphBuilder.ToString()
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2025 Iain Brighton
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Src/Private/Write-PScriboProcessSectionId.ps1:
--------------------------------------------------------------------------------
1 | function Write-PScriboProcessSectionId
2 | {
3 | [CmdletBinding()]
4 | param
5 | (
6 | [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
7 | [System.String] $SectionId,
8 |
9 | [Parameter(Mandatory, ValueFromPipelineByPropertyName)]
10 | [System.String] $SectionType,
11 |
12 | [Parameter(ValueFromPipelineByPropertyName)]
13 | [System.Int32] $Length = 40,
14 |
15 | [Parameter(ValueFromPipelineByPropertyName)]
16 | [System.Int32] $Indent = 0
17 | )
18 | process
19 | {
20 | if ($SectionId.Length -gt $Length)
21 | {
22 | $sectionDisplayName = '{0}[..]' -f $SectionId.Substring(0, ($Length -4))
23 | }
24 | else
25 | {
26 | $sectionDisplayName = $SectionId
27 | }
28 |
29 | $writePScriboMessageParams = @{
30 | Message = $localized.PluginProcessingSection -f $SectionType, $sectionDisplayName
31 | Indent = $Indent
32 | }
33 | Write-PScriboMessage @writePScriboMessageParams
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Tests/Plugins/Json/Out-JsonTOC.Tests.ps1:
--------------------------------------------------------------------------------
1 | $here = Split-Path -Path $MyInvocation.MyCommand.Path -Parent;
2 | $pluginRoot = Split-Path -Path $here -Parent;
3 | $testRoot = Split-Path -Path $pluginRoot -Parent;
4 | $moduleRoot = Split-Path -Path $testRoot -Parent;
5 | Import-Module "$moduleRoot\PScribo.psm1" -Force;
6 |
7 | InModuleScope 'PScribo' {
8 |
9 | Describe 'Plugins\Json\Out-JsonTOC' {
10 |
11 | ## Section numbering is ignored and used regardless
12 |
13 | It 'outputs TOC' {
14 | $tocName = 'Table of contents'
15 | $heading1 = 'Heading 1'
16 | $heading2 = 'Heading 2'
17 | $Document = Document -Name 'TestDocument' -ScriptBlock {
18 | TOC -Name $tocName
19 | Section $heading1 -Style Heading1 {
20 | Section $heading2 -Style Heading2 { }
21 | }
22 | }
23 | $expected = '{{.*"{0}".*"{1}"}}' -f $heading1, $heading2
24 |
25 | $result = Out-JsonTOC | ConvertTo-Json -Depth 100 -Compress
26 |
27 | $result | Should MatchExactly $expected
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Tests/Plugins/Word/ConvertTo-WordColor.Tests.ps1:
--------------------------------------------------------------------------------
1 | $here = Split-Path -Path $MyInvocation.MyCommand.Path -Parent;
2 | $pluginsRoot = Split-Path -Path $here -Parent;
3 | $testRoot = Split-Path -Path $pluginsRoot -Parent;
4 | $moduleRoot = Split-Path -Path $testRoot -Parent;
5 | Import-Module "$moduleRoot\PScribo.psm1" -Force;
6 |
7 | InModuleScope 'PScribo' {
8 |
9 | Describe 'Plugins\Word\ConvertTo-WordColor' {
10 |
11 | It 'converts to "abcdef" to "ABCDEF"' {
12 | $result = ConvertTo-WordColor 'abcdef'
13 |
14 | $result | Should BeExactly 'ABCDEF'
15 | }
16 |
17 | It 'converts "#abcdef" to "ABCDEF"' {
18 | $result = ConvertTo-WordColor '#abcdef'
19 |
20 | $result | Should BeExactly 'ABCDEF'
21 | }
22 |
23 | It 'converts "abc" to "AABBCC"' {
24 | $result = ConvertTo-WordColor 'abc'
25 |
26 | $result | Should BeExactly 'AABBCC'
27 | }
28 |
29 | It 'converts "#abc" to "AABBCC"' {
30 | $result = ConvertTo-WordColor '#abc'
31 |
32 | $result | Should BeExactly 'AABBCC'
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Tests/Unit/Get-PScriboImage.Tests.ps1:
--------------------------------------------------------------------------------
1 | $here = Split-Path -Path $MyInvocation.MyCommand.Path -Parent
2 | $testRoot = Split-Path -Path $here -Parent
3 | $moduleRoot = Split-Path -Path $testRoot -Parent
4 | Import-Module -Name "$moduleRoot\PScribo.psm1" -Force
5 |
6 | InModuleScope -ModuleName 'PScribo' -ScriptBlock {
7 |
8 | $testRoot = Split-Path -Path $PSScriptRoot -Parent
9 |
10 | Describe -Name 'Get-PScriboImage' -Fixture {
11 |
12 | $pscriboDocument = Document -Name 'ScaffoldDocument' -ScriptBlock {
13 | Image -Path (Join-Path -Path $testRoot -ChildPath 'TestImage.jpg') -Id 1
14 | Section Nested {
15 | Image -Path (Join-Path -Path $testRoot -ChildPath 'TestImage.png') -Id 2
16 | }
17 | }
18 |
19 | It 'finds all Images' {
20 | $result = Get-PScriboImage -Section $pscriboDocument.Sections
21 |
22 | $result.Count | Should Be 2
23 | }
24 |
25 | It 'finds Image by Id' {
26 | $result = @(Get-PScriboImage -Section $pscriboDocument.Sections -Id 2)
27 |
28 | $result.Count | Should Be 1
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Examples/Example10.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding()]
2 | param (
3 | [System.String[]] $Format = 'Html',
4 | [System.String] $Path = '~\Desktop',
5 | [System.Management.Automation.SwitchParameter] $PassThru
6 | )
7 |
8 | Import-Module PScribo -Force -Verbose:$false
9 |
10 | $example10 = Document -Name 'PScribo Example 10' {
11 |
12 | <#
13 | PScribo supports insertion of tables into a document. In it's simplest form, a
14 | collection of objects can be added to a document by using the 'Table' cmdlet. By
15 | default, a table is created the full width (100%) of the document, with each
16 | column width being equally distributed.
17 |
18 | The following examples creates a table of all properties on all services.
19 |
20 | NOTE: Due the the vast number of properties, the table will not render in any
21 | meaningful way! Text output may also be truncated due to limitations/
22 | implementation of the 'Format-Table' cmdlet.
23 | #>
24 | Table -InputObject (Get-Service | Select-Object -First 100)
25 | }
26 | $example10 | Export-Document -Path $Path -Format $Format -PassThru:$PassThru
27 |
--------------------------------------------------------------------------------
/Examples/Example22.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding()]
2 | param (
3 | [System.String[]] $Format = 'Html',
4 | [System.String] $Path = '~\Desktop',
5 | [System.Management.Automation.SwitchParameter] $PassThru
6 | )
7 |
8 | Import-Module PScribo -Force -Verbose:$false
9 |
10 | $example22 = Document -Name 'PScribo Example 22' {
11 |
12 | <#
13 | A grid can be applied to a table by setting the -BorderWidth property. The
14 | border width is specified in points (pt).
15 |
16 | NOTE: Table borders apply to both standard tables and -List view tables.
17 |
18 | Optionally, you may set a border/grid color with the -BorderColor property.
19 | If the border color is not specified, it will default to black (#000).
20 |
21 | The following example creates a table with an orange/red grid/border around
22 | all cells.
23 | #>
24 | TableStyle -Name 'BasicGrid' -HeaderStyle Normal -RowStyle Normal -BorderWidth 1 -BorderColor OrangeRed
25 | Get-Service | Select-Object -Property Name,DisplayName,Status -First 3 | Table -Style BasicGrid
26 | }
27 | $example22 | Export-Document -Path $Path -Format $Format -PassThru:$PassThru
28 |
--------------------------------------------------------------------------------
/Src/Plugins/Html/Get-HtmlTableCaption.ps1:
--------------------------------------------------------------------------------
1 | function Get-HtmlTableCaption
2 | {
3 | <#
4 | .SYNOPSIS
5 | Generates html
caption from a PScribo.Table object.
6 | #>
7 | [CmdletBinding()]
8 | [OutputType([System.String])]
9 | param
10 | (
11 | [Parameter(Mandatory, ValueFromPipeline)]
12 | [ValidateNotNull()]
13 | [System.Management.Automation.PSObject] $Table
14 | )
15 | process
16 | {
17 | $tableStyle = Get-PScriboDocumentStyle -TableStyle $Table.Style
18 |
19 | ## Scaffold paragraph and paragraph run for table caption
20 | $paragraphId = '{0}{1}' -f $tableStyle.CaptionPrefix, $Table.Number
21 | $paragraph = New-PScriboParagraph -Id $paragraphId -Style $tableStyle.CaptionStyle -NoIncrementCounter
22 | $paragraphRunText = '{0} {1} {2}' -f $tableStyle.CaptionPrefix, $Table.CaptionNumber, $Table.Caption
23 | $paragraphRun = New-PScriboParagraphRun -Text $paragraphRunText
24 | $paragraphRun.IsParagraphRunEnd = $true
25 | [ref] $null = $paragraph.Sections.Add($paragraphRun)
26 |
27 | return (Out-HtmlParagraph -Paragraph $paragraph)
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Src/Private/Get-UriBytes.ps1:
--------------------------------------------------------------------------------
1 | function Get-UriBytes
2 | {
3 | <#
4 | .SYNOPSIS
5 | Gets an image's content as a byte[]
6 | #>
7 | [CmdletBinding()]
8 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns','')]
9 | [OutputType([System.Byte[]])]
10 | param
11 | (
12 | [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
13 | [System.Uri] $Uri
14 | )
15 | process
16 | {
17 | try
18 | {
19 | $webClient = New-Object -TypeName 'System.Net.WebClient'
20 | [System.IO.Stream] $contentStream = $webClient.OpenRead($uri.AbsoluteUri)
21 | [System.IO.MemoryStream] $memoryStream = New-Object System.IO.MemoryStream
22 | $contentStream.CopyTo($memoryStream)
23 | return $memoryStream.ToArray()
24 | }
25 | catch
26 | {
27 | $_
28 | }
29 | finally
30 | {
31 | if ($null -ne $memoryStream) { $memoryStream.Close() }
32 | if ($null -ne $contentStream) { $contentStream.Close() }
33 | if ($null -ne $webClient) { $webClient.Dispose() }
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Src/Plugins/Html/Get-HtmlTablePaddingStyle.ps1:
--------------------------------------------------------------------------------
1 | function Get-HtmlTablePaddingStyle
2 | {
3 | <#
4 | .SYNOPSIS
5 | Generates html stylesheet style padding attributes from a PScribo document table style.
6 | #>
7 | [CmdletBinding()]
8 | [OutputType([System.String])]
9 | param
10 | (
11 | ## PScribo document table style
12 | [Parameter(Mandatory, ValueFromPipeline)]
13 | [System.Management.Automation.PSObject] $TableStyle
14 | )
15 | process
16 | {
17 | $tableStyleBuilder = New-Object -TypeName 'System.Text.StringBuilder'
18 | [ref] $null = $tableStyleBuilder.AppendFormat(' padding: {0}rem {1}rem {2}rem {3}rem;',
19 | (ConvertTo-InvariantCultureString -Object (ConvertTo-Em -Millimeter $TableStyle.PaddingTop)),
20 | (ConvertTo-InvariantCultureString -Object (ConvertTo-Em -Millimeter $TableStyle.PaddingRight)),
21 | (ConvertTo-InvariantCultureString -Object (ConvertTo-Em -Millimeter $TableStyle.PaddingBottom)),
22 | (ConvertTo-InvariantCultureString -Object (ConvertTo-Em -Millimeter $TableStyle.PaddingLeft)))
23 | return $tableStyleBuilder.ToString()
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Src/Plugins/Text/ConvertTo-IndentedString.ps1:
--------------------------------------------------------------------------------
1 | function ConvertTo-IndentedString
2 | {
3 | <#
4 | .SYNOPSIS
5 | Indents a block of text using the number of tab stops.
6 | #>
7 | [CmdletBinding()]
8 | [OutputType([System.String])]
9 | param
10 | (
11 | [Parameter(Mandatory, ValueFromPipeline)]
12 | [ValidateNotNull()]
13 | [Object[]] $InputObject,
14 |
15 | ## Tab indent
16 | [Parameter()]
17 | [ValidateRange(0,10)]
18 | [System.Int32] $Tabs = 0,
19 |
20 | ## Tab size
21 | [Parameter()]
22 | [ValidateRange(0,10)]
23 | [System.Int32] $TabSize = 4
24 | )
25 | process
26 | {
27 | $padding = ''.PadRight(($Tabs * $TabSize), ' ')
28 | ## Use a StringBuilder to write the table line by line (to indent it)
29 | [System.Text.StringBuilder] $builder = New-Object System.Text.StringBuilder
30 |
31 | foreach ($line in ($InputObject -split '\r\n?|\n'))
32 | {
33 | [ref] $null = $builder.Append($padding)
34 | [ref] $null = $builder.AppendLine($line.TrimEnd()) ## Trim trailing space (#67)
35 | }
36 | return $builder.ToString()
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Src/Plugins/Xml/Out-XmlParagraph.ps1:
--------------------------------------------------------------------------------
1 | function Out-XmlParagraph
2 | {
3 | <#
4 | .SYNOPSIS
5 | Output formatted Xml paragraph run.
6 | #>
7 | [CmdletBinding()]
8 | param
9 | (
10 | ## PScribo paragraph object
11 | [Parameter(Mandatory, ValueFromPipeline)]
12 | [ValidateNotNull()]
13 | [System.Management.Automation.PSObject] $Paragraph
14 | )
15 | process
16 | {
17 | [System.Text.StringBuilder] $paragraphBuilder = New-Object -TypeName 'System.Text.StringBuilder'
18 | foreach ($paragraphRun in $Paragraph.Sections)
19 | {
20 |
21 | $text = Resolve-PScriboToken -InputObject $paragraphRun.Text
22 | [ref] $null = $paragraphBuilder.Append($text)
23 |
24 | if (($paragraphRun.IsParagraphRunEnd -eq $false) -and
25 | ($paragraphRun.NoSpace -eq $false))
26 | {
27 | [ref] $null = $paragraphBuilder.Append(' ')
28 | }
29 | }
30 |
31 | $paragraphElement = $xmlDocument.CreateElement('paragraph')
32 | [ref] $null = $paragraphElement.AppendChild($xmlDocument.CreateTextNode($paragraphBuilder.ToString()))
33 |
34 | return $paragraphElement
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Src/Private/New-PScriboListReference.ps1:
--------------------------------------------------------------------------------
1 | function New-PScriboListReference
2 | {
3 | <#
4 | .SYNOPSIS
5 | Initializes new PScribo list reference object.
6 |
7 | .DESCRIPTION
8 | Creates a placeholder reference to a list stored in $pscriboDocument.Lists.
9 |
10 | .NOTES
11 | This is an internal function and should not be called directly.
12 | #>
13 | [CmdletBinding()]
14 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions','')]
15 | [OutputType([System.Management.Automation.PSCustomObject])]
16 | param
17 | (
18 | ## Display name used in verbose output when processing.
19 | [Parameter(ValueFromPipelineByPropertyName)]
20 | [System.String] $Name,
21 |
22 | [Parameter(ValueFromPipelineByPropertyName)]
23 | [System.Int32] $Number
24 | )
25 | process
26 | {
27 | $pscriboListReference = [PSCustomObject] @{
28 | Id = [System.Guid]::NewGuid().ToString()
29 | Name = $Name
30 | Type = 'PScribo.ListReference'
31 | Number = $Number
32 | }
33 | return $pscriboListReference
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Examples/Example18.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding()]
2 | param (
3 | [System.String[]] $Format = 'Html',
4 | [System.String] $Path = '~\Desktop',
5 | [System.Management.Automation.SwitchParameter] $PassThru
6 | )
7 |
8 | Import-Module PScribo -Force -Verbose:$false
9 |
10 | $example18 = Document -Name 'PScribo Example 18' {
11 |
12 | <#
13 | If you need to list an object's or hashtable's values in a list format, you
14 | can specify the -List parameter on the 'Table' cmdlet. Rather than creating
15 | a table column for each property, it will create a two-column table, with a
16 | row for each property instead.
17 |
18 | This is useful if not all properties will fit across as page (like Services).
19 | However, if multiple objects are encountered, PScribo will create a separate
20 | two-column table for each object (similar in functionality to the
21 | 'Format-List' cmdlet).
22 |
23 | The following example will create a list table, detailing every property,
24 | for the first 10 services regiestered on the local machine.
25 | #>
26 | Get-Service | Select-Object -First 10 | Table -List
27 | }
28 | $example18 | Export-Document -Path $Path -Format $Format -PassThru:$PassThru
29 |
--------------------------------------------------------------------------------
/Src/Plugins/Word/Get-WordListLevel.ps1:
--------------------------------------------------------------------------------
1 | function Get-WordListLevel
2 | {
3 | <#
4 | .SYNOPSIS
5 | Process (nested) lists and build index of number/bullet styles.
6 | #>
7 | [CmdletBinding()]
8 | param
9 | (
10 | [Parameter(Mandatory, ValueFromPipeline)]
11 | [System.Management.Automation.PSObject] $List,
12 |
13 | [Parameter(ValueFromPipelineByPropertyName)]
14 | [System.Collections.Hashtable] $Levels = @{ }
15 | )
16 | process
17 | {
18 | foreach ($item in $List.Items)
19 | {
20 | if ($item.Type -eq 'PScribo.Item')
21 | {
22 | $level = $item.Level -1
23 | if (-not $Levels.ContainsKey($level))
24 | {
25 | $Levels[$level] = @{
26 | IsNumbered = $List.IsNumbered
27 | NumberStyle = $List.NumberStyle
28 | BulletStyle = $List.BulletStyle
29 | }
30 | }
31 | }
32 | elseif ($item.Type -eq 'PScribo.List')
33 | {
34 | $Levels = Get-WordListLevel -List $item -Levels $Levels
35 | }
36 | }
37 | return $Levels
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Src/Private/Copy-Object.ps1:
--------------------------------------------------------------------------------
1 | function Copy-Object
2 | {
3 | <#
4 | .SYNOPSIS
5 | Clones a .NET object by serializing and deserializing it.
6 | .NOTES
7 | PowerShell 7.4 throws a "Type 'System.Management.Automation.PSObject' is not marked as serializable." exception.
8 | This function has been replaced by 'ConvertTo-Json | ConvertFrom-Json' to serialize and deserialize into a
9 | "clone" object. This works for PScribo objects but may not work for other nested objects in script blocks.
10 | #>
11 | [CmdletBinding()]
12 | param
13 | (
14 | [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
15 | [System.Object] $InputObject
16 | )
17 | process
18 | {
19 | try
20 | {
21 | $stream = New-Object IO.MemoryStream
22 | $formatter = New-Object Runtime.Serialization.Formatters.Binary.BinaryFormatter
23 | $formatter.Serialize($stream, $InputObject)
24 | $stream.Position = 0
25 | return $formatter.Deserialize($stream)
26 | }
27 | catch
28 | {
29 | Write-Error -ErrorRecord $_
30 | }
31 | finally
32 | {
33 | $stream.Dispose()
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Src/Plugins/Html/Get-HtmlTableColGroup.ps1:
--------------------------------------------------------------------------------
1 | function Get-HtmlTableColGroup
2 | {
3 | <#
4 | .SYNOPSIS
5 | Generates Html
tags based on table column widths
6 | #>
7 | [CmdletBinding()]
8 | [OutputType([System.String])]
9 | param
10 | (
11 | [Parameter(Mandatory, ValueFromPipeline)]
12 | [ValidateNotNull()]
13 | [System.Management.Automation.PSObject] $Table
14 | )
15 | process
16 | {
17 | $colGroupBuilder = New-Object -TypeName 'System.Text.StringBuilder'
18 |
19 | if ($Table.ColumnWidths)
20 | {
21 | [ref] $null = $colGroupBuilder.Append('')
22 | foreach ($columnWidth in $Table.ColumnWidths)
23 | {
24 | if ($null -eq $columnWidth)
25 | {
26 | [ref] $null = $colGroupBuilder.Append('')
27 | }
28 | else
29 | {
30 | [ref] $null = $colGroupBuilder.AppendFormat('', $columnWidth)
31 | }
32 | }
33 | [ref] $null = $colGroupBuilder.AppendLine('')
34 | }
35 |
36 | return $colGroupBuilder.ToString()
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Tests/Unit/LineBreak.Tests.ps1:
--------------------------------------------------------------------------------
1 | $here = Split-Path -Path $MyInvocation.MyCommand.Path -Parent;
2 | $testRoot = Split-Path -Path $here -Parent;
3 | $moduleRoot = Split-Path -Path $testRoot -Parent;
4 | Import-Module "$moduleRoot\PScribo.psm1" -Force;
5 |
6 | InModuleScope 'PScribo' {
7 |
8 | Describe 'LineBreak' {
9 | $pscriboDocument = Document 'ScaffoldDocument' {};
10 |
11 | It 'returns a PSCustomObject object' {
12 | $l = LineBreak
13 |
14 | $l.GetType().Name | Should Be 'PSCustomObject'
15 | }
16 |
17 | It 'creates a PScribo.LineBreak type' {
18 | $l = LineBreak
19 |
20 | $l.Type | Should Be 'PScribo.LineBreak'
21 | }
22 |
23 | It 'creates line break with no parameters' {
24 | $l = LineBreak
25 |
26 | $l.Id | Should Not Be $null
27 | }
28 |
29 | It 'creates line break by named -Id parameter' {
30 | $id = 'Test'
31 |
32 | $l = LineBreak -Id $id
33 |
34 | $l.Id | Should Be $id
35 | }
36 |
37 | It 'creates line break by positional -Id parameter' {
38 | $id = 'Test'
39 |
40 | $l = LineBreak $id
41 |
42 | $l.Id | Should Be $id
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/PScribo.psm1:
--------------------------------------------------------------------------------
1 | Set-StrictMode -Version Latest
2 |
3 | ## Import localisation strings based on UICulture
4 | $importLocalizedDataParams = @{
5 | BindingVariable = 'localized'
6 | BaseDirectory = $PSScriptRoot
7 | FileName = 'PScribo.Resources.psd1'
8 | }
9 | Import-LocalizedData @importLocalizedDataParams -ErrorAction SilentlyContinue
10 |
11 | #Fallback to en-US culture strings
12 | if (-not (Test-Path -Path 'Variable:\localized'))
13 | {
14 | $importLocalizedDataParams['UICulture'] = 'en-US'
15 | Import-LocalizedData @importLocalizedDataParams -ErrorAction Stop
16 | }
17 |
18 | ## Dot source all the nested .ps1 files in the \Functions and \Plugin folders, excluding tests
19 | $pscriboRoot = Split-Path -Parent $PSCommandPath
20 | Get-ChildItem -Path "$pscriboRoot\Src\" -Include '*.ps1' -Recurse |
21 | ForEach-Object {
22 | Write-Debug ($localized.ImportingFile -f $_.FullName)
23 | ## https://becomelotr.wordpress.com/2017/02/13/expensive-dot-sourcing/
24 | . ([System.Management.Automation.ScriptBlock]::Create(
25 | [System.IO.File]::ReadAllText($_.FullName)
26 | ))
27 | }
28 |
29 | Add-Type -AssemblyName 'System.Drawing'
30 | #Export-ModuleMember -Function $exportedFunctions -Alias $exportedAliases -Verbose:$false
31 |
--------------------------------------------------------------------------------
/Tests/Unit/PageBreak.Tests.ps1:
--------------------------------------------------------------------------------
1 | $here = Split-Path -Path $MyInvocation.MyCommand.Path -Parent;
2 | $testRoot = Split-Path -Path $here -Parent;
3 | $moduleRoot = Split-Path -Path $testRoot -Parent;
4 | Import-Module "$moduleRoot\PScribo.psm1" -Force;
5 |
6 | InModuleScope 'PScribo' {
7 |
8 | Describe 'PageBreak' {
9 |
10 | $pscriboDocument = Document 'ScaffoldDocument' {}
11 |
12 | It 'returns a PSCustomObject object' {
13 | $p = PageBreak
14 |
15 | $p.GetType().Name | Should Be 'PSCustomObject'
16 | }
17 |
18 | It 'creates a PScribo.PageBreak type' {
19 | $p = PageBreak
20 |
21 | $p.Type | Should Be 'PScribo.PageBreak'
22 | }
23 |
24 | It 'creates page break with no parameters' {
25 | $p = PageBreak
26 |
27 | $p.Id | Should Not Be $null
28 | }
29 |
30 | It 'creates page break by named -Id parameter' {
31 | $id = 'Test'
32 |
33 | $p = PageBreak -Id $id
34 |
35 | $p.Id | Should Be $id
36 | }
37 |
38 | It 'creates page break by positional -Id parameter' {
39 | $id = 'Test'
40 |
41 | $p = PageBreak $id
42 |
43 | $p.Id | Should Be $id
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/Src/Plugins/Word/Out-WordLineBreak.ps1:
--------------------------------------------------------------------------------
1 | function Out-WordLineBreak
2 | {
3 | <#
4 | .SYNOPSIS
5 | Output formatted Word line break.
6 | #>
7 | [CmdletBinding()]
8 | [OutputType([System.Xml.XmlElement])]
9 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter','LineBreak')]
10 | param
11 | (
12 | [Parameter(Mandatory, ValueFromPipeline)]
13 | [System.Management.Automation.PSObject] $LineBreak,
14 |
15 | [Parameter(Mandatory)]
16 | [System.Xml.XmlDocument] $XmlDocument
17 | )
18 | process
19 | {
20 | $xmlns = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'
21 | $p = $XmlDocument.CreateElement('w', 'p', $xmlns)
22 | $pPr = $p.AppendChild($XmlDocument.CreateElement('w', 'pPr', $xmlns))
23 | $pBdr = $pPr.AppendChild($XmlDocument.CreateElement('w', 'pBdr', $xmlns))
24 | $bottom = $pBdr.AppendChild($XmlDocument.CreateElement('w', 'bottom', $xmlns))
25 | [ref] $null = $bottom.SetAttribute('val', $xmlns, 'single')
26 | [ref] $null = $bottom.SetAttribute('sz', $xmlns, 6)
27 | [ref] $null = $bottom.SetAttribute('space', $xmlns, 1)
28 | [ref] $null = $bottom.SetAttribute('color', $xmlns, 'auto')
29 |
30 | return $p
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Src/Private/New-PScriboTOC.ps1:
--------------------------------------------------------------------------------
1 | function New-PScriboTOC
2 | {
3 | <#
4 | .SYNOPSIS
5 | Initializes a new PScribo Table of Contents (TOC) object.
6 |
7 | .NOTES
8 | This is an internal function and should not be called directly.
9 | #>
10 | [CmdletBinding()]
11 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions','')]
12 | [OutputType([System.Management.Automation.PSCustomObject])]
13 | param
14 | (
15 | [Parameter(ValueFromPipeline)]
16 | [ValidateNotNullOrEmpty()]
17 | [System.String] $Name = 'Contents',
18 |
19 | [Parameter(ValueFromPipelineByPropertyName)]
20 | [ValidateNotNullOrEmpty()]
21 | [System.String] $ClassId = 'TOC'
22 | )
23 | process
24 | {
25 | $typeName = 'PScribo.TOC';
26 | if ($pscriboDocument.Options['ForceUppercaseSection'])
27 | {
28 | $Name = $Name.ToUpper();
29 | }
30 | $pscriboDocument.Properties['TOCs']++;
31 | $pscriboTOC = [PSCustomObject] @{
32 | Id = [System.Guid]::NewGuid().ToString();
33 | Name = $Name;
34 | Type = $typeName;
35 | ClassId = $ClassId;
36 | }
37 | return $pscriboTOC;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Examples/Example24.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding()]
2 | param (
3 | [System.String[]] $Format = 'Html',
4 | [System.String] $Path = '~\Desktop',
5 | [System.Management.Automation.SwitchParameter] $PassThru
6 | )
7 |
8 | Import-Module PScribo -Force -Verbose:$false
9 |
10 | $example24 = Document -Name 'PScribo Example 24' {
11 |
12 | <#
13 | The following example combines the creation of multiple custom styles with the
14 | definition of a custom table style. The custom "BlueZebra" table style is then
15 | applied to a table.
16 | #>
17 | Style -Name 'BlueZebraHeading' -Bold -Color 039 -Font 'Segoe UI' -Size 12
18 | Style -Name 'BlueZebraRow' -Color 669 -Font 'Lucida Sans Unicode' -BackgroundColor E8EDFF
19 | Style -Name 'BlueZebraAltRow' -Color 669 -Font 'Lucida Sans Unicode'
20 | TableStyle -Name 'BlueZebra' -HeaderStyle BlueZebraHeading -RowStyle BlueZebraRow -AlternateRowStyle BlueZebraAltRow -PaddingTop 4 -PaddingRight 4 -PaddingBottom 4 -PaddingLeft 4
21 |
22 | <#
23 | Create a standard table using the new "BlueZebra" table style.
24 | #>
25 | Get-Service | Select-Object -Last 10 | Table -Columns Name,DisplayName,Status -Headers Name,'Display Name','State' -Style BlueZebra
26 | }
27 | $example24 | Export-Document -Path $Path -Format $Format -PassThru:$PassThru
28 |
--------------------------------------------------------------------------------
/Examples/Example12.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding()]
2 | param (
3 | [System.String[]] $Format = 'Html',
4 | [System.String] $Path = '~\Desktop',
5 | [System.Management.Automation.SwitchParameter] $PassThru
6 | )
7 |
8 | Import-Module PScribo -Force -Verbose:$false
9 |
10 | $example12 = Document -Name 'PScribo Example 12' {
11 | <#
12 | The 'Table' cmdlet supports filtering of object properties by using the -Columns
13 | parameter. The -Columns parameter specifies the object properties you wish to
14 | display in the table, in the order required.
15 |
16 | NOTE: The -Columns parameter is required if you wish to override the values
17 | displayed in column headings.
18 |
19 | The following example displays the Name, DisplayName and Status properties of
20 | all services sent down the pipeline, ignoring all other properties.
21 |
22 | NOTE: The columns are displayed in the exact order that they are listed in
23 | the -Columns parameter.
24 |
25 | NOTE: Due the the length of the table cell content, text output may be
26 | truncated due to limitations/implementation of the 'Format-Table' cmdlet.
27 | #>
28 | Get-Service | Table -Columns Name,DisplayName,Status
29 | }
30 | $example12 | Export-Document -Path $Path -Format $Format -PassThru:$PassThru
31 |
--------------------------------------------------------------------------------
/Examples/Example13.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding()]
2 | param (
3 | [System.String[]] $Format = 'Html',
4 | [System.String] $Path = '~\Desktop',
5 | [System.Management.Automation.SwitchParameter] $PassThru
6 | )
7 |
8 | Import-Module PScribo -Force -Verbose:$false
9 |
10 | $example13 = Document -Name 'PScribo Example 13' {
11 |
12 | <#
13 | To override the column headers, the -Columns and -Headers parameters can be used
14 | together.
15 |
16 | The -Headers parameter specifies the heading names to apply to the corresponding
17 | (positional) -Columns parameter. This permits you to include spaces in the headers
18 | and/or change the properties' display values.
19 |
20 | The following example overrides the column names with the values supplied in the
21 | -Headers parameter - a space is introduced in the 'DisplayName' property and the
22 | 'Status' property is displayed as 'State' instead.
23 |
24 | NOTE: Due the the length of the table cell content, text output may be
25 | truncated due to limitations/implementation of the 'Format-Table' cmdlet.
26 | #>
27 | Get-Service | Table -Columns Name,DisplayName,Status -Headers Name,'Display Name',State
28 | }
29 | $example13 | Export-Document -Path $Path -Format $Format -PassThru:$PassThru -Options @{ TextWidth = 160 }
30 |
--------------------------------------------------------------------------------
/Examples/Example40.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding()]
2 | param (
3 | [System.String[]] $Format = 'Html',
4 | [System.String] $Path = '~\Desktop',
5 | [System.Management.Automation.SwitchParameter] $PassThru
6 | )
7 |
8 | Import-Module PScribo -Force -Verbose:$false
9 |
10 | $example40 = Document -Name 'PScribo Example 40' {
11 |
12 | <#
13 | Numbered lists are supported and can be specified with the '-Numbered' parameter.
14 | #>
15 | List -Item 'Apples','Oranges','Bananas' -Numbered
16 |
17 | <#
18 | Multiple number styles are available: 'Number', 'Letter' and 'Roman'. If not specified,
19 | a numbered list will default to the 'Number' style. You can specify the required number
20 | format with the '-NumberStyle' parameter.
21 | #>
22 | List -Item 'Apples','Oranges','Bananas' -Numbered -NumberStyle Letter
23 |
24 | <#
25 | Multiple number styles are available: 'Number', 'Letter' and 'Roman'. If not specified,
26 | a numbered list will default to the 'Number' style. You can specify the required number
27 | format with the '-NumberStyle' parameter.
28 | #>
29 | List -Numbered -NumberStyle Roman {
30 | Item 'Apples'
31 | Item 'Bananas'
32 | Item 'Oranges'
33 | }
34 |
35 | }
36 | $example40 | Export-Document -Path $Path -Format $Format -PassThru:$PassThru
37 |
--------------------------------------------------------------------------------
/Examples/Example07.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding()]
2 | param (
3 | [System.String[]] $Format = 'Html',
4 | [System.String] $Path = '~\Desktop',
5 | [System.Management.Automation.SwitchParameter] $PassThru
6 | )
7 |
8 | Import-Module PScribo -Force -Verbose:$false
9 |
10 | $example7 = Document -Name 'PScribo Example 7' {
11 |
12 | <#
13 | Sections support automatic numbering, i.e. PScribo will automatically generate the section
14 | numbers/levels based on the nesting. To turn this on, use the 'DocumentOption' cmdlet.
15 | #>
16 | DocumentOption -EnableSectionNumbering -MarginTopAndBottom 72 -MarginLeftAndRight 54
17 |
18 | Section -Name 'First Section' -ScriptBlock {
19 | Paragraph 'This section should be labeled as "1 First Section".'
20 | }
21 |
22 | Section -Name 'Second "Styled" Section' -Style Heading1 -ScriptBlock {
23 | Paragraph 'This section should be labeled as "2 Second Styled Section".'
24 | }
25 |
26 | Section -Name 'Third "Styled" Section' -Style Heading1 -ScriptBlock {
27 | Paragraph 'This section should be labeled as "3 Third Section".'
28 |
29 | Section 'Sub Section' -Style Heading2 {
30 | Paragraph 'This section should be labeled as "3.1 Sub Section".'
31 | }
32 | }
33 | }
34 | $example7 | Export-Document -Path $Path -Format $Format -PassThru:$PassThru
35 |
--------------------------------------------------------------------------------
/Src/Private/ConvertTo-Mm.ps1:
--------------------------------------------------------------------------------
1 | function ConvertTo-Mm
2 | {
3 | <#
4 | .SYNOPSIS
5 | Convert points, inches or pixels into millimeters
6 | #>
7 | [CmdletBinding()]
8 | [OutputType([System.Single])]
9 | param
10 | (
11 | [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'Point')]
12 | [Alias('pt')]
13 | [System.Single] $Point,
14 |
15 | [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'Inch')]
16 | [Alias('in')]
17 | [System.Single] $Inch,
18 |
19 | [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'Pixel')]
20 | [Alias('px')]
21 | [System.Single] $Pixel,
22 |
23 | [Parameter(ValueFromPipelineByPropertyName, ParameterSetName = 'Pixel')]
24 | [System.Int16] $Dpi = 96
25 | )
26 | process
27 | {
28 | if ($PSCmdlet.ParameterSetName -eq 'Point')
29 | {
30 | return [System.Math]::Round(($Point / 72) * 25.4, 2)
31 | }
32 | elseif ($PSCmdlet.ParameterSetName -eq 'Inch')
33 | {
34 | $mm = $Inch * 25.4
35 | return [System.Math]::Round($mm, 2)
36 | }
37 | elseif ($PSCmdlet.ParameterSetName -eq 'Pixel')
38 | {
39 | $mm = (25.4 / $Dpi) * $Pixel
40 | return [System.Math]::Round($mm, 2)
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Examples/Example05.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding()]
2 | param (
3 | [System.String[]] $Format = 'Html',
4 | [System.String] $Path = '~\Desktop',
5 | [System.Management.Automation.SwitchParameter] $PassThru
6 | )
7 |
8 | Import-Module PScribo -Force -Verbose:$false
9 |
10 | $example5 = Document -Name 'PScribo Example 5' {
11 |
12 | <#
13 | Rather than specifying styling options on individual paragraphs, PScribo supports defining (or
14 | overriding the default styles) with your own. Creating your own style is easy - just use the
15 | 'Style' cmdlet.
16 |
17 | The following command creates a new style called 'Funky':
18 | #>
19 | Style -Name 'Funky' -Font Arial -Size 16 -Color Pink -Align Right
20 |
21 | <#
22 | The style can then easily be applied to a paragraph by specifying the -Style parameter.
23 | #>
24 | Paragraph 'This paragraph is styled with the "Funky" style!' -Style Funky
25 |
26 | <#
27 | If no style is specified, the default 'Normal' is used. You can override the default style
28 | by defining your own style with the same name:
29 | #>
30 | Style -Name 'Normal' -Font Tahoma -Size 12 -Color 000
31 | Paragraph 'This paragraph will be styled with the custom "Normal" style defined earlier.'
32 | }
33 | $example5 | Export-Document -Path $Path -Format $Format -PassThru:$PassThru
34 |
--------------------------------------------------------------------------------
/Examples/Example44.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding()]
2 | param (
3 | [System.String[]] $Format = 'Word',
4 | [System.String] $Path = '~\Desktop',
5 | [System.Management.Automation.SwitchParameter] $PassThru
6 | )
7 |
8 | Import-Module PScribo -Force -Verbose:$false
9 |
10 | $example44 = Document -Name 'PScribo Example 44' {
11 |
12 | <#
13 | Custom numbered lists are registered with the 'NumberStyle' keyword, but only the Word and
14 | Text plugins are supported. All other plugins will render the number as a decimal (using the
15 | 'Number' format).
16 |
17 | Custom number lists can contain any wording and punctuation you require.
18 |
19 | NOTE: The '-Uppercase' and '-Suffix' parameters are ignored so you need to include any suffix
20 | in the number format definition.
21 |
22 | The '%' token is used to denote where the number will be placed. To include leading zeroes,
23 | use multiple '%' tokens, e.g. 'ab%%' for ab01, ab02 and 'XYZ-%%%' for XYZ-001, XYZ-002, etc..
24 | #>
25 | NumberStyle -Id 'CustomNumberStyle' -Custom 'xYz-%%%.' -Indent 1500 -Hanging 200 -Align Left
26 |
27 | <#
28 | Output list using the 'Custom' number style
29 | #>
30 |
31 | List -Numbered -NumberStyle CustomNumberStyle -Item 'Apples','Bananas','Oranges'
32 |
33 | }
34 | $example44 | Export-Document -Path $Path -Format $Format -PassThru:$PassThru
35 |
--------------------------------------------------------------------------------
/Examples/Example02.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding()]
2 | param (
3 | [System.Management.Automation.SwitchParameter] $PassThru
4 | )
5 |
6 | Import-Module PScribo -Force -Verbose:$false
7 |
8 | $example2 = Document -Name 'PScribo Example 2' {
9 | Paragraph 'This is an example that adds a single paragraph to the document that will be styled with the default style.'
10 | }
11 |
12 | <#
13 | Once we have a reference to a PScribo document, it can be exported with the Export-Document cmdlet.
14 | The Export-Document cmdlet can export to one or more formats: Word, Html, Text and Html are included
15 | by default.
16 |
17 | This command converts/exports the $example2 document to a text formatted file named 'PScribo Example 2.txt' on the desktop.
18 | #>
19 | Export-Document -Document $example2 -Format Text -Path ~\Desktop
20 |
21 | <#
22 | This command converts/exports the $example2 document to a html formatted file named 'PScribo Example 2.html' on the desktop.
23 | #>
24 | Export-Document -Document $example2 -Format Html -Path ~\Desktop
25 |
26 | <#
27 | This command exports the $example2 document to both Word formatted 'PScribo Example 2.docx' and html formatted
28 | 'PScribo Example 2.html' files on the desktop, via the pipeline.
29 |
30 | NOTE: This will overwrite the 'PScribo Example 2.html' created above without warning.
31 | #>
32 | $example2 | Export-Document -Format Word,Html -Path ~\Desktop -PassThru:$PassThru
33 |
--------------------------------------------------------------------------------
/Src/Private/ConvertTo-RomanNumeral.ps1:
--------------------------------------------------------------------------------
1 | function ConvertTo-RomanNumeral
2 | {
3 | <#
4 | .SYNOPSIS
5 | Converts a decimal number to Roman numerals.
6 | #>
7 | [CmdletBinding()]
8 | param
9 | (
10 | [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
11 | [System.Int32] $Value
12 | )
13 | begin
14 | {
15 | $conversionTable = [ordered] @{
16 | 1000 = 'M'
17 | 900 = 'CM'
18 | 500 = 'D'
19 | 400 = 'CD'
20 | 100 = 'C'
21 | 90 = 'XC'
22 | 50 = 'L'
23 | 40 = 'XL'
24 | 10 = 'X'
25 | 9 = 'IX'
26 | 5 = 'V'
27 | 4 = 'IV'
28 | 1 = 'I'
29 | }
30 | }
31 | process
32 | {
33 | $romanNumeralBuilder = New-Object -TypeName System.Text.StringBuilder
34 | do
35 | {
36 | foreach ($romanNumeral in $conversionTable.GetEnumerator())
37 | {
38 | if ($Value -ge $romanNumeral.Key)
39 | {
40 | [ref] $null = $romanNumeralBuilder.Append($romanNumeral.Value)
41 | $Value -= $romanNumeral.Key
42 | break
43 | }
44 | }
45 |
46 | }
47 | until ($Value -eq 0)
48 | return $romanNumeralBuilder.ToString()
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/Examples/Example30.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding()]
2 | param (
3 | [System.String[]] $Format = 'Html',
4 | [System.String] $Path = '~\Desktop',
5 | [System.Management.Automation.SwitchParameter] $PassThru
6 | )
7 |
8 | Import-Module PScribo -Force -Verbose:$false
9 |
10 | $example30 = Document -Name 'PScribo Example 30' {
11 |
12 | <#
13 | When sending PScribo output as a HTML email body, Outlook does not necessarily
14 | display the page styling/look-and-feel correctly. This can be suppressed by
15 | passing an -Options hashtable with the 'NoPageLayoutStyle' key to the
16 | Export-Document function.
17 |
18 | Setting this option, removes the page layout styling, rendering the contents the
19 | full width of the web browser (or Outlook message) window.
20 |
21 | NOTE: Regardless, Outlook might not render the HTML5 content correctly due its
22 | usage of the Internet Explorer rendering engine.
23 | #>
24 | DocumentOption -Margin 18
25 | Style -Name StoppedService -Color White -BackgroundColor Firebrick
26 |
27 | $services = Get-Service
28 | $services | Where-Object { $_.Status -ne 'Running' } | Set-Style -Style 'StoppedService'
29 | Table -InputObject $services -Columns Name,DisplayName,Status -Headers 'Name','Display Name','State'
30 | }
31 | $example30 | Export-Document -Format $Format -Path $Path -Options @{ NoPageLayoutStyle = $true } -PassThru:$PassThru
32 |
--------------------------------------------------------------------------------
/Examples/Example25.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding()]
2 | param (
3 | [System.String[]] $Format = 'Html',
4 | [System.String] $Path = '~\Desktop',
5 | [System.Management.Automation.SwitchParameter] $PassThru
6 | )
7 |
8 | Import-Module PScribo -Force -Verbose:$false
9 |
10 | $example25 = Document -Name 'PScribo Example 25' {
11 |
12 | <#
13 | The following example combines the creation of multiple custom styles with the
14 | definition of a custom table style. The custom "BlueZebra" table style is then
15 | applied to a -List view table of the 11th to last service.
16 |
17 | NOTE: List view tables do apply the -AlternateRowStyle styling, but this style
18 | does not include an alternate row style.
19 | #>
20 | Style -Name 'BlueZebraHeading' -Bold -Color 039 -Font 'Segoe UI' -BackgroundColor E8EDFF
21 | Style -Name 'BlueZebraRow' -Color 669 -Font 'Lucida Sans Unicode'
22 | TableStyle -Name 'BlueZebra' -HeaderStyle BlueZebraHeading -RowStyle BlueZebraRow -PaddingTop 4 -PaddingRight 4 -PaddingBottom 4 -PaddingLeft 4 -BorderWidth 1 -BorderColor E8EDFF
23 |
24 | <#
25 | Create a standard table using the new "BlueZebra" table style.
26 | #>
27 | Get-Service | Select-Object -Last 1 -Skip 10 | Table -Columns 'Name','DisplayName','Status' -Headers 'Name','Display Name','State' -ColumnWidths 25,75 -Style BlueZebra -List
28 | }
29 | $example25 | Export-Document -Path $Path -Format $Format -PassThru:$PassThru
30 |
--------------------------------------------------------------------------------
/Src/Private/New-PScriboFormattedTableRowCell.ps1:
--------------------------------------------------------------------------------
1 | function New-PScriboFormattedTableRowCell
2 | {
3 | <#
4 | .SYNOPSIS
5 | Creates a formatted table cell for plugin output/rendering.
6 | #>
7 | [CmdletBinding()]
8 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions','')]
9 | [OutputType([System.Management.Automation.PSObject])]
10 | param
11 | (
12 | [Parameter(ValueFromPipeline)]
13 | [AllowNull()]
14 | [System.String[]] $Content,
15 |
16 | [Parameter(ValueFromPipelineByPropertyName)]
17 | [System.Uint16] $Width,
18 |
19 | [Parameter(ValueFromPipelineByPropertyName)]
20 | [AllowNull()]
21 | [System.String] $Style = $null
22 | )
23 | process
24 | {
25 | $isStyleInherited = $true
26 | $combinedContent = $Content
27 |
28 | if ($Content -is [System.Array])
29 | {
30 | $combinedContent = [System.String]::Join([System.Environment]::NewLine, $Content)
31 | }
32 |
33 | if (-not ([System.String]::IsNullOrEmpty($Style)))
34 | {
35 | ## Use the explictit style
36 | $isStyleInherited = $false
37 | }
38 |
39 | return [PSCustomObject] @{
40 | Content = $combinedContent
41 | Width = $Width
42 | Style = $Style
43 | IsStyleInherited = $isStyleInherited
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/Tests/Plugins/Html/Out-HtmlPageBreak.Tests.ps1:
--------------------------------------------------------------------------------
1 | $here = Split-Path -Path $MyInvocation.MyCommand.Path -Parent;
2 | $pluginRoot = Split-Path -Path $here -Parent;
3 | $testRoot = Split-Path -Path $pluginRoot -Parent;
4 | $moduleRoot = Split-Path -Path $testRoot -Parent;
5 | Import-Module "$moduleRoot\PScribo.psm1" -Force;
6 |
7 | InModuleScope 'PScribo' {
8 |
9 | Describe 'Plugins\Html\Out-HtmlPageBreak' {
10 |
11 | ## Scaffold new document to initialise options/styles
12 | $Document = Document -Name 'Test' -ScriptBlock { }
13 | $script:currentPageNumber = 1
14 | $text = Out-HtmlPageBreak -Orientation Portrait
15 |
16 | It 'closes previous tags' {
17 | $text.StartsWith('') | Should Be $true
18 | }
19 |
20 | It 'creates new ' {
21 | $text -match '
' | Should Be $true
22 | }
23 |
24 | It 'sets page class to default style' {
25 | $divStyleMatch = '
24 | $hashtableArray = @(
25 | [Ordered] @{ 'Column 1' = 'Some random text'; 'Column2' = 345; 'Custom Property' = $true; }
26 | [Ordered] @{ 'Column 1' = 'Random some text'; 'Column2' = 16; 'Custom Property' = $false; }
27 | [Ordered] @{ 'Column 1' = 'Text random some'; 'Column2' = 1GB; 'Custom Property' = $true; }
28 | )
29 | Table -Hashtable $hashtableArray
30 | }
31 | $example17 | Export-Document -Path $Path -Format $Format -PassThru:$PassThru
32 |
--------------------------------------------------------------------------------
/Src/Private/Get-PScriboImage.ps1:
--------------------------------------------------------------------------------
1 | function Get-PScriboImage
2 | {
3 | <#
4 | .SYNOPSIS
5 | Retrieves PScribo.Images in a document/section
6 | #>
7 | [CmdletBinding()]
8 | [OutputType([System.Management.Automation.PSObject])]
9 | param
10 | (
11 | [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
12 | [System.Management.Automation.PSObject[]] $Section,
13 |
14 | [Parameter(ValueFromPipelineByPropertyName)]
15 | [System.String[]] $Id
16 | )
17 | process
18 | {
19 | foreach ($subSection in $Section)
20 | {
21 | if ($subSection.Type -eq 'PScribo.Image')
22 | {
23 | if ($PSBoundParameters.ContainsKey('Id'))
24 | {
25 | if ($subSection.Id -in $Id)
26 | {
27 | Write-Output -InputObject $subSection
28 | }
29 | }
30 | else
31 | {
32 | Write-Output -InputObject $subSection
33 | }
34 | }
35 | elseif ($subSection.Type -eq 'PScribo.Section')
36 | {
37 | if ($subSection.Sections.Count -gt 0)
38 | {
39 | ## Recursively search subsections
40 | $PSBoundParameters['Section'] = $subSection.Sections
41 | Get-PScriboImage @PSBoundParameters
42 | }
43 | }
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/Src/Plugins/Html/Out-HtmlTOC.ps1:
--------------------------------------------------------------------------------
1 | function Out-HtmlTOC
2 | {
3 | <#
4 | .SYNOPSIS
5 | Generates Html table of contents.
6 | #>
7 | [CmdletBinding()]
8 | [OutputType([System.String])]
9 | param
10 | (
11 | [Parameter(Mandatory, ValueFromPipeline)]
12 | [System.Management.Automation.PSObject] $TOC
13 | )
14 | process
15 | {
16 | $tocBuilder = New-Object -TypeName 'System.Text.StringBuilder'
17 | [ref] $null = $tocBuilder.AppendFormat('
{1}
', $TOC.ClassId, $TOC.Name)
18 | #[ref] $null = $tocBuilder.AppendLine('
')
19 | [ref] $null = $tocBuilder.AppendLine('')
20 | foreach ($tocEntry in $Document.TOC)
21 | {
22 | $sectionNumberIndent = ' ' * $tocEntry.Level
23 | if ($Document.Options['EnableSectionNumbering'])
24 | {
25 | [ref] $null = $tocBuilder.AppendFormat('| {0} | {1}{3} |
', $tocEntry.Number, $sectionNumberIndent, $tocEntry.Id, $tocEntry.Name).AppendLine()
26 | }
27 | else
28 | {
29 | [ref] $null = $tocBuilder.AppendFormat('| {0}{2} |
', $sectionNumberIndent, $tocEntry.Id, $tocEntry.Name).AppendLine()
30 | }
31 | }
32 | [ref] $null = $tocBuilder.AppendLine('
')
33 | return $tocBuilder.ToString()
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Src/Private/ConvertTo-PSObjectKeyedListTable.ps1:
--------------------------------------------------------------------------------
1 | function ConvertTo-PSObjectKeyedListTable
2 | {
3 | <#
4 | .SYNOPSIS
5 | Converts a PScribo.Table to a [PSCustomObject] collection representing a keyed list table.
6 | #>
7 | [CmdletBinding()]
8 | [OutputType([System.Management.Automation.PSObject])]
9 | param
10 | (
11 | [Parameter(Mandatory, ValueFromPipeline)]
12 | [System.Management.Automation.PSObject] $Table
13 | )
14 | process
15 | {
16 | $listKey = $Table.ListKey
17 | $rowHeaders = $Table.Rows | Select-Object -ExpandProperty $listKey
18 | $columnHeaders = $Table.Rows |
19 | Select-Object -First 1 -Property * -ExcludeProperty '*__Style' |
20 | ForEach-Object { $_.PSObject.Properties.Name } |
21 | Where-Object { $_ -ne $listKey }
22 |
23 | foreach ($columnHeader in $columnHeaders)
24 | {
25 | $psCustomObjectParams = [Ordered] @{
26 | $listKey = $columnHeader
27 | }
28 | foreach ($rowHeader in $rowHeaders)
29 | {
30 | $psCustomObjectParams[$rowHeader] = $Table.Rows |
31 | Where-Object { $_.$listKey -eq $rowHeader } |
32 | Select-Object -ExpandProperty $columnHeader
33 | }
34 | $psCustomObject = [PSCustomObject] $psCustomObjectParams
35 | Write-Output -InputObject $psCustomObject
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Examples/Example33.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding()]
2 | param (
3 | [System.String[]] $Format = 'Html',
4 | [System.String] $Path = '~\Desktop',
5 | [System.Management.Automation.SwitchParameter] $PassThru
6 | )
7 |
8 | Import-Module PScribo -Force -Verbose:$false
9 |
10 | $example33 = Document -Name 'PScribo Example 33' {
11 |
12 | <#
13 | A keyed list combines a collection of objects by a single property (key)
14 | into a single table. All other properties are displayed as individual
15 | rows.
16 | #>
17 |
18 | $servers = @(
19 | [Ordered] @{ ComputerName = 'DC1'; DomainName = 'example.local'; FQDN = 'dc1.example.local'; IpAddress = '192.168.0.1' }
20 | [Ordered] @{ ComputerName = 'DC2'; DomainName = 'example.local'; FQDN = 'dc2.example.local'; IpAddress = '192.168.0.2' }
21 | [Ordered] @{ ComputerName = 'DC3'; DomainName = 'example.local'; FQDN = 'dc3.example.local'; IpAddress = '192.168.0.3' }
22 | )
23 |
24 | Table -Hashtable $servers -List -Key 'ComputerName'
25 |
26 | <#
27 | The table above, will be rendered like so:
28 |
29 | ComputerName DC1 DC2 DC3
30 | ------------ --- --- ---
31 | DomainName example.local example.local example.local
32 | FQDN dc1.example.local dc2.example.local dc3.example.local
33 | IpAddress 192.168.0.1 192.168.0.2 192.168.0.3
34 | #>
35 |
36 | }
37 | $example33 | Export-Document -Path $Path -Format $Format -PassThru:$PassThru
38 |
--------------------------------------------------------------------------------
/Src/Private/Invoke-PScriboSectionLevel.ps1:
--------------------------------------------------------------------------------
1 | function Invoke-PScriboSectionLevel
2 | {
3 | <#
4 | .SYNOPSIS
5 | Nested function that processes each document/TOC nested section
6 | #>
7 | [CmdletBinding()]
8 | param
9 | (
10 | [Parameter(Mandatory)]
11 | [ValidateNotNull()]
12 | [System.Management.Automation.PSObject] $Section,
13 |
14 | [Parameter(Mandatory)]
15 | [ValidateNotNullOrEmpty()]
16 | [System.String] $Number
17 | )
18 | process
19 | {
20 | if ($pscriboDocument.Options['ForceUppercaseSection'])
21 | {
22 | $Section.Name = $Section.Name.ToUpper();
23 | }
24 |
25 | ## Set this section's level
26 | $Section.Number = $Number;
27 | $Section.Level = $Number.Split('.').Count -1;
28 | ### Add to the TOC
29 | $tocEntry = [PScustomObject] @{ Id = $Section.Id; Number = $Number; Level = $Section.Level; Name = $Section.Name; }
30 | [ref] $null = $pscriboDocument.TOC.Add($tocEntry);
31 | ## Set sub-section level seed
32 | $minorNumber = 1;
33 | foreach ($s in $Section.Sections)
34 | {
35 | if ($s.Type -like '*.Section' -and -not $s.IsExcluded)
36 | {
37 | $sectionNumber = ('{0}.{1}' -f $Number, $minorNumber).TrimStart('.'); ## Calculate section version
38 | Invoke-PScriboSectionLevel -Section $s -Number $sectionNumber;
39 | $minorNumber++;
40 | }
41 | } #end foreach section
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Src/Plugins/Text/ConvertTo-JustifiedString.ps1:
--------------------------------------------------------------------------------
1 | function ConvertTo-JustifiedString
2 | {
3 | <#
4 | .SYNOPSIS
5 | Justifies a block of text using the specified alignment.
6 | #>
7 | [CmdletBinding()]
8 | [OutputType([System.String])]
9 | param
10 | (
11 | [Parameter(Mandatory, ValueFromPipeline)]
12 | [ValidateNotNull()]
13 | [System.Object[]] $InputObject,
14 |
15 | ## Text alignment
16 | [Parameter(ValueFromPipelineByPropertyName)]
17 | [ValidateSet('Left','Center','Right','Justify')]
18 | [System.String] $Align = 'Left',
19 |
20 | ## Text width
21 | [Parameter()]
22 | [System.Int32] $Width = ($Host.UI.RawUI.BufferSize.Width -1)
23 | )
24 | process
25 | {
26 | foreach ($object in $InputObject)
27 | {
28 | $objectString = $object.ToString()
29 | if (($Align -eq 'Left') -or ($objectString.Length -ge $Width))
30 | {
31 | $justifiedString = $objectString
32 | }
33 | else
34 | {
35 | $paddingLength = $Width - $objectString.Length
36 | if ($Align -eq 'Center')
37 | {
38 | $paddingLength = ($paddingLength /2) -as [System.Int32]
39 | }
40 | $padding = ''.PadRight($paddingLength, ' ')
41 | $justifiedString = '{0}{1}' -f $padding, $objectString
42 | }
43 | Write-Output -InputObject $justifiedString
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/en-US/about_HtmlPlugin.help.txt:
--------------------------------------------------------------------------------
1 | TOPIC
2 | Html Plugin
3 |
4 | SYNOPSIS
5 | PScribo supports outputting hypertext markup language (.html) documents.
6 |
7 | DESCRIPTION
8 | PScribo can output HTML documents for rendering in a web broswer.
9 |
10 | KNOWN LIMITATIONS
11 | There are some restrictions emposed by Html documents which means that some PScribo functionality cannot
12 | either be partially or fully implemented:
13 |
14 | - Html output attempts to create a document-like experience. Paper sizes, page breaks and headers/footers are
15 | rendered, but page numbers cannot be faithfully recreated.
16 | - Html output does not support the 'Dash' bullet style. Dashes will be rendered using the the web broswer's
17 | defaults.
18 | - Html numbered lists only support the default '.' number style terminator/suffix. The use of custom number
19 | style terminators/suffixes i.e. ')', is not supported.
20 |
21 | PLUGIN OPTIONS
22 | The Html plugin accepts the following output customisation options:
23 |
24 | NoPageLayoutStyle [bool] : Removes the page layout style and renders the content the full width of the
25 | browser window. If not specified, defaults to '$true'.
26 |
27 | Output customisations are passed to the Export-Document cmdlet as a hashtable, e.g.
28 |
29 | PS> $document | Export-Document -Format Html -Options @{ NoPageLayoutStyle = $true }
30 |
31 | SEE ALSO
32 | about_PscriboPlugins
33 | about_TextPlugin
34 | about_JsonPlugin
35 | about_WordPlugin
36 |
--------------------------------------------------------------------------------
/Examples/Example23.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding()]
2 | param (
3 | [System.String[]] $Format = 'Html',
4 | [System.String] $Path = '~\Desktop',
5 | [System.Management.Automation.SwitchParameter] $PassThru
6 | )
7 |
8 | Import-Module PScribo -Force -Verbose:$false
9 |
10 | $example23 = Document -Name 'PScribo Example 23' {
11 |
12 | <#
13 | By default, PScribo adds padding to each table cell within a table. Different amounts
14 | of padding can be applied to the top, right, bottom and left of each table cell. The
15 | padding is specified in points (pt).
16 |
17 | NOTE: Table padding applies to both standard tables and -List view tables.
18 |
19 | The default padding attempts to ensure that table padding renders evenly in both
20 | Html and Word without adding too much space. The default values are as follows:
21 |
22 | Padding-Top : 1.0pt
23 | Padding-Right : 4.0pt
24 | Padding-Bottom: 4.0pt
25 | Padding-Left : 0.0pt
26 |
27 | The following example creates a custom table style that creates even padding around
28 | all table cells.
29 |
30 | NOTE: a -BorderWidth has been specified to demonstrate the padding but is not required!
31 | #>
32 | TableStyle -Name 'LargeGrid' -HeaderStyle Normal -RowStyle Normal -BorderWidth 1 -PaddingTop 4 -PaddingRight 4 -PaddingBottom 4 -PaddingLeft 4
33 | Get-Service | Select-Object -Property Name,DisplayName,Status -First 3 | Table -Style LargeGrid
34 | }
35 | $example23 | Export-Document -Path $Path -Format $Format -PassThru:$PassThru
36 |
--------------------------------------------------------------------------------
/Src/Private/New-PScriboHeaderFooter.ps1:
--------------------------------------------------------------------------------
1 | function New-PScriboHeaderFooter
2 | {
3 | <#
4 | .SYNOPSIS
5 | Initializes a new PScribo header/footer object.
6 |
7 | .NOTES
8 | This is an internal function and should not be called directly.
9 | #>
10 | [CmdletBinding()]
11 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions','')]
12 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter','Footer')]
13 | [OutputType([System.Management.Automation.PSCustomObject])]
14 | param
15 | (
16 | [Parameter(Mandatory, ValueFromPipelineByPropertyName, ParameterSetName = 'Header')]
17 | [System.Management.Automation.SwitchParameter] $Header,
18 |
19 | [Parameter(Mandatory, ValueFromPipelineByPropertyName, ParameterSetName = 'Footer')]
20 | [System.Management.Automation.SwitchParameter] $Footer
21 | )
22 | begin
23 | {
24 | ## Ignores dot-sourced script blocks, i.e. style scripts
25 | $psCallStack = Get-PSCallStack | Where-Object { $_.FunctionName -ne '' }
26 | if ($psCallStack[2].FunctionName -ne 'Document')
27 | {
28 | throw $localized.HeaderFooterDocumentRootError
29 | }
30 | }
31 | process
32 | {
33 | $pscriboHeaderFooter = [PSCustomObject] @{
34 | Type = if ($Header) { 'PScribo.Header' } else { 'PScribo.Footer' }
35 | Sections = (New-Object -TypeName System.Collections.ArrayList)
36 | }
37 | return $pscriboHeaderFooter
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/en-US/about_WordPlugin.help.txt:
--------------------------------------------------------------------------------
1 | TOPIC
2 | Word Plugin
3 |
4 | SYNOPSIS
5 | PScribo supports outputting Microsoft Word (.docx) documents.
6 |
7 | DESCRIPTION
8 | PScribo can output Office Open XML (OOXML) documents for rendering with Microsoft Word 2013 (and later).
9 |
10 | KNOWN LIMITATIONS
11 | There are some restrictions emposed by Word documents which means that some PScribo functionality cannot
12 | either be partially or fully implemented:
13 |
14 | - When opening documents that include a Table of Contents (TOC), Word displays a 'This document contains fields
15 | that may refer to other files.' warning message:
16 | - When the Word document is generated, page numbers are unknown. The 'updateFields' settings flag is used to
17 | instruct Word to update all field references, i.e. page numbers.
18 | - Selecting 'No' to this warning will render an empty Table of Contents
19 | - Whilst LibreOffice can open documents generated by PScribo, the following features are not currently
20 | implemented:
21 | - Table of Contents are not rendered as the 'updateFields' flag is not implemented/supported
22 | - Table cell font colors are not rendered correctly
23 | - Word does not support a mixture of formats at the same level within a bullet/numbered list. Therefore, only the
24 | first list type will be rendered.
25 |
26 | PLUGIN OPTIONS
27 | The Word plugin does not accept any output customisation options.
28 |
29 | SEE ALSO
30 | about_PscriboPlugins
31 | about_HtmlPlugin
32 | about_TextPlugin
33 | about_JsonPlugin
34 |
--------------------------------------------------------------------------------
/Examples/Example15.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding()]
2 | param (
3 | [System.String[]] $Format = 'Html',
4 | [System.String] $Path = '~\Desktop',
5 | [System.Management.Automation.SwitchParameter] $PassThru
6 | )
7 |
8 | Import-Module PScribo -Force -Verbose:$false
9 |
10 | $example15 = Document -Name 'PScribo Example 15' {
11 |
12 | <#
13 | You can optionally set the width of each column by using the -ColumnWidths
14 | parameter on the 'Table' cmdlet.
15 |
16 | NOTE: You can only specify column widths if you also specify the -Columns
17 | parameter.
18 |
19 | Just like the Table -Width parameter, the column widths are specified in
20 | percentages (of overall table width).
21 |
22 | NOTE: The total of all columns widths must total exactly 100 (%).
23 |
24 | The following example retrieves all local services, displaying the Name,
25 | DisplayName and Status properties. The column width for the Name property
26 | is set to 30%, the column width for the DisplayName property is set to 50%
27 | and the Status property column width set to 20%.
28 |
29 | NOTE: It is recommended that you set column widths on all tables to ensure
30 | consistent formatting between HTML and Word outputs.
31 |
32 | NOTE: Column widths are not implemented for Text output rendering as they
33 | are not supported/implemented in the 'Format-Table' cmdlet.
34 | #>
35 | Get-Service | Table -Columns Name,DisplayName,Status -ColumnWidths 30,50,20
36 | }
37 | $example15 | Export-Document -Path $Path -Format $Format -PassThru:$PassThru
38 |
--------------------------------------------------------------------------------
/Examples/Example03.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding()]
2 | param (
3 | [System.String[]] $Format = 'Html',
4 | [System.String] $Path = '~\Desktop',
5 | [System.Management.Automation.SwitchParameter] $PassThru
6 | )
7 |
8 | Import-Module PScribo -Force -Verbose:$false
9 |
10 | Document -Name 'PScribo Example 3' {
11 |
12 | <#
13 | By default, a PScribo document will default to an A4 page size. The default top and bottom
14 | pages margins are configured at 25.4mm (or 1 inch). The default left and right page margins
15 | are set at 19.05mm (or 3/4 inch).
16 |
17 | You can override the defaults with the 'DocumentOption' cmdlet/keyword. The following sets the
18 | page size to US Letter.
19 | #>
20 | DocumentOption -PageSize Letter
21 |
22 | <#
23 | The page margins are specified in points (pt). The follow cmdlet sets all page margins to
24 | 12.7mm (or 0.5 inch).
25 | #>
26 | DocumentOption -Margin 36
27 |
28 | <#
29 | The top and bottom page margins can be set independently from the left and right margin. The
30 | following configures the top/bottom page margin to 19.05mm (3/4 inch) and the left/right page
31 | margin to 12.7mm (0.5 inch).
32 | #>
33 | DocumentOption -MarginTopAndBottom 54 -MarginLeftAndRight 36
34 |
35 | <#
36 | Multiple options can be specified in a single call to 'DocumentOption', e.g. setting the
37 | page size and margins like so:
38 | #>
39 | DocumentOption -PageSize Letter -MarginTopAndBottom 54 -MarginLeftAndRight 36
40 |
41 | } | Export-Document -Path $Path -Format $Format -PassThru:$PassThru
42 |
--------------------------------------------------------------------------------
/Tests/Plugins/Html/Out-HtmlStyle.Tests.ps1:
--------------------------------------------------------------------------------
1 | $here = Split-Path -Path $MyInvocation.MyCommand.Path -Parent;
2 | $pluginRoot = Split-Path -Path $here -Parent;
3 | $testRoot = Split-Path -Path $pluginRoot -Parent;
4 | $moduleRoot = Split-Path -Path $testRoot -Parent;
5 | Import-Module "$moduleRoot\PScribo.psm1" -Force;
6 |
7 | InModuleScope 'PScribo' {
8 |
9 | Describe 'Plugins\Html\Out-HtmlStyle' {
10 |
11 | It 'creates ' | Should Be $true
17 | }
18 |
19 | It 'creates page layout style by default' {
20 | $Document = Document -Name 'Test' -ScriptBlock { }
21 | $text = Out-HtmlStyle -Styles $Document.Styles -TableStyles $Document.TableStyles
22 |
23 | $text -match 'html {' | Should Be $true
24 | $text -match 'page {' | Should Be $true
25 | $text -match '@media print {' | Should Be $true
26 | }
27 |
28 | It "suppresses page layout style when 'Options.NoPageLayoutSyle' specified" {
29 | $Document = Document -Name 'Test' -ScriptBlock { }
30 | $text = Out-HtmlStyle -Styles $Document.Styles -TableStyles $Document.TableStyles -NoPageLayoutStyle
31 |
32 | $text -match 'html {' | Should Be $false
33 | $text -match 'page {' | Should Be $false
34 | $text -match '@media print {' | Should Be $false
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Tests/Plugins/Text/Out-TextLineBreak.Tests.ps1:
--------------------------------------------------------------------------------
1 | $here = Split-Path -Path $MyInvocation.MyCommand.Path -Parent;
2 | $pluginRoot = Split-Path -Path $here -Parent;
3 | $testRoot = Split-Path -Path $pluginRoot -Parent;
4 | $moduleRoot = Split-Path -Path $testRoot -Parent;
5 | Import-Module "$moduleRoot\PScribo.psm1" -Force;
6 |
7 | InModuleScope 'PScribo' {
8 |
9 | $isNix = $false
10 | if (($PSVersionTable['PSEdition'] -eq 'Core') -and (-not $IsWindows))
11 | {
12 | $isNix = $true
13 | }
14 |
15 |
16 | Describe 'Plugins\Text\Out-TextLineBreak' {
17 |
18 | ## Scaffold document options
19 | $pscriboDocument = Document -Name 'TestDocument' -ScriptBlock {}
20 | $Options = New-PScriboTextOption;
21 |
22 | It 'Defaults to 120 and includes new line' {
23 | $expected = 122
24 | if ($isNix) { $expected -= 1 }
25 |
26 | $l = Out-TextLineBreak
27 |
28 | $l.Length | Should Be $expected
29 | }
30 |
31 | It 'Truncates to 40 and includes new line' {
32 | $Options = New-PScriboTextOption -TextWidth 40 -SeparatorWidth 40
33 | $expected = 42
34 | if ($isNix) { $expected -= 1 }
35 |
36 | $l = Out-TextLineBreak
37 |
38 | $l.Length | Should Be $expected
39 | }
40 |
41 | It 'Wraps lines and includes new line' {
42 | $Options = New-PScriboTextOption -TextWidth 40 -SeparatorWidth 80
43 | $expected = 84
44 | if ($isNix) { $expected -= 2 }
45 |
46 | $l = Out-TextLineBreak
47 |
48 | $l.Length | Should Be $expected
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Src/Plugins/Xml/Out-XmlTable.ps1:
--------------------------------------------------------------------------------
1 | function Out-XmlTable
2 | {
3 | <#
4 | .SYNOPSIS
5 | Output formatted Xml table.
6 | #>
7 | [CmdletBinding()]
8 | param
9 | (
10 | ## PScribo table object
11 | [Parameter(Mandatory, ValueFromPipeline)]
12 | [ValidateNotNull()]
13 | [System.Management.Automation.PSObject] $Table
14 | )
15 | process
16 | {
17 | $tableId = ($Table.Id -replace '[^a-z0-9-_\.]','').ToLower()
18 | $tableElement = $element.AppendChild($xmlDocument.CreateElement($tableId))
19 | [ref] $null = $tableElement.SetAttribute('name', $Table.Name)
20 |
21 | foreach ($row in $Table.Rows)
22 | {
23 | $groupElement = $tableElement.AppendChild($xmlDocument.CreateElement('group'))
24 | foreach ($property in $row.PSObject.Properties)
25 | {
26 | if (-not ($property.Name).EndsWith('__Style', 'CurrentCultureIgnoreCase'))
27 | {
28 | $propertyId = ($property.Name -replace '[^a-z0-9-_\.]','').ToLower()
29 | $rowElement = $groupElement.AppendChild($xmlDocument.CreateElement($propertyId))
30 | ## Only add the Name attribute if there's a difference
31 | if ($property.Name -ne $propertyId)
32 | {
33 | [ref] $null = $rowElement.SetAttribute('name', $property.Name)
34 | }
35 | [ref] $null = $rowElement.AppendChild($xmlDocument.CreateTextNode($row.($property.Name)))
36 | }
37 | }
38 | }
39 |
40 | return $tableElement
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Src/Plugins/Word/Get-WordSettingsDocument.ps1:
--------------------------------------------------------------------------------
1 | function Get-WordSettingsDocument
2 | {
3 | <#
4 | .SYNOPSIS
5 | Outputs Office Open XML settings document
6 | #>
7 | [CmdletBinding()]
8 | [OutputType([System.Xml.XmlDocument])]
9 | param
10 | (
11 | [Parameter()]
12 | [System.Management.Automation.SwitchParameter] $UpdateFields
13 | )
14 | process
15 | {
16 | ## Create the Style.xml document
17 | $xmlns = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'
18 | $settingsDocument = New-Object -TypeName 'System.Xml.XmlDocument'
19 | [ref] $null = $settingsDocument.AppendChild($settingsDocument.CreateXmlDeclaration('1.0', 'utf-8', 'yes'))
20 | $settings = $settingsDocument.AppendChild($settingsDocument.CreateElement('w', 'settings', $xmlns))
21 |
22 | ## Set compatibility mode to Word 2013
23 | $compat = $settings.AppendChild($settingsDocument.CreateElement('w', 'compat', $xmlns))
24 | $compatSetting = $compat.AppendChild($settingsDocument.CreateElement('w', 'compatSetting', $xmlns))
25 | [ref] $null = $compatSetting.SetAttribute('name', $xmlns, 'compatibilityMode')
26 | [ref] $null = $compatSetting.SetAttribute('uri', $xmlns, 'http://schemas.microsoft.com/office/word')
27 | [ref] $null = $compatSetting.SetAttribute('val', $xmlns, 15)
28 |
29 | if ($UpdateFields)
30 | {
31 | $wupdateFields = $settings.AppendChild($settingsDocument.CreateElement('w', 'updateFields', $xmlns))
32 | [ref] $null = $wupdateFields.SetAttribute('val', $xmlns, 'true')
33 | }
34 |
35 | return $settingsDocument
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Examples/Example01.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding()]
2 | param (
3 | [System.String] $Path = '~\Desktop\Example1.CliXml',
4 | [System.Management.Automation.SwitchParameter] $PassThru
5 | )
6 |
7 | <#
8 | From Powershell v3 onwards, the module should not need to be explicitly imported. It is included
9 | here to avoid any ambiguity.
10 | #>
11 | Import-Module PScribo -Force -Verbose:$false
12 |
13 | <#
14 | We create a PScribo document with the 'Document' cmdlet. Inside the supplied script block, you can include any
15 | standard Powershell code as well as additional PScribo content, such as paragraphs. The following code creates a
16 | new blank document named 'PScribo Example 1', storing it in the $example1 variable.
17 |
18 | When documents are exported, they are exported using the name of the document appended with the extension of the
19 | plugin. For example, exporting 'PScribo Example 1' to a Word document results in a 'PScribo Example 1.docx' file.
20 | #>
21 |
22 | $example1 = Document -Name 'PScribo Example 1' {
23 | <#
24 | This creates a single paragraph within the 'Example 1' document
25 | #>
26 | Paragraph 'This is an example that adds a single paragraph to the document that will be styled with the default style.'
27 | }
28 |
29 | <#
30 | If needed the PScribo document stored in variable $example1 could be exported via the Export-CliXml cmdlet. This would
31 | permit the creation of a document on one machine, and converted into an external document format on another. The following
32 | command will export the 'PScribo Example 1' document to a file named Example1.CliXml on the desktop.
33 | #>
34 | $example1 | Export-Clixml -Depth 128 -Path $Path -Force
35 |
--------------------------------------------------------------------------------
/Tests/Plugins/Text/Out-TextPageBreak.Tests.ps1:
--------------------------------------------------------------------------------
1 | $here = Split-Path -Path $MyInvocation.MyCommand.Path -Parent;
2 | $pluginRoot = Split-Path -Path $here -Parent;
3 | $testRoot = Split-Path -Path $pluginRoot -Parent;
4 | $moduleRoot = Split-Path -Path $testRoot -Parent;
5 | Import-Module "$moduleRoot\PScribo.psm1" -Force;
6 |
7 | InModuleScope 'PScribo' {
8 |
9 | $isNix = $false
10 | if (($PSVersionTable['PSEdition'] -eq 'Core') -and (-not $IsWindows))
11 | {
12 | $isNix = $true
13 | }
14 |
15 |
16 | Describe 'Plugins\Text\Out-TextPageBreak' {
17 |
18 | ## Scaffold document options
19 | $Document = Document -Name 'TestDocument' -ScriptBlock {}
20 | $script:currentPageNumber = 1
21 | $Options = New-PScriboTextOption
22 |
23 | It 'Defaults to 120 and includes 2 new lines' {
24 | $expected = 124
25 | if ($isNix) { $expected -= 2 }
26 |
27 | $l = Out-TextPageBreak
28 |
29 | $l.Length | Should Be $expected
30 | }
31 |
32 | It 'Truncates to 40 and includes 2 new lines' {
33 | $Options = New-PScriboTextOption -TextWidth 40 -SeparatorWidth 40
34 | $expected = 44
35 | if ($isNix) { $expected -= 2 }
36 |
37 | $l = Out-TextPageBreak
38 |
39 | $l.Length | Should Be $expected
40 | }
41 |
42 | It 'Wraps lines and includes new line' {
43 | $Options = New-PScriboTextOption -TextWidth 40 -SeparatorWidth 80
44 | $expected = 86
45 | if ($isNix) { $expected -= 3 }
46 |
47 | $l = Out-TextPageBreak
48 |
49 | $l.Length | Should Be $expected
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Src/Private/Merge-PScriboPluginOption.ps1:
--------------------------------------------------------------------------------
1 | function Merge-PScriboPluginOption
2 | {
3 | <#
4 | .SYNOPSIS
5 | Merges the specified options along with the plugin-specific default options.
6 | #>
7 | [CmdletBinding()]
8 | [OutputType([System.Collections.Hashtable])]
9 | param
10 | (
11 | ## Default/document options
12 | [Parameter(Mandatory, ValueFromPipelineByPropertyName)]
13 | [AllowNull()]
14 | [System.Collections.Hashtable] $DocumentOptions,
15 |
16 | ## Default plugin options to merge
17 | [Parameter(ValueFromPipelineByPropertyName)]
18 | [System.Collections.Hashtable] $DefaultPluginOptions,
19 |
20 | ## Specified runtime plugin options
21 | [Parameter(ValueFromPipelineByPropertyName)]
22 | [AllowNull()]
23 | [System.Collections.Hashtable] $PluginOptions
24 | )
25 | process
26 | {
27 | $mergedOptions = $DocumentOptions.Clone();
28 |
29 | if ($null -ne $DefaultPluginOptions)
30 | {
31 | ## Overwrite the default document option with the plugin default option/value
32 | foreach ($option in $DefaultPluginOptions.GetEnumerator())
33 | {
34 | $mergedOptions[$($option.Key)] = $option.Value;
35 | }
36 | }
37 |
38 | if ($null -ne $PluginOptions)
39 | {
40 | ## Overwrite the default document/plugin default option/value with the specified/runtime option
41 | foreach ($option in $PluginOptions.GetEnumerator())
42 | {
43 | $mergedOptions[$($option.Key)] = $option.Value;
44 | }
45 | }
46 | return $mergedOptions;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Tests/Plugins/Word/Out-WordPageBreak.Tests.ps1:
--------------------------------------------------------------------------------
1 | $here = Split-Path -Path $MyInvocation.MyCommand.Path -Parent;
2 | $pluginsRoot = Split-Path -Path $here -Parent;
3 | $testRoot = Split-Path -Path $pluginsRoot -Parent;
4 | $moduleRoot = Split-Path -Path $testRoot -Parent;
5 | Import-Module "$moduleRoot\PScribo.psm1" -Force;
6 |
7 | InModuleScope 'PScribo' {
8 |
9 | function GetMatch
10 | {
11 | [CmdletBinding()]
12 | param
13 | (
14 | [System.String] $String,
15 | [System.Management.Automation.SwitchParameter] $Complete
16 | )
17 | Write-Verbose "Pre Match : '$String'"
18 | $matchString = $String.Replace('/','\/')
19 | if (-not $String.StartsWith('^'))
20 | {
21 | $matchString = $matchString.Replace('[..]','[\s\S]+')
22 | $matchString = $matchString.Replace('[??]','([\s\S]+)?')
23 | if ($Complete)
24 | {
25 | $matchString = '^{0}<\/w:test>$' -f $matchString
26 | }
27 | }
28 | Write-Verbose "Post Match: '$matchString'"
29 | return $matchString
30 | }
31 |
32 | Describe 'Plugins\Word\Out-WordPageBreak' {
33 |
34 | It 'outputs ""' {
35 | $document = Document -Name 'TestDocument' {
36 | PageBreak
37 | }
38 |
39 | $testDocument = Get-WordDocument -Document $document
40 |
41 | $expected = GetMatch ''
42 | $testDocument.OuterXml | Should Match $expected
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Examples/Example28.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding()]
2 | param (
3 | [System.String[]] $Format = 'Html',
4 | [System.String] $Path = '~\Desktop',
5 | [System.Management.Automation.SwitchParameter] $PassThru
6 | )
7 |
8 | Import-Module PScribo -Force -Verbose:$false
9 |
10 | $example28 = Document -Name 'PScribo Example 28' {
11 |
12 | <#
13 | Custom styling can also be applied to individual cells within a table. To
14 | flag an individual object property to apply a different style, an additional
15 | property must be added to the object(s). Instead of adding a '__Style' property
16 | add a '__Style' string property.
17 |
18 | For example, to style a service 'Name' property with a custom style, add an
19 | additional property called 'Name__Style' with the style to apply.
20 |
21 | NOTE: Individual cell styling will override any row style applied via the
22 | '__Style' property.
23 |
24 | How the properties are added does not matter. However, the Set-Style cmdlet
25 | can also apply a specified style to one or more object properties with
26 | the -Property parameter.
27 |
28 | The following example styles the individual table cells wherever the service
29 | status is not 'Running'.
30 | #>
31 | Style -Name StoppedService -Color White -BackgroundColor Firebrick
32 |
33 | $services = Get-Service
34 | $services | Where-Object { $_.Status -ne 'Running' } | Set-Style -Style 'StoppedService' -Property 'Status'
35 |
36 | Table -InputObject $services -Columns Name,DisplayName,Status -Headers 'Name','Display Name','State'
37 | }
38 | $example28 | Export-Document -Path $Path -Format $Format -PassThru:$PassThru
39 |
--------------------------------------------------------------------------------
/Examples/Example27.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding()]
2 | param (
3 | [System.String[]] $Format = 'Html',
4 | [System.String] $Path = '~\Desktop',
5 | [System.Management.Automation.SwitchParameter] $PassThru
6 | )
7 |
8 | Import-Module PScribo -Force -Verbose:$false
9 |
10 | $example27 = Document -Name 'PScribo Example 27' {
11 |
12 | <#
13 | Custom styling can also be applied to rows of one or more hashtables.
14 |
15 | The following defines a custom style that we will apply to particular objects
16 | within the collection.
17 | #>
18 | Style -Name StoppedService -Color White -BackgroundColor Firebrick
19 |
20 | <#
21 | To apply a style to a particular hashtable, just ensure that a '__Style' key
22 | is defined with the required style name to apply to the row!
23 |
24 | In the following example, the first and last rows in the array of hashtables
25 | will be styled with the 'StoppedService' style.
26 |
27 | NOTE: How the '__Style' key is added to a hashtable is up to you. It could
28 | be added programatically etc.
29 | #>
30 | $hashtableArray = @(
31 | [Ordered] @{ 'Column 1' = 'Some random text'; 'Column2' = 345; 'Custom Property' = $true; '__Style' = 'StoppedService'; }
32 | [Ordered] @{ 'Column 1' = 'Random some text'; 'Column2' = 16; 'Custom Property' = $false; }
33 | [Ordered] @{ 'Column 1' = 'Random text some'; 'Column2' = 241; 'Custom Property' = $true; }
34 | [Ordered] @{ 'Column 1' = 'Text random some'; 'Column2' = 1GB; 'Custom Property' = $true; '__Style' = 'StoppedService'; }
35 | )
36 | Table -Hashtable $hashtableArray
37 | }
38 | $example27 | Export-Document -Path $Path -Format $Format -PassThru:$PassThru
39 |
--------------------------------------------------------------------------------
/en-US/about_PScribo.help.txt:
--------------------------------------------------------------------------------
1 | TOPIC
2 | PScribo
3 |
4 | SYNOPSIS
5 | PScribo is a documentation framework for Windows PowerShell and PowerShell (Core).
6 |
7 | DESCRIPTION
8 | PScribo is an open source project that implements a documentation domain-specific-language (DSL) for Windows
9 | Powershell. The latest version is available at https://github.com/iainbrighton/PScribo.
10 |
11 | PScribo provides a set of functions that make it easy to create a document-like structure within Powershell without
12 | having to handle individual output formatting. A document's layout and contents only need to defined once. After
13 | creation, the document can be exported to one or more formats simultaneously. For more detailed infomation on the
14 | documentation DSL, see about_PScriboDocument.
15 |
16 | Pscribo can export documentation in a variety of formats and currently supports creation of text, Html and Word
17 | formats. Additional "plugins" can be created to support future formats if required. For more detailed information
18 | on plugins, see about_PScriboPlugins.
19 |
20 | PScribo is available as a Powershell module and supported on both Windows PowerShell and PowerShell (Core).
21 |
22 | CREATING A PSCRIBO DOCUMENT
23 | To start using PScribo, you need to either install the PScribo module in your Powershell module path or download
24 | the PScribo bundle.
25 |
26 | OTHER EXAMPLES
27 | Included in the PScribo module (not the bundle) are some heavily documented example scripts in the .\Examples
28 | directory. For an index of the examples, see about_PScriboExamples.
29 |
30 | SEE ALSO
31 | about_PScriboDocument
32 | about_PScriboStyles
33 | about_PScriboPlugins
34 | about_PScriboExamples
35 |
--------------------------------------------------------------------------------
/en-US/about_JsonPlugin.help.txt:
--------------------------------------------------------------------------------
1 | TOPIC
2 | Json Plugin
3 |
4 | SYNOPSIS
5 | PScribo supports outputting JSON-formatted text (.json) documents.
6 |
7 | DESCRIPTION
8 | PScribo can output JSON-formatted text documents with multiple file encodings. The benefit of JSON is it can be consumed by 3rd party tools after the fact to ingest the information contained in the report.
9 |
10 | KNOWN LIMITATIONS
11 | There are some restrictions which means that some PScribo functionality cannot either be partially or fully implemented:
12 |
13 | - PScribo style elements are ignored
14 | - This includes section numbering as it better ensures each section is unique which facilitates easier parsing.
15 | - The following PScribo types are not supported as there is no provision for them in JSON:
16 | - Image
17 | - PageBreak
18 | - LineBreak
19 | - BlankLine
20 | - Headers and footers are only shown once at the beginning/end of the generated document
21 | - Sections at the same hierarchical level using the NOTOC* header cannot have the same name. This is a PowerShell Dictionary limitation.
22 |
23 | PLUGIN OPTIONS
24 | The Text plugin accepts the following output customisation options:
25 |
26 | Encoding [string] : Specifies the file encoding to use. Supported values are 'ASCII', 'Unicode',
27 | 'UTF7' and 'UTF8'. If not specified, defaults to 'ASCII'.
28 |
29 | Output customisations are passed to the Export-Document cmdlet as a hashtable, e.g.
30 |
31 | PS> $document | Export-Document -Format Text -Options @{ Encoding = 'ASCII' }
32 |
33 | SEE ALSO
34 | about_PscriboPlugins
35 | about_HtmlPlugin
36 | about_WordPlugin
37 | about_TextPlugin
38 |
--------------------------------------------------------------------------------
/Src/Plugins/Word/Get-WordParagraphRun.ps1:
--------------------------------------------------------------------------------
1 | function Get-WordParagraphRun
2 | {
3 | <#
4 | .SYNOPSIS
5 | Returns an array of strings, split on tokens (PageNumber/TotalPages).
6 | #>
7 | [CmdletBinding()]
8 | [OutputType([System.String[]])]
9 | param
10 | (
11 | [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
12 | [AllowEmptyString()]
13 | [System.String] $Text,
14 |
15 | [Parameter(ValueFromPipelineByPropertyName)]
16 | [System.Management.Automation.SwitchParameter] $NoSpace
17 | )
18 | process
19 | {
20 | $pageNumberMatch = ''
21 | $totalPagesMatch = ''
22 | $runs = New-Object -TypeName 'System.Collections.ArrayList'
23 |
24 | if (-not $NoSpace)
25 | {
26 | $Text = '{0} ' -f $Text
27 | }
28 |
29 | $pageNumbers = $Text -isplit $pageNumberMatch
30 | for ($pn = 0; $pn -lt $pageNumbers.Count; $pn++)
31 | {
32 | $totalPages = $pageNumbers[$pn] -isplit $totalPagesMatch
33 | for ($tp = 0; $tp -lt $totalPages.Count; $tp++)
34 | {
35 | if (-not [System.String]::IsNullOrWhitespace($totalPages[$tp]))
36 | {
37 | $null = $runs.Add($totalPages[$tp])
38 | }
39 | if ($tp -lt ($totalPages.Count -1))
40 | {
41 | $null = $runs.Add('')
42 | }
43 | }
44 |
45 | if ($pn -lt ($pageNumbers.Count -1))
46 | {
47 | $null = $runs.Add('')
48 | }
49 | }
50 |
51 | return $runs.ToArray()
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/Tests/Plugins/Json/Out-JsonDocument.Tests.ps1:
--------------------------------------------------------------------------------
1 | $here = Split-Path -Path $MyInvocation.MyCommand.Path -Parent;
2 | $pluginRoot = Split-Path -Path $here -Parent;
3 | $testRoot = Split-Path -Path $pluginRoot -Parent;
4 | $moduleRoot = Split-Path -Path $testRoot -Parent;
5 | Import-Module "$moduleRoot\PScribo.psm1" -Force;
6 |
7 | InModuleScope 'PScribo' {
8 |
9 | Describe 'Plugins\Json\Out-JsonDocument' {
10 |
11 | $path = (Get-PSDrive -Name TestDrive).Root;
12 |
13 | It 'calls Out-JsonSection' {
14 | Mock -CommandName Out-JsonSection
15 |
16 | Document -Name 'TestDocument' -ScriptBlock { Section -Name 'TestSection' -ScriptBlock { } } | Out-JsonDocument -Path $path
17 |
18 | Assert-MockCalled -CommandName Out-JsonSection -Exactly 1
19 | }
20 |
21 | It 'calls Out-JsonParagraph' {
22 | Mock -CommandName Out-JsonParagraph
23 |
24 | Document -Name 'TestDocument' -ScriptBlock { Paragraph 'TestParagraph' } | Out-JsonDocument -Path $path
25 |
26 | Assert-MockCalled -CommandName Out-JsonParagraph -Exactly 1
27 | }
28 |
29 | It 'calls Out-JsonTable' {
30 | Mock -CommandName Out-JsonTable
31 |
32 | Document -Name 'TestDocument' -ScriptBlock { Get-Process | Select-Object -First 1 | Table 'TestTable' } | Out-JsonDocument -Path $path
33 |
34 | Assert-MockCalled -CommandName Out-JsonTable -Exactly 1
35 | }
36 |
37 | It 'calls Out-JsonTOC' {
38 | Mock -CommandName Out-JsonTOC
39 |
40 | Document -Name 'TestDocument' -ScriptBlock { TOC -Name 'TestTOC'; } | Out-JsonDocument -Path $path
41 |
42 | Assert-MockCalled -CommandName Out-JsonTOC -Exactly 1
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Src/Private/Invoke-PScriboListLevel.ps1:
--------------------------------------------------------------------------------
1 | function Invoke-PScriboListLevel
2 | {
3 | <#
4 | .SYNOPSIS
5 | Nested function that processes each nested list numbering.
6 | #>
7 | [CmdletBinding()]
8 | param
9 | (
10 | [Parameter(Mandatory)]
11 | [ValidateNotNull()]
12 | [System.Management.Automation.PSObject] $List,
13 |
14 | [Parameter(Mandatory)]
15 | [AllowEmptyString()]
16 | [System.String] $Number
17 | )
18 | process
19 | {
20 | $level = $Number.Split('.').Count +1
21 | $processingListPadding = ''.PadRight($level -1, ' ')
22 | $processingListMessage = $localized.ProcessingList -f $List.Name
23 | Write-PScriboMessage -Message ('{0}{1}' -f $processingListPadding, $processingListMessage)
24 |
25 | $itemNumber = 0
26 | $numberString = $Number
27 | $hasItem = $false
28 |
29 | foreach ($item in $List.Items)
30 | {
31 | if ($item.Type -eq 'PScribo.Item')
32 | {
33 | $itemNumber++
34 | $item.Level = $level
35 | $item.Index = $itemNumber
36 | $item.Number = ('{0}.{1}' -f $Number, $itemNumber).TrimStart('.')
37 |
38 | $numberString = $item.Number
39 | $hasItem = $true
40 | }
41 | elseif ($item.Type -eq 'PScribo.List')
42 | {
43 | if ($hasItem)
44 | {
45 | Invoke-PScriboListLevel -List $item -Number $numberString
46 | }
47 | else
48 | {
49 | Write-PScriboMessage -Message $localized.NoPriorListItemWarning -IsWarning
50 | }
51 | }
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/Src/Private/Get-PScriboHeaderFooter.ps1:
--------------------------------------------------------------------------------
1 | function Get-PScriboHeaderFooter
2 | {
3 | <#
4 | .SYNOPSIS
5 | Returns the specified PScribo header/footer object.
6 | #>
7 | [CmdletBinding()]
8 | param
9 | (
10 | [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'DefaultHeader')]
11 | [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'FirstPageHeader')]
12 | [System.Management.Automation.SwitchParameter] $Header,
13 |
14 | [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'DefaultFooter')]
15 | [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'FirstPageFooter')]
16 | [System.Management.Automation.SwitchParameter] $Footer,
17 |
18 | [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'FirstPageHeader')]
19 | [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'FirstPageFooter')]
20 | [System.Management.Automation.SwitchParameter] $FirstPage
21 | )
22 | process
23 | {
24 | if ($FirstPage)
25 | {
26 | if ($Header -and ($Document.Header.HasFirstPageHeader))
27 | {
28 | return $Document.Header.FirstPageHeader
29 | }
30 | elseif ($Footer -and ($Document.Footer.HasFirstPageFooter))
31 | {
32 | return $Document.Footer.FirstPageFooter
33 | }
34 | }
35 | else
36 | {
37 | if ($Header -and ($Document.Header.HasDefaultHeader))
38 | {
39 | return $Document.Header.DefaultHeader
40 | }
41 | elseif ($Footer -and ($Document.Footer.HasDefaultFooter))
42 | {
43 | return $Document.Footer.DefaultFooter
44 | }
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/Src/Plugins/Word/Get-WordTableConditionalFormattingValue.ps1:
--------------------------------------------------------------------------------
1 | function Get-WordTableConditionalFormattingValue
2 | {
3 | <#
4 | .SYNOPSIS
5 | Generates legacy table conditioning formatting value (for LibreOffice).
6 | #>
7 | [CmdletBinding()]
8 | [OutputType([System.Int32])]
9 | param
10 | (
11 | [Parameter(ValueFromPipelineByPropertyName)]
12 | [System.Management.Automation.SwitchParameter] $HasFirstRow,
13 |
14 | [Parameter(ValueFromPipelineByPropertyName)]
15 | [System.Management.Automation.SwitchParameter] $HasLastRow,
16 |
17 | [Parameter(ValueFromPipelineByPropertyName)]
18 | [System.Management.Automation.SwitchParameter] $HasFirstColumn,
19 |
20 | [Parameter(ValueFromPipelineByPropertyName)]
21 | [System.Management.Automation.SwitchParameter] $HasLastColumn,
22 |
23 | [Parameter(ValueFromPipelineByPropertyName)]
24 | [System.Management.Automation.SwitchParameter] $NoHorizontalBand,
25 |
26 | [Parameter(ValueFromPipelineByPropertyName)]
27 | [System.Management.Automation.SwitchParameter] $NoVerticalBand
28 | )
29 | process
30 | {
31 | $val = 0
32 | if ($HasFirstRow)
33 | {
34 | $val = $val -bor 0x20
35 | }
36 | if ($HasLastRow)
37 | {
38 | $val = $val -bor 0x40
39 | }
40 | if ($HasFirstColumn)
41 | {
42 | $val = $val -bor 0x80
43 | }
44 | if ($HasLastColumn)
45 | {
46 | $val = $val -bor 0x100
47 | }
48 | if ($NoHorizontalBand)
49 | {
50 | $val = $val -bor 0x200
51 | }
52 | if ($NoVerticalBand)
53 | {
54 | $val = $val -bor 0x400
55 | }
56 | return $val
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/Src/Private/Get-ImageMimeType.ps1:
--------------------------------------------------------------------------------
1 | function Get-ImageMimeType
2 | {
3 | <#
4 | .SYNOPSIS
5 | Returns an image's Mime type
6 | #>
7 | [CmdletBinding()]
8 | [OutputType([System.String])]
9 | param
10 | (
11 | [Parameter(Mandatory, ValueFromPipeline)]
12 | [System.Drawing.Image] $Image
13 | )
14 | process
15 | {
16 | if ($Image.RawFormat.Equals([System.Drawing.Imaging.ImageFormat]::Jpeg))
17 | {
18 | return 'image/jpeg'
19 | }
20 | elseif ($Image.RawFormat.Equals([System.Drawing.Imaging.ImageFormat]::Png))
21 | {
22 | return 'image/png'
23 | }
24 | elseif ($Image.RawFormat.Equals([System.Drawing.Imaging.ImageFormat]::Bmp))
25 | {
26 | return 'image/bmp'
27 | }
28 | elseif ($Image.RawFormat.Equals([System.Drawing.Imaging.ImageFormat]::Emf))
29 | {
30 | return 'image/emf'
31 | }
32 | elseif ($Image.RawFormat.Equals([System.Drawing.Imaging.ImageFormat]::Gif))
33 | {
34 | return 'image/gif'
35 | }
36 | elseif ($Image.RawFormat.Equals([System.Drawing.Imaging.ImageFormat]::Icon))
37 | {
38 | return 'image/icon'
39 | }
40 | elseif ($Image.RawFormat.Equals([System.Drawing.Imaging.ImageFormat]::Tiff))
41 | {
42 | return 'image/tiff'
43 | }
44 | elseif ($Image.RawFormat.Equals([System.Drawing.Imaging.ImageFormat]::Wmf))
45 | {
46 | return 'image/wmf'
47 | }
48 | elseif ($Image.RawFormat.Equals([System.Drawing.Imaging.ImageFormat]::Exif))
49 | {
50 | return 'image/exif'
51 | }
52 | else
53 | {
54 | return 'image/unknown'
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Examples/Example16.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding()]
2 | param (
3 | [System.String[]] $Format = 'Html',
4 | [System.String] $Path = '~\Desktop',
5 | [System.Management.Automation.SwitchParameter] $PassThru
6 | )
7 |
8 | Import-Module PScribo -Force -Verbose:$false
9 |
10 | $example16 = Document -Name 'PScribo Example 16' {
11 |
12 | <#
13 | If you do not have a collection/array of objects that you wish to create
14 | a table from, PScribo supports creating a table from single ordered hashtable
15 | or an array of ordered hashtables.
16 |
17 | NOTE: You cannot pipe a single hashtable or an array of hashtables to the
18 | 'Table' cmdlet. You MUST pass the hashtable(s) via the -HashTable parameter.
19 | If you pipe the hashtable(s), the hashtable object's properties are
20 | displayed and not the hashtable key/value pairs!
21 |
22 | Creating a hashtable does permit the utilisation of spaces in the key names,
23 | requiring that the -Headers parameter does not necessarily need to be used.
24 |
25 | NOTE: This is not a standard hashtable, but a System.Collections.Specialized.OrderedDictionary
26 | object. These can be created with the [Ordered] attribute on the hashtable
27 | declaration, e.g. [Ordered] @{ Key1 = Value1; Key2 = Value2; }
28 |
29 | The following example creates a table with a single row with the hashtable keys
30 | used as the header values and the corresponding values as the first table row.
31 | #>
32 | $hashtable = [Ordered] @{
33 | 'Column 1' = 'Some random text'
34 | 'Column2' = 345
35 | 'Custom Property' = $true
36 | }
37 | Table -Hashtable $hashtable
38 | }
39 | $example16 | Export-Document -Path $Path -Format $Format -PassThru:$PassThru
40 |
--------------------------------------------------------------------------------
/Src/Plugins/Word/Get-WordStyleRunPr.ps1:
--------------------------------------------------------------------------------
1 | function Get-WordStyleRunPr
2 | {
3 | <#
4 | .SYNOPSIS
5 | Generates Word run (rPr) formatting properties
6 | #>
7 | [CmdletBinding()]
8 | [OutputType([System.Xml.XmlElement])]
9 | param
10 | (
11 | [Parameter(Mandatory)]
12 | [System.Management.Automation.PSObject] $Style,
13 |
14 | [Parameter(Mandatory)]
15 | [System.Xml.XmlDocument] $XmlDocument
16 | )
17 | process
18 | {
19 | $xmlns = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'
20 |
21 | $rPr = $XmlDocument.CreateElement('w', 'rPr', $xmlns)
22 |
23 | $rFonts = $rPr.AppendChild($XmlDocument.CreateElement('w', 'rFonts', $xmlns))
24 | [ref] $null = $rFonts.SetAttribute('ascii', $xmlns, $Style.Font[0])
25 | [ref] $null = $rFonts.SetAttribute('hAnsi', $xmlns, $Style.Font[0])
26 |
27 | if ($Style.Bold)
28 | {
29 | [ref] $null = $rPr.AppendChild($XmlDocument.CreateElement('w', 'b', $xmlns))
30 | }
31 |
32 | if ($Style.Underline)
33 | {
34 | [ref] $null = $rPr.AppendChild($XmlDocument.CreateElement('w', 'u', $xmlns))
35 | }
36 |
37 | if ($Style.Italic)
38 | {
39 | [ref] $null = $rPr.AppendChild($XmlDocument.CreateElement('w', 'i', $xmlns))
40 | }
41 |
42 | $wordColor = ConvertTo-WordColor -Color (Resolve-PScriboStyleColor -Color $Style.Color)
43 | $color = $rPr.AppendChild($XmlDocument.CreateElement('w', 'color', $xmlns))
44 | [ref] $null = $color.SetAttribute('val', $xmlns, $wordColor)
45 |
46 | $sz = $rPr.AppendChild($XmlDocument.CreateElement('w', 'sz', $xmlns))
47 | [ref] $null = $sz.SetAttribute('val', $xmlns, $Style.Size * 2)
48 |
49 | return $rPr
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Src/Plugins/Text/Out-TextParagraph.ps1:
--------------------------------------------------------------------------------
1 | function Out-TextParagraph
2 | {
3 | <#
4 | .SYNOPSIS
5 | Output formatted paragraph run.
6 | #>
7 | [CmdletBinding()]
8 | [OutputType([System.String])]
9 | param
10 | (
11 | [Parameter(Mandatory, ValueFromPipeline)]
12 | [ValidateNotNull()]
13 | [System.Management.Automation.PSObject] $Paragraph
14 | )
15 | begin
16 | {
17 | ## Fix Set-StrictMode
18 | if (-not (Test-Path -Path Variable:\Options))
19 | {
20 | $options = New-PScriboTextOption;
21 | }
22 | }
23 | process
24 | {
25 | $convertToAlignedStringParams = @{
26 | Width = $options.TextWidth
27 | Tabs = $Paragraph.Tabs
28 | Align = 'Left'
29 | }
30 |
31 | if (-not [System.String]::IsNullOrEmpty($Paragraph.Style))
32 | {
33 | $paragraphStyle = Get-PScriboDocumentStyle -Style $Paragraph.Style
34 | $convertToAlignedStringParams['Align'] = $paragraphStyle.Align
35 | }
36 |
37 | [System.Text.StringBuilder] $paragraphBuilder = New-Object -TypeName 'System.Text.StringBuilder'
38 | foreach ($paragraphRun in $Paragraph.Sections)
39 | {
40 | $text = Resolve-PScriboToken -InputObject $paragraphRun.Text
41 | [ref] $null = $paragraphBuilder.Append($text)
42 |
43 | if (($paragraphRun.IsParagraphRunEnd -eq $false) -and
44 | ($paragraphRun.NoSpace -eq $false))
45 | {
46 | [ref] $null = $paragraphBuilder.Append(' ')
47 | }
48 | }
49 |
50 | $convertToAlignedStringParams['InputObject'] = $paragraphBuilder.ToString()
51 | return (ConvertTo-AlignedString @convertToAlignedStringParams)
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/Tests/Plugins/Json/Out-JsonTable.Tests.ps1:
--------------------------------------------------------------------------------
1 | $here = Split-Path -Path $MyInvocation.MyCommand.Path -Parent;
2 | $pluginRoot = Split-Path -Path $here -Parent;
3 | $testRoot = Split-Path -Path $pluginRoot -Parent;
4 | $moduleRoot = Split-Path -Path $testRoot -Parent;
5 | Import-Module "$moduleRoot\PScribo.psm1" -Force;
6 |
7 | InModuleScope 'PScribo' {
8 |
9 | Describe 'Plugins\Json\Out-JsonTable' {
10 |
11 | ## Scaffold document options
12 | $Document = Document -Name 'TestDocument' -ScriptBlock {}
13 | $script:currentPageNumber = 1
14 | $pscriboDocument = $Document
15 |
16 | ## Context (list vs table) doesn't make a difference as they are treated the same
17 |
18 | $services = @(
19 | [Ordered] @{ Name = 'TestService1'; 'Service Name' = 'Test 1'; 'Display Name' = 'Test Service 1'; }
20 | [Ordered] @{ Name = 'TestService3'; 'Service Name' = 'Test 3'; 'Display Name' = 'Test Service 3'; }
21 | [Ordered] @{ Name = 'TestService2'; 'Service Name' = 'Test 2'; 'Display Name' = 'Test Service 2'; }
22 | )
23 |
24 | It 'Input matches output' {
25 | $expected = 3
26 |
27 | $table = Table -Hashtable $services 'Test Table' | Out-JsonTable
28 |
29 | $table.Count | Should Be $expected
30 | }
31 |
32 | It 'Caption present' {
33 | $expected = $true
34 |
35 | $table = Table -Hashtable $services 'Test Table' -Caption 'Test' | Out-JsonTable
36 |
37 | $table[0].Caption | Should Be $expected
38 | }
39 |
40 | It 'Input matches output with caption present' {
41 | $expected = 3
42 |
43 | $table = Table -Hashtable $services 'Test Table' -Caption 'Test' | Out-JsonTable
44 |
45 | $table[1].Count | Should Be $expected
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Src/Plugins/Html/Get-HtmlTableStyle.ps1:
--------------------------------------------------------------------------------
1 | function Get-HtmlTableStyle
2 | {
3 | <#
4 | .SYNOPSIS
5 | Generates html stylesheet style attributes from a PScribo document table style.
6 | #>
7 | [CmdletBinding()]
8 | [OutputType([System.String])]
9 | param
10 | (
11 | ## PScribo document table style
12 | [Parameter(Mandatory, ValueFromPipeline)]
13 | [System.Management.Automation.PSObject] $TableStyle
14 | )
15 | process
16 | {
17 | $tableStyleBuilder = New-Object -TypeName 'System.Text.StringBuilder'
18 | [ref] $null = $tableStyleBuilder.AppendFormat((Get-HtmlTablePaddingStyle -TableStyle $TableStyle))
19 | [ref] $null = $tableStyleBuilder.AppendFormat(' border-style: {0};', $TableStyle.BorderStyle.ToLower())
20 |
21 | if ($TableStyle.BorderWidth -gt 0)
22 | {
23 | $invariantBorderWidth = ConvertTo-InvariantCultureString -Object (ConvertTo-Em -Millimeter $TableStyle.BorderWidth)
24 | [ref] $null = $tableStyleBuilder.AppendFormat(' border-width: {0}rem;', $invariantBorderWidth)
25 |
26 | $borderColor = Resolve-PScriboStyleColor -Color $TableStyle.BorderColor
27 | [ref] $null = $tableStyleBuilder.AppendFormat(' border-color: #{0};', $borderColor.ToLower())
28 | }
29 |
30 | [ref] $null = $tableStyleBuilder.Append(' border-collapse: collapse;')
31 | ## is deprecated in Html5
32 | if ($TableStyle.Align -eq 'Center')
33 | {
34 | [ref] $null = $tableStyleBuilder.Append(' margin-left: auto; margin-right: auto;')
35 | }
36 | elseif ($TableStyle.Align -eq 'Right')
37 | {
38 | [ref] $null = $tableStyleBuilder.Append(' margin-left: auto; margin-right: 0;')
39 | }
40 |
41 | return $tableStyleBuilder.ToString()
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Examples/Example21.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding()]
2 | param (
3 | [System.String[]] $Format = 'Html',
4 | [System.String] $Path = '~\Desktop',
5 | [System.Management.Automation.SwitchParameter] $PassThru
6 | )
7 |
8 | Import-Module PScribo -Force -Verbose:$false
9 |
10 | $example21 = Document -Name 'PScribo Example 21' {
11 |
12 | <#
13 | Styling can also be applied to tables - just like Paragraphs and Sections. Tables
14 | support additional styling options such as borders and cell padding options.
15 |
16 | NOTE: There is a built-in "TableDefault" style. You can override the default table
17 | style just like overriding the default "Normal" paragraph style.
18 |
19 | Each table style also requires three styles; one applied to the header row, one
20 | applied to each table row and an optional alternating row style.
21 |
22 | Before table styles can be defined, the individual styles must already be defined
23 | in the document via the 'Style' cmdlet/keyword.
24 |
25 | NOTE: The "TableDefault" style uses a style called "TableDefaultHeading" for the
26 | header row, a style called "TableDefaultRow" for the row style and a style
27 | called "TableDefaultAltRow" for the alternating row style.
28 |
29 | The following defines a very simple table style named "Basic" that uses the "Normal"
30 | style for the header and all other rows, e.g. no styling!
31 |
32 | NOTE: When -AlternateRowStyle is not specified, the -RowStyle property value is
33 | used for -AlternateRowStyle property.
34 | #>
35 | TableStyle -Name 'Basic' -HeaderStyle Normal -RowStyle Normal
36 | Get-Service | Select-Object -Property Name,DisplayName,Status -First 3 | Table -Style Basic
37 | }
38 | $example21 | Export-Document -Path $Path -Format $Format -PassThru:$PassThru
39 |
--------------------------------------------------------------------------------
/Examples/Example29.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding()]
2 | param (
3 | [System.String[]] $Format = 'Html',
4 | [System.String] $Path = '~\Desktop',
5 | [System.Management.Automation.SwitchParameter] $PassThru
6 | )
7 |
8 | Import-Module PScribo -Force -Verbose:$false
9 |
10 | $example29 = Document -Name 'PScribo Example 29' {
11 |
12 | <#
13 | Custom styling can also be applied to individual keys of one or more
14 | hashtables.
15 |
16 | To apply a style to a particular hashtable key, just ensure that a
17 | '__Style' key is also defined with the style name you wish to to apply
18 | to the particular table cell.
19 |
20 | For example, to apply a "MyCustomStyle" to a 'Name' key, ensure that a
21 | 'Name__Style' key exists in the hashtable with a value of "MyCustomStyle".
22 |
23 | In the following example, the the middle two rows where key 'Custom Property' is
24 | set to $false will be highlighted with the in the array of hashtables
25 | will be styled with the 'Warning' custom style.
26 |
27 | NOTE: How the 'Custom Property__Style' key is added to a hashtable is up to you!
28 | #>
29 | Style -Name Warning -Color White -BackgroundColor Firebrick
30 |
31 | $hashtableArray = @(
32 | [Ordered] @{ 'Column 1' = 'Some random text'; 'Column2' = 345; 'Custom Property' = $true; }
33 | [Ordered] @{ 'Column 1' = 'Random some text'; 'Column2' = 16; 'Custom Property' = $false; 'Custom Property__Style' = 'Warning'; }
34 | [Ordered] @{ 'Column 1' = 'Random text some'; 'Column2' = 241; 'Custom Property' = $false; 'Custom Property__Style' = 'Warning'; }
35 | [Ordered] @{ 'Column 1' = 'Text random some'; 'Column2' = 1GB; 'Custom Property' = $true; }
36 | )
37 | Table -Hashtable $hashtableArray
38 | }
39 | $example29 | Export-Document -Path $Path -Format $Format -PassThru:$PassThru
40 |
--------------------------------------------------------------------------------
/Src/Private/New-PScriboFormattedTableRow.ps1:
--------------------------------------------------------------------------------
1 | function New-PScriboFormattedTableRow
2 | {
3 | <#
4 | .SYNOPSIS
5 | Creates a formatted table row for plugin output/rendering.
6 | #>
7 | [CmdletBinding()]
8 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions','')]
9 | [OutputType([System.Management.Automation.PSObject])]
10 | param
11 | (
12 | [Parameter(Mandatory, ValueFromPipeline)]
13 | [System.String] $TableStyle,
14 |
15 | [Parameter(ValueFromPipeline)]
16 | [AllowNull()]
17 | [System.String] $Style = $null,
18 |
19 | [Parameter(ValueFromPipeline, ParameterSetName = 'Header')]
20 | [System.Management.Automation.SwitchParameter] $IsHeaderRow,
21 |
22 | [Parameter(ValueFromPipeline, ParameterSetName = 'Row')]
23 | [System.Management.Automation.SwitchParameter] $IsAlternateRow
24 | )
25 | process
26 | {
27 | if (-not ([System.String]::IsNullOrEmpty($Style)))
28 | {
29 | ## Use the explictit style
30 | $IsStyleInherited = $false
31 | }
32 | elseif ($IsHeaderRow)
33 | {
34 | $Style = $document.TableStyles[$TableStyle].HeaderStyle
35 | $IsStyleInherited = $true
36 | }
37 | elseif ($IsAlternateRow)
38 | {
39 | $Style = $document.TableStyles[$TableStyle].AlternateRowStyle
40 | $IsStyleInherited = $true
41 | }
42 | else
43 | {
44 | $Style = $document.TableStyles[$TableStyle].RowStyle
45 | $IsStyleInherited = $true
46 | }
47 |
48 | return [PSCustomObject] @{
49 | Style = $Style;
50 | IsStyleInherited = $IsStyleInherited;
51 | Cells = New-Object -TypeName System.Collections.ArrayList;
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/Tests/Unit/Image.Tests.ps1:
--------------------------------------------------------------------------------
1 | $here = Split-Path -Path $MyInvocation.MyCommand.Path -Parent
2 | $testRoot = Split-Path -Path $here -Parent
3 | $moduleRoot = Split-Path -Path $testRoot -Parent
4 | Import-Module -Name "$moduleRoot\PScribo.psm1" -Force
5 |
6 | InModuleScope -ModuleName 'PScribo' -ScriptBlock {
7 |
8 | $testRoot = Split-Path -Path $PSScriptRoot -Parent
9 |
10 | Describe -Name 'Image' -Fixture {
11 |
12 | $pscriboDocument = Document -Name 'ScaffoldDocument' -ScriptBlock { }
13 | $testJpgFile = Join-Path -Path $testRoot -ChildPath 'TestImage.jpg'
14 | $testPngFile = Join-Path -Path $testRoot -ChildPath 'TestImage.png'
15 |
16 | It -name 'returns "PSCustomObject" object.' -test {
17 | $p = Image -Path $testJpgFile
18 | $p.GetType().Name | Should -eq 'PSCustomObject'
19 | }
20 |
21 | It -name 'creates "PScribo.Image" type.' -test {
22 | $p = Image -Path $testJpgFile
23 | $p.Type | Should -eq 'PScribo.Image'
24 | }
25 |
26 | It -name 'set MIME type "jpeg"' -test {
27 | $p = Image -Path $testJpgFile
28 | $p.MIMEType | Should -eq 'image/jpeg'
29 | }
30 |
31 | It -name 'set MIME type "png"' -test {
32 | $p = Image -Path $testPngFile
33 | $p.MIMEType | Should -eq 'image/png'
34 | }
35 |
36 | It -name 'creates image number' {
37 | $p = Image -Path $testJpgFile
38 | $p.Name | Should -match '^Image\d+$'
39 | }
40 |
41 | It -name 'sets Emu width' -test {
42 | $p = Image -Path $testJpgFile -Height 61 -Width 250
43 | $p.WidthEm | Should -eq 2381250
44 | }
45 |
46 | It -name 'sets Emu Height' -test {
47 | $p = Image -Path $testJpgFile -Height 61 -Width 250
48 | $p.HeightEm | Should -eq 581025
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Src/Plugins/Word/Get-WordNumberingDocument.ps1:
--------------------------------------------------------------------------------
1 | function Get-WordNumberingDocument
2 | {
3 | <#
4 | .SYNOPSIS
5 | Outputs Office Open XML numbering document
6 | #>
7 | [CmdletBinding()]
8 | [OutputType([System.Xml.XmlDocument])]
9 | param
10 | (
11 | ## PScribo document styles
12 | [Parameter(Mandatory, ValueFromPipeline)]
13 | [AllowEmptyCollection()]
14 | [System.Collections.ArrayList] $Lists
15 | )
16 | process
17 | {
18 | ## Create the numbering.xml document
19 | $xmlns = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'
20 | $xmlDocument = New-Object -TypeName 'System.Xml.XmlDocument'
21 | [ref] $null = $xmlDocument.AppendChild($XmlDocument.CreateXmlDeclaration('1.0', 'utf-8', 'yes'))
22 | $numbering = $xmlDocument.AppendChild($xmlDocument.CreateElement('w', 'numbering', $xmlns))
23 | [ref] $null = $xmlDocument.DocumentElement.SetAttribute('xmlns:mc', 'http://schemas.openxmlformats.org/markup-compatibility/2006')
24 | [ref] $null = $xmlDocument.DocumentElement.SetAttribute('xmlns:w14', 'http://schemas.microsoft.com/office/word/2010/wordml')
25 |
26 | foreach ($list in $Lists.GetEnumerator())
27 | {
28 | $abstractNum = Get-WordNumberStyle -List $list -XmlDocument $xmlDocument
29 | [ref] $null = $numbering.AppendChild($abstractNum)
30 | }
31 |
32 | foreach ($list in $Lists.GetEnumerator())
33 | {
34 | $num = $numbering.AppendChild($xmlDocument.CreateElement('w', 'num', $xmlns))
35 | [ref] $null = $num.SetAttribute('numId', $xmlns, $list.Number)
36 | $abstractNumId = $num.AppendChild($xmlDocument.CreateElement('w', 'abstractNumId', $xmlns))
37 | [ref] $null = $abstractNumId.SetAttribute('val', $xmlns, $list.Number -1)
38 | }
39 |
40 | return $xmlDocument
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Examples/Example36.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding()]
2 | param (
3 | [System.String[]] $Format = 'Html',
4 | [System.String] $Path = '~\Desktop',
5 | [System.Management.Automation.SwitchParameter] $PassThru
6 | )
7 |
8 | Import-Module PScribo -Force -Verbose:$false
9 |
10 | $example36 = Document -Name 'PScribo Example 36' {
11 |
12 | <#
13 | Headers and footers are displayed inside the page margin. To increase
14 | the available space, the top and bottom margins can be adjusted to
15 | compensate.
16 | #>
17 | DocumentOption -MarginTopAndBottom 36 -MarginLeftAndRight 54
18 |
19 | <#
20 | There are no default styles defined for headers and footers, but they
21 | can be styled in the standard way we style paragraphs and tables.
22 | #>
23 | Style -Name 'Header' -Size 12 -Color 0072af -Align Center -Bold
24 | Header -Default -IncludeOnFirstPage {
25 | Paragraph -Style 'Header' 'PScribo Example 36'
26 | }
27 |
28 | <#
29 | It is also possible to define a custom style and assign it to a
30 | header and/or footer.
31 | #>
32 | Style -Name 'CustomFooter' -Size 11 -Color 0072af -Align Center -Italic
33 | Footer -Default {
34 | Paragraph -Style 'CustomFooter' 'Page of '
35 | }
36 |
37 | Get-Service |
38 | Select-Object -First 25 -Property 'Name','DisplayName','Status' |
39 | Table -ColumnWidths 42,42,16
40 |
41 | PageBreak
42 |
43 | Get-Service |
44 | Select-Object -First 25 -Skip 25 -Property 'Name','DisplayName','Status' |
45 | Table -ColumnWidths 42,42,16
46 |
47 | PageBreak
48 |
49 | Get-Service |
50 | Select-Object -First 25 -Skip 50 -Property 'Name','DisplayName','Status' |
51 | Table -ColumnWidths 42,42,16
52 |
53 | }
54 | $example36 | Export-Document -Path $Path -Format $Format -PassThru:$PassThru
55 |
--------------------------------------------------------------------------------
/Tests/Unit/TOC.Tests.ps1:
--------------------------------------------------------------------------------
1 | $here = Split-Path -Path $MyInvocation.MyCommand.Path -Parent;
2 | $testRoot = Split-Path -Path $here -Parent;
3 | $moduleRoot = Split-Path -Path $testRoot -Parent;
4 | Import-Module "$moduleRoot\PScribo.psm1" -Force;
5 |
6 | InModuleScope 'PScribo' {
7 |
8 | Describe 'TOC' {
9 | $pscriboDocument = Document 'ScaffoldDocument' {};
10 |
11 | Context 'By Named Parameter' {
12 |
13 | It 'returns a PSCustomObject object' {
14 | $t = TOC -Name Test
15 |
16 | $t.GetType().Name | Should Be 'PSCustomObject'
17 | $t.Type | Should Be 'PScribo.TOC'
18 | }
19 |
20 | It 'creates a TOC by named -Name parameter' {
21 | $text = 'Simple paragraph.'
22 |
23 | $t = TOC -Name $text
24 |
25 | $t.Name | Should Be $text
26 | }
27 |
28 | It 'creates a TOC by named -Name parameter with enabled -ForceUppercaseSection option' {
29 | $pscriboDocument.Options['ForceUppercaseSection'] = $true
30 | $text = 'Simple paragraph.'
31 |
32 | $t = TOC -Name $text
33 |
34 | $t.Name | Should Be $text.ToUpper()
35 | }
36 | }
37 |
38 | Context 'By Positional Parameter' {
39 |
40 | It 'creates a TOC by named -Name parameter' {
41 | $text = 'Simple paragraph.'
42 |
43 | $t = TOC $text
44 |
45 | $t.Name | Should Be $text
46 | }
47 |
48 | It 'creates a TOC by named -Name parameter with enabled -ForceUppercaseSection option' {
49 | $pscriboDocument.Options['ForceUppercaseSection'] = $true
50 | $text = 'Simple paragraph.'
51 |
52 | $t = TOC $text
53 |
54 | $t.Name | Should Be $text.ToUpper()
55 | }
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/Examples/Example06.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding()]
2 | param (
3 | [System.String[]] $Format = 'Html',
4 | [System.String] $Path = '~\Desktop',
5 | [System.Management.Automation.SwitchParameter] $PassThru
6 | )
7 |
8 | Import-Module PScribo -Force -Verbose:$false
9 |
10 | $example6 = Document -Name 'PScribo Example 6' {
11 |
12 | <#
13 | You can create a document structure with the 'Section' cmdlet. This is the only PScribo
14 | cmdlet that supports nesting of script blocks.
15 |
16 | Sections are used to create a hierarchy within the document that are used when generating
17 | a table of contents. If you have no requirement for a table of contents, then you may
18 | not need to use the 'Section' keyword.
19 |
20 | You can define sections with the 'Section' keyword, a name and script block. You can nest
21 | sections within sections.
22 | #>
23 | Section -Name 'First Section' -ScriptBlock {
24 | Paragraph 'This section will not have any explicit styling applied.'
25 | }
26 |
27 | <#
28 | Styles can also be applied to Sections with the -Style parameter. PScribo defines the
29 | following heading styles: Heading1, Heading2 and Heading3. Just like the built-in
30 | "Normal" style you can define your own styles or override the default ones.
31 | #>
32 | Section -Name 'Second Styled Section' -Style Heading1 -ScriptBlock {
33 | Paragraph 'This section heading will be styled with the built-in "Heading1" style.'
34 | }
35 |
36 | Section -Name 'Third Section' -Style Heading1 -ScriptBlock {
37 | Paragraph 'This paragraph is nested within "Third Section".'
38 |
39 | Section 'Sub Section' -Style Heading2 {
40 | Paragraph 'This paragraph is nested beneath the "Third Section\Sub Section".'
41 | }
42 | }
43 | }
44 | $example6 | Export-Document -Path $Path -Format $Format -PassThru:$PassThru
45 |
--------------------------------------------------------------------------------
/Examples/Example41.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding()]
2 | param (
3 | [System.String[]] $Format = 'Html',
4 | [System.String] $Path = '~\Desktop',
5 | [System.Management.Automation.SwitchParameter] $PassThru
6 | )
7 |
8 | Import-Module PScribo -Force -Verbose:$false
9 |
10 | $example41 = Document -Name 'PScribo Example 41' {
11 |
12 | <#
13 | Multi-level bullet lists can be created by nesting one or more 'List' keywords.
14 |
15 | NOTE: There must be an 'Item' keyword defined before a nested 'List' can be used.
16 | #>
17 | List {
18 | Item 'Apples'
19 | List {
20 | Item 'Jazz'
21 | Item 'Granny smith'
22 | Item 'Pink lady'
23 | }
24 | Item 'Bananas'
25 | Item 'Oranges'
26 | List {
27 | Item 'Jaffa'
28 | Item 'Tangerine'
29 | Item 'Clementine'
30 | }
31 | }
32 |
33 | <#
34 | Each 'List' can have its own bullet style defined.
35 |
36 | NOTE: Word does not support a mixture of bullet/number formats at the same level within a
37 | list. Therefore, only the first list type will be rendered at each level - in this
38 | example the 'Disc' style will be used.
39 |
40 | NOTE: Html output does not support the 'Dash' bullet style. Dashes will be rendered using
41 | the the web broswer's defaults.
42 | #>
43 | List -BulletStyle Square {
44 | Item 'Apples'
45 | List -BulletStyle Disc {
46 | Item 'Jazz'
47 | Item 'Granny smith'
48 | Item 'Pink lady'
49 | }
50 | Item 'Bananas'
51 | Item 'Oranges'
52 | List -BulletStyle Dash {
53 | Item 'Jaffa'
54 | Item 'Tangerine'
55 | Item 'Clementine'
56 | }
57 | }
58 |
59 | }
60 | $example41 | Export-Document -Path $Path -Format $Format -PassThru:$PassThru
61 |
--------------------------------------------------------------------------------
/Src/Plugins/Html/Get-HtmlTableDiv.ps1:
--------------------------------------------------------------------------------
1 | function Get-HtmlTableDiv
2 | {
3 | <#
4 | .SYNOPSIS
5 | Generates Html tags based upon table width, columns and indentation
6 | .NOTES
7 | A is required to ensure that the table stays within the "page" boundaries/margins.
8 | #>
9 | param
10 | (
11 | [Parameter(Mandatory, ValueFromPipeline)]
12 | [ValidateNotNull()]
13 | [System.Management.Automation.PSObject] $Table
14 | )
15 | process
16 | {
17 | $divBuilder = New-Object -TypeName 'System.Text.StringBuilder'
18 | [ref] $null = $divBuilder.Append('
tag
26 | [ref] $null = $divBuilder.AppendFormat('">
', [System.String]::Join(' ', $styleElements))
43 | }
44 | else
45 | {
46 | [ref] $null = $divBuilder.Append('>')
47 | }
48 |
49 | return $divBuilder.ToString()
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Src/Public/Set-Style.ps1:
--------------------------------------------------------------------------------
1 | function Set-Style
2 | {
3 | <#
4 | .SYNOPSIS
5 | Sets the style for an individual table row or cell.
6 | #>
7 | [CmdletBinding()]
8 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions','')]
9 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidMultipleTypeAttributes','')]
10 | [OutputType([System.Object])]
11 | param
12 | (
13 | ## PSCustomObject to apply the style to
14 | [Parameter(Mandatory, ValueFromPipeline)]
15 | [System.Object[]] [Ref] $InputObject,
16 |
17 | ## PScribo style Id to apply
18 | [Parameter(Mandatory, ValueFromPipelineByPropertyName)]
19 | [System.String] $Style,
20 |
21 | ## Property name(s) to apply the selected style to. Leave blank to apply the style to the entire row.
22 | [Parameter(ValueFromPipelineByPropertyName)]
23 | [ValidateNotNullOrEmpty()]
24 | [System.String[]] $Property = '',
25 |
26 | ## Passes the modified object back to the pipeline
27 | [Parameter(ValueFromPipelineByPropertyName)]
28 | [System.Management.Automation.SwitchParameter] $PassThru
29 | )
30 | begin
31 | {
32 | if (-not (Test-PScriboStyle -Name $Style))
33 | {
34 | Write-Error ($localized.UndefinedStyleError -f $Style)
35 | return
36 | }
37 | }
38 | process
39 | {
40 | foreach ($object in $InputObject)
41 | {
42 | foreach ($p in $Property)
43 | {
44 | ## If $Property not set, __Style will apply to the whole row.
45 | $propertyName = '{0}__Style' -f $p
46 | $object | Add-Member -MemberType NoteProperty -Name $propertyName -Value $Style -Force
47 | }
48 | }
49 | if ($PassThru)
50 | {
51 | return $object
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/Src/Plugins/Html/Get-HtmlListItemInlineStyle.ps1:
--------------------------------------------------------------------------------
1 | function Get-HtmlListItemInlineStyle
2 | {
3 | <#
4 | .SYNOPSIS
5 | Generates inline Html style attribute from PScribo list Item style overrides.
6 | #>
7 | [CmdletBinding()]
8 | [OutputType([System.String])]
9 | param
10 | (
11 | [Parameter(Mandatory, ValueFromPipeline)]
12 | [ValidateNotNull()]
13 | [System.Management.Automation.PSObject] $Item
14 | )
15 | process
16 | {
17 | $itemStyleBuilder = New-Object -TypeName System.Text.StringBuilder
18 |
19 | if ($Item.Font)
20 | {
21 | $fontList = $List.Font -Join "','"
22 | [ref] $null = $itemStyleBuilder.AppendFormat(" font-family: '{0}';", $fontList)
23 | }
24 |
25 | if ($Item.Size -gt 0)
26 | {
27 | ## Create culture invariant decimal https://github.com/iainbrighton/PScribo/issues/6
28 | $invariantItemSize = ConvertTo-InvariantCultureString -Object ($Item.Size / 12) -Format 'f2'
29 | [ref] $null = $itemStyleBuilder.AppendFormat(' font-size: {0}rem;', $invariantItemSize)
30 | }
31 |
32 | if ($Item.Bold -eq $true)
33 | {
34 | [ref] $null = $itemStyleBuilder.Append(' font-weight: bold;')
35 | }
36 |
37 | if ($Item.Italic -eq $true)
38 | {
39 | [ref] $null = $itemStyleBuilder.Append(' font-style: italic;')
40 | }
41 |
42 | if ($Item.Underline -eq $true)
43 | {
44 | [ref] $null = $itemStyleBuilder.Append(' text-decoration: underline;')
45 | }
46 |
47 | if (-not [System.String]::IsNullOrEmpty($Item.Color))
48 | {
49 | $color = Resolve-PScriboStyleColor -Color $Item.Color
50 | [ref] $null = $itemStyleBuilder.AppendFormat(' color: #{0};', $color)
51 | }
52 |
53 | return $itemStyleBuilder.ToString().TrimStart()
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/Src/Plugins/Word/Get-WordTableRenderWidthMm.ps1:
--------------------------------------------------------------------------------
1 | function Get-WordTableRenderWidthMm
2 | {
3 | <#
4 | .SYNOPSIS
5 | Calcualtes a table's (maximum) rendering size in millimetres.
6 | #>
7 | [CmdletBinding()]
8 | param
9 | (
10 | [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
11 | [ValidateRange(0, 100)]
12 | [System.UInt16] $TableWidth,
13 |
14 | [Parameter(Mandatory, ValueFromPipelineByPropertyName)]
15 | [ValidateRange(0, 10)]
16 | [System.UInt16] $Tabs,
17 |
18 | [Parameter(Mandatory, ValueFromPipeline)]
19 | [System.String] $Orientation
20 | )
21 | process
22 | {
23 | if ($TableWidth -eq 0)
24 | {
25 | ## Word will autofit contents as necessary, but LibreOffice won't
26 | ## so we just have assume that we're using all available width
27 | $TableWidth = 100
28 | }
29 | if ($Orientation -eq 'Portrait')
30 | {
31 | $pageWidthMm = $Document.Options['PageWidth'] - ($Document.Options['MarginLeft'] + $Document.Options['MarginRight'])
32 | }
33 | elseif ($Orientation -eq 'Landscape')
34 | {
35 | $pageWidthMm = $Document.Options['PageHeight'] - ($Document.Options['MarginLeft'] + $Document.Options['MarginRight'])
36 | }
37 | $indentWidthMm = ConvertTo-Mm -Point ($Tabs * 36)
38 | $tableWidthRenderMm = (($pageWidthMm / 100) * $TableWidth) + $indentWidthMm
39 | if ($tableWidthRenderMm -gt $pageWidthMm)
40 | {
41 | ## We now need to deal with tables being pushed outside the page margin so just return the maximum permitted
42 | $tableWidthRenderMm = $pageWidthMm - $indentWidthMm
43 | Write-PScriboMessage -Message ($localized.TableWidthOverflowWarning -f $tableWidthRenderMm) -IsWarning
44 | }
45 | return $tableWidthRenderMm
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/Tests/Plugins/Xml/Out-XmlDocument.Tests.ps1:
--------------------------------------------------------------------------------
1 | $here = Split-Path -Path $MyInvocation.MyCommand.Path -Parent;
2 | $pluginRoot = Split-Path -Path $here -Parent;
3 | $testRoot = Split-Path -Path $pluginRoot -Parent;
4 | $moduleRoot = Split-Path -Path $testRoot -Parent;
5 | Import-Module "$moduleRoot\PScribo.psm1" -Force;
6 |
7 | InModuleScope 'PScribo' {
8 |
9 | ## Scaffold root XmlDocument
10 | $xmlDocument = New-Object -TypeName System.Xml.XmlDocument;
11 | [ref] $null = $xmlDocument.AppendChild($xmlDocument.CreateXmlDeclaration('1.0', 'utf-8', 'yes'));
12 | $element = $xmlDocument.AppendChild($xmlDocument.CreateElement('testdocument'));
13 | [ref] $null = $element.SetAttribute('name', 'testdocument');
14 |
15 | Describe 'Plugins\Text\Out-XmlDocument' {
16 |
17 | It 'calls Out-XmlTable' {
18 | Mock -CommandName Out-XmlTable -MockWith { return $xmlDocument.CreateElement('TestTable') }
19 |
20 | Document -Name 'TestDocument' -ScriptBlock { Get-Process | Select-Object -First 1 | Table 'TestTable' } | Out-XmlDocument -Path $testDrive
21 |
22 | Assert-MockCalled -CommandName Out-XmlTable -Exactly 1
23 | }
24 |
25 | It 'calls Out-XmlParagraph' {
26 | Mock -CommandName Out-XmlParagraph -MockWith { return $xmlDocument.CreateElement('TestParagraph') }
27 |
28 | Document -Name 'TestDocument' -ScriptBlock { Paragraph 'TestParagraph' } | Out-XmlDocument -Path $testDrive
29 |
30 | Assert-MockCalled -CommandName Out-XmlParagraph -Exactly 1
31 | }
32 |
33 | It 'calls Out-XmlSection' {
34 | Mock -CommandName Out-XmlSection -MockWith { return $xmlDocument.CreateElement('TestSection'); }
35 |
36 | Document -Name 'TestDocument' -ScriptBlock { Section -Name 'TestSection' -ScriptBlock { } } | Out-XmlDocument -Path $testDrive
37 |
38 | Assert-MockCalled -CommandName Out-XmlSection -Exactly 1
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/PScribo.psd1:
--------------------------------------------------------------------------------
1 | @{
2 | RootModule = 'PScribo.psm1'
3 | ModuleVersion = '0.11.1'
4 | GUID = '058eab05-b7bc-4f8b-a2d1-737cc664b12b'
5 | Author = 'Iain Brighton'
6 | CompanyName = 'Virtual Engine'
7 | Copyright = '(c) 2025 Iain Brighton. All rights reserved.'
8 | Description = 'PScribo documentation Powershell module/framework.'
9 | PowerShellVersion = '3.0'
10 | FunctionsToExport = @(
11 | 'BlankLine',
12 | 'Document',
13 | 'DocumentOption',
14 | 'Export-Document',
15 | 'Footer',
16 | 'Header',
17 | 'Image',
18 | 'Item',
19 | 'LineBreak',
20 | 'List',
21 | 'NumberStyle',
22 | 'PageBreak',
23 | 'Paragraph',
24 | 'Section',
25 | 'Set-Style',
26 | 'Style',
27 | 'Table',
28 | 'TableStyle',
29 | 'Text',
30 | 'TOC',
31 | 'Write-PScriboMessage',
32 | 'Get-WordListLevel'
33 | )
34 | AliasesToExport = @(
35 | 'GlobalOption'
36 | )
37 | PrivateData = @{
38 | PSData = @{
39 | Tags = @('Powershell','PScribo','Documentation','Framework','VirtualEngine','Windows','Linux','MacOS','PSEdition_Desktop','PSEdition_Core','Word','Html')
40 | LicenseUri = 'https://raw.githubusercontent.com/iainbrighton/PScribo/master/LICENSE'
41 | ProjectUri = 'http://github.com/iainbrighton/PScribo'
42 | # IconUri = '';
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Src/Private/ConvertFrom-NumberStyle.ps1:
--------------------------------------------------------------------------------
1 | function ConvertFrom-NumberStyle
2 | {
3 | <#
4 | .SYNOPSIS
5 | Converts a number to its string representation, based upon the number style
6 | #>
7 | [CmdletBinding()]
8 | param
9 | (
10 | [Parameter(Mandatory, ValueFromPipeline)]
11 | [System.Int32] $Value,
12 |
13 | [Parameter(Mandatory, ValueFromPipeline)]
14 | [System.Management.Automation.PSObject] $NumberStyle
15 | )
16 | process
17 | {
18 | switch ($NumberStyle.Format)
19 | {
20 | 'Number'
21 | {
22 | $numberString = $Value.ToString()
23 | }
24 | 'Letter'
25 | {
26 | $numberString = [System.Char] ($Value + 64)
27 | }
28 | 'Roman'
29 | {
30 | $numberString = ConvertTo-RomanNumeral -Value $Value
31 | }
32 | 'Custom'
33 | {
34 | $numberCount = 0
35 | $customStringChars = $numberStyle.Custom.ToCharArray()
36 | $customStringLength = $numberStyle.Custom.Length
37 | for ($n = $customStringLength - 1; $n -ge 0; $n--)
38 | {
39 | if ($customStringChars[$n] -eq '%')
40 | {
41 | $numberCount++
42 | }
43 | }
44 |
45 | $searchString = ''.PadRight($numberCount, '%')
46 | $replacementString = $Value.ToString().PadLeft($numberCount, '0')
47 | return $numberStyle.Custom.Replace($searchString, $replacementString)
48 | }
49 | }
50 |
51 | $numberString = '{0}{1}' -f $numberString, $NumberStyle.Suffix
52 | if ($NumberStyle.Uppercase)
53 | {
54 | return $numberString.ToUpper()
55 | }
56 | else
57 | {
58 | return $numberString.ToLower()
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/Examples/Example42.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding()]
2 | param (
3 | [System.String[]] $Format = 'Html',
4 | [System.String] $Path = '~\Desktop',
5 | [System.Management.Automation.SwitchParameter] $PassThru
6 | )
7 |
8 | Import-Module PScribo -Force -Verbose:$false
9 |
10 | $example42 = Document -Name 'PScribo Example 42' {
11 |
12 | <#
13 | Multi-level numbered lists can be created by nesting one or more 'List' keywords in
14 | combination with the '-Numbered' parameter.
15 |
16 | NOTE: A 'List' defaults to a bulleted list by default, so the '-Numbered' switch needs
17 | to be specified at each level - where required.
18 | #>
19 | List -Numbered {
20 | Item 'Apples'
21 | List -Numbered {
22 | Item 'Jazz'
23 | Item 'Granny smith'
24 | Item 'Pink lady'
25 | }
26 | Item 'Bananas'
27 | Item 'Oranges'
28 | List -Numbered {
29 | Item 'Jaffa'
30 | Item 'Tangerine'
31 | Item 'Clementine'
32 | }
33 | }
34 |
35 | <#
36 | Like bullet lists, each 'List' can have its own number style defined.
37 |
38 | NOTE: Word does not support a mixture of bullet/number formats at the same level within a
39 | list. Therefore, only the first list type will be rendered at each level - in this
40 | example the 'Letter' style will be used for the second nested numbered list.
41 | #>
42 | List -Numbered {
43 | Item 'Apples'
44 | List -Numbered -NumberStyle Letter {
45 | Item 'Jazz'
46 | Item 'Granny smith'
47 | Item 'Pink lady'
48 | }
49 | Item 'Bananas'
50 | Item 'Oranges'
51 | List -Numbered -NumberStyle Roman {
52 | Item 'Jaffa'
53 | Item 'Tangerine'
54 | Item 'Clementine'
55 | }
56 | }
57 |
58 | }
59 | $example42 | Export-Document -Path $Path -Format $Format -PassThru:$PassThru
60 |
--------------------------------------------------------------------------------
/Examples/Example04.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding()]
2 | param (
3 | [System.String[]] $Format = 'Html',
4 | [System.String] $Path = '~\Desktop',
5 | [System.Management.Automation.SwitchParameter] $PassThru
6 | )
7 |
8 | Import-Module PScribo -Force -Verbose:$false
9 |
10 | $example4 = Document -Name 'PScribo Example 4' {
11 |
12 | <#
13 | NOTE: This example is the 'legacy' paragraph implementation. For
14 | advanced paragraph styling options see Example38.ps1
15 | #>
16 | Paragraph 'The default built-in style that is applied to paragraphs is named "Normal".'
17 | Paragraph 'You can apply an alternative color to a particular paragraph by specifying a html color code to the -Color parameter.' -Color f00
18 | Paragraph 'You can also supply Word constant colors to a paragraph!' -Color SteelBlue
19 | Paragraph 'You can apply bold styling to a particular paragraph by specifying the -Bold switch parameter.' -Bold
20 | Paragraph 'You can apply italic styling to a particular paragraph by specifying the -Italic switch parameter.' -Italic
21 | Paragraph 'You can apply underline styling to a particular paragraph by specifying the -Underline switch parameter.' -Underline
22 | Paragraph 'You can alter the default font size of a particular paragraph by specifying the font point size with the -Size parameter' -Size 16
23 | Paragraph 'You can alter the default font typeface of a particular paragraph by specifying -Font parameter. This parameter takes an array of font names. Typically, only the first font name is used in Word output, but all names are used in Html output.' -Font Arial
24 | Paragraph 'If you wish to indent a paragraph, specify the -Tabs parameter. This is an integer number that indents a paragraph at 12.7mm/0.5inch intervals.' -Tabs 1
25 | Paragraph 'Of course, you are free to combine multiple styling parameters to a single paragraph :).' -Color DarkOrchid -Size 14 -Bold
26 | }
27 | $example4 | Export-Document -Path $Path -Format $Format -PassThru:$PassThru
28 |
--------------------------------------------------------------------------------
/Examples/Example39.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding()]
2 | param (
3 | [System.String[]] $Format = 'Html',
4 | [System.String] $Path = '~\Desktop',
5 | [System.Management.Automation.SwitchParameter] $PassThru
6 | )
7 |
8 | Import-Module PScribo -Force -Verbose:$false
9 |
10 | # 'List' single-level bullet lists
11 | $example39 = Document -Name 'PScribo Example 39' {
12 |
13 | <#
14 | A bulleted list is defined by the 'List' keyword and can contain one or more items.
15 |
16 | A simple single-level list can be defined with the '-Item' parameter and passing an
17 | array of strings ([string[]]).
18 | #>
19 | List -Item 'Apples','Oranges','Bananas'
20 |
21 | <#
22 | A list can also be created using a script block and nesting one or 'Item' keywords
23 | within it.
24 | #>
25 | List {
26 | Item 'Apples'
27 | Item 'Bananas'
28 | Item 'Oranges'
29 | }
30 |
31 | <#
32 | Bullet styles can be applied to a list, e.g. 'Dash', 'Circle', 'Disc' and 'Square'. If
33 | not specified, the bullet list defaults to the 'Disc' style.
34 | #>
35 | List -BulletStyle Square {
36 | Item 'Apples'
37 | Item 'Bananas'
38 | Item 'Oranges'
39 | }
40 |
41 | <#
42 | Formatting styles can be applied to all items in a list.
43 | #>
44 | List -Style Caption {
45 | Item 'Apples'
46 | Item 'Bananas'
47 | Item 'Oranges'
48 | }
49 |
50 | <#
51 | Styles can be applied to indiviual items in a list.
52 | #>
53 | List {
54 | Item 'Apples'
55 | Item 'Bananas' -Style Caption
56 | Item 'Oranges'
57 | }
58 |
59 | <#
60 | Inline styles can also be applied to indiviual items in a list.
61 | #>
62 | List {
63 | Item 'Apples' -Bold
64 | Item 'Bananas' -Italic
65 | Item 'Oranges' -Color Firebrick
66 | }
67 |
68 | }
69 | $example39 | Export-Document -Path $Path -Format $Format -PassThru:$PassThru
70 |
--------------------------------------------------------------------------------
/Src/Plugins/Text/Out-TextTOC.ps1:
--------------------------------------------------------------------------------
1 | function Out-TextTOC
2 | {
3 | <#
4 | .SYNOPSIS
5 | Output formatted Table of Contents
6 | #>
7 | [CmdletBinding()]
8 | param
9 | (
10 | [Parameter(Mandatory, ValueFromPipeline)]
11 | [System.Management.Automation.PSObject] $TOC
12 | )
13 | begin
14 | {
15 | ## Fix Set-StrictMode
16 | if (-not (Test-Path -Path Variable:\Options))
17 | {
18 | $options = New-PScriboTextOption
19 | }
20 | }
21 | process
22 | {
23 | $tocBuilder = New-Object -TypeName System.Text.StringBuilder
24 | [ref] $null = $tocBuilder.AppendLine($TOC.Name)
25 | [ref] $null = $tocBuilder.AppendLine(''.PadRight($options.SeparatorWidth, $options.SectionSeparator))
26 |
27 | if ($Options.ContainsKey('EnableSectionNumbering'))
28 | {
29 | $maxSectionNumberLength = $Document.TOC.Number | ForEach-Object { $_.Length } | Measure-Object -Maximum | Select-Object -ExpandProperty Maximum
30 | foreach ($tocEntry in $Document.TOC)
31 | {
32 | $sectionNumberPaddingLength = $maxSectionNumberLength - $tocEntry.Number.Length
33 | $sectionNumberIndent = ''.PadRight($tocEntry.Level, ' ')
34 | $sectionPadding = ''.PadRight($sectionNumberPaddingLength, ' ')
35 | [ref] $null = $tocBuilder.AppendFormat('{0}{1} {2}{3}', $tocEntry.Number, $sectionPadding, $sectionNumberIndent, $tocEntry.Name).AppendLine()
36 | }
37 | }
38 | else
39 | {
40 | $maxSectionNumberLength = $Document.TOC.Level | Sort-Object | Select-Object -Last 1
41 | foreach ($tocEntry in $Document.TOC)
42 | {
43 | $sectionNumberIndent = ''.PadRight($tocEntry.Level, ' ')
44 | [ref] $null = $tocBuilder.AppendFormat('{0}{1}', $sectionNumberIndent, $tocEntry.Name).AppendLine()
45 | }
46 | }
47 |
48 | return $tocBuilder.ToString()
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/Src/Plugins/Text/New-PScriboTextOption.ps1:
--------------------------------------------------------------------------------
1 | function New-PScriboTextOption
2 | {
3 | <#
4 | .SYNOPSIS
5 | Sets the text plugin specific formatting/output options.
6 |
7 | .NOTES
8 | All plugin options should be prefixed with the plugin name.
9 | #>
10 | [CmdletBinding()]
11 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions','')]
12 | [OutputType([System.Collections.Hashtable])]
13 | param
14 | (
15 | ## Text/output width. 0 = none/no wrap.
16 | [Parameter(ValueFromPipelineByPropertyName)]
17 | [ValidateNotNull()]
18 | [System.Int32] $TextWidth = 120,
19 |
20 | ## Document header separator character.
21 | [Parameter(ValueFromPipelineByPropertyName)]
22 | [ValidateLength(1,1)]
23 | [System.String] $HeaderSeparator = '=',
24 |
25 | ## Document section separator character.
26 | [Parameter(ValueFromPipelineByPropertyName)]
27 | [ValidateLength(1,1)]
28 | [System.String] $SectionSeparator = '-',
29 |
30 | ## Document section separator character.
31 | [Parameter(ValueFromPipelineByPropertyName)]
32 | [ValidateLength(1,1)]
33 | [System.String] $LineBreakSeparator = '_',
34 |
35 | ## Default header/section separator width.
36 | [Parameter(ValueFromPipelineByPropertyName)]
37 | [ValidateNotNull()]
38 | [System.Int32] $SeparatorWidth = $TextWidth,
39 |
40 | ## Text encoding
41 | [Parameter(ValueFromPipelineByPropertyName)]
42 | [ValidateSet('ASCII','Unicode','UTF7','UTF8')]
43 | [System.String] $Encoding = 'ASCII'
44 | )
45 | process
46 | {
47 | return @{
48 | TextWidth = $TextWidth
49 | HeaderSeparator = $HeaderSeparator
50 | SectionSeparator = $SectionSeparator
51 | LineBreakSeparator = $LineBreakSeparator
52 | SeparatorWidth = $SeparatorWidth
53 | Encoding = $Encoding
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/Src/Plugins/Html/Out-HtmlPageBreak.ps1:
--------------------------------------------------------------------------------
1 | function Out-HtmlPageBreak
2 | {
3 | <#
4 | .SYNOPSIS
5 | Output formatted Html page break.
6 | #>
7 | [CmdletBinding()]
8 | [OutputType([System.String])]
9 | param
10 | (
11 | [Parameter(Mandatory, ValueFromPipeline)]
12 | [System.String] $Orientation
13 | )
14 | process
15 | {
16 | [System.Text.StringBuilder] $pageBreakBuilder = New-Object 'System.Text.StringBuilder'
17 |
18 | [ref] $null = $pageBreakBuilder.Append('') ## Canvas
19 | $isFirstPage = $currentPageNumber -eq 1
20 | [ref] $null = $pageBreakBuilder.Append((Out-HtmlHeaderFooter -Footer -FirstPage:$isFirstPage))
21 |
22 | $script:currentPageNumber++
23 | [ref] $null = $pageBreakBuilder.Append('')
24 | $topMargin = ConvertTo-InvariantCultureString -Object (ConvertTo-Em -Millimeter $Document.Options['MarginTop']) -Format 'f2'
25 | $leftMargin = ConvertTo-InvariantCultureString -Object (ConvertTo-Em -Millimeter $Document.Options['MarginLeft']) -Format 'f2'
26 | $bottomMargin = ConvertTo-InvariantCultureString -Object (ConvertTo-Em -Millimeter $Document.Options['MarginBottom']) -Format 'f2'
27 | $rightMargin = ConvertTo-InvariantCultureString -Object (ConvertTo-Em -Millimeter $Document.Options['MarginRight']) -Format 'f2'
28 | [ref] $null = $pageBreakBuilder.AppendFormat('', $Orientation.ToLower())
29 | [ref] $null = $pageBreakBuilder.AppendFormat('
', $Document.DefaultStyle, $topMargin, $leftMargin, $bottomMargin, $rightMargin).AppendLine()
30 |
31 | $canvasHeight = Get-HtmlCanvasHeight -Orientation $Orientation
32 | [ref] $null = $pageBreakBuilder.AppendFormat('
', $canvasHeight)
33 | [ref] $null = $pageBreakBuilder.Append((Out-HtmlHeaderFooter -Header))
34 |
35 | return $pageBreakBuilder.ToString()
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Tests/Plugins/Word/Out-WordBlankLine.Tests.ps1:
--------------------------------------------------------------------------------
1 | $here = Split-Path -Path $MyInvocation.MyCommand.Path -Parent;
2 | $pluginsRoot = Split-Path -Path $here -Parent;
3 | $testRoot = Split-Path -Path $pluginsRoot -Parent;
4 | $moduleRoot = Split-Path -Path $testRoot -Parent;
5 | Import-Module "$moduleRoot\PScribo.psm1" -Force;
6 |
7 |
8 |
9 | InModuleScope 'PScribo' {
10 |
11 | function GetMatch
12 | {
13 | [CmdletBinding()]
14 | param
15 | (
16 | [System.String] $String,
17 | [System.Management.Automation.SwitchParameter] $Complete
18 | )
19 | Write-Verbose "Pre Match : '$String'"
20 | $matchString = $String.Replace('/','\/')
21 | if (-not $String.StartsWith('^'))
22 | {
23 | $matchString = $matchString.Replace('[..]','[\s\S]+')
24 | $matchString = $matchString.Replace('[??]','([\s\S]+)?')
25 | if ($Complete)
26 | {
27 | $matchString = '^{0}<\/w:test>$' -f $matchString
28 | }
29 | }
30 | Write-Verbose "Post Match: '$matchString'"
31 | return $matchString
32 | }
33 |
34 | Describe 'Plugins\Word\Out-WordBlankLine' {
35 |
36 | It 'appends paragraph ""' {
37 | $document = Document -Name 'TestDocument' {
38 | BlankLine
39 | }
40 |
41 | $testDocument = Get-WordDocument -Document $document
42 |
43 | $expected = GetMatch ''
44 | $testDocument.DocumentElement.OuterXml | Should Match $expected
45 | }
46 |
47 | It 'appends paragraph "" per blankline' {
48 | $document = Document -Name 'TestDocument' {
49 | BlankLine -Count 2
50 | }
51 |
52 | $testDocument = Get-WordDocument -Document $document
53 |
54 | $expected = GetMatch ''
55 | $testDocument.DocumentElement.OuterXml | Should Match $expected
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/Src/Plugins/Html/Get-HtmlStyle.ps1:
--------------------------------------------------------------------------------
1 | function Get-HtmlStyle
2 | {
3 | <#
4 | .SYNOPSIS
5 | Generates html stylesheet style attributes from a PScribo document style.
6 | #>
7 | [CmdletBinding()]
8 | [OutputType([System.String])]
9 | param
10 | (
11 | ## PScribo document style
12 | [Parameter(Mandatory, ValueFromPipeline)]
13 | [System.Management.Automation.PSObject] $Style
14 | )
15 | process
16 | {
17 | $styleBuilder = New-Object -TypeName System.Text.StringBuilder
18 | [ref] $null = $styleBuilder.AppendFormat(" font-family: '{0}';", $Style.Font -join "','")
19 | ## Create culture invariant decimal https://github.com/iainbrighton/PScribo/issues/6
20 | $invariantFontSize = ConvertTo-InvariantCultureString -Object ($Style.Size / 12) -Format 'f2'
21 | [ref] $null = $styleBuilder.AppendFormat(' font-size: {0}rem;', $invariantFontSize)
22 | [ref] $null = $styleBuilder.AppendFormat(' text-align: {0};', $Style.Align.ToLower())
23 |
24 | if ($Style.Bold)
25 | {
26 | [ref] $null = $styleBuilder.Append(' font-weight: bold;')
27 | }
28 | else
29 | {
30 | [ref] $null = $styleBuilder.Append(' font-weight: normal;')
31 | }
32 |
33 | if ($Style.Italic)
34 | {
35 | [ref] $null = $styleBuilder.Append(' font-style: italic;')
36 | }
37 |
38 | if ($Style.Underline)
39 | {
40 | [ref] $null = $styleBuilder.Append(' text-decoration: underline;')
41 | }
42 |
43 | if ($Style.Color)
44 | {
45 | $color = Resolve-PScriboStyleColor -Color $Style.Color
46 | [ref] $null = $styleBuilder.AppendFormat(' color: #{0};', $color)
47 | }
48 |
49 | if ($Style.BackgroundColor)
50 | {
51 | $backgroundColor = Resolve-PScriboStyleColor -Color $Style.BackgroundColor
52 | [ref] $null = $styleBuilder.AppendFormat(' background-color: #{0};', $backgroundColor)
53 | }
54 |
55 | return $styleBuilder.ToString()
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Src/Private/New-PScriboParagraph.ps1:
--------------------------------------------------------------------------------
1 | function New-PScriboParagraph
2 | {
3 | <#
4 | .SYNOPSIS
5 | Initializes a new PScribo paragraph object.
6 |
7 | .NOTES
8 | This is an internal function and should not be called directly.
9 | #>
10 | [CmdletBinding()]
11 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions','')]
12 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter','ScriptBlock')]
13 | [OutputType([System.Management.Automation.PSCustomObject])]
14 | param
15 | (
16 | ## PScribo paragraph run script block.
17 | [Parameter(ValueFromPipeline, ValueFromPipelineByPropertyName)]
18 | [ValidateNotNull()]
19 | [System.Management.Automation.ScriptBlock] $ScriptBlock,
20 |
21 | ## Paragraph Id.
22 | [Parameter(ValueFromPipelineByPropertyName)]
23 | [ValidateNotNull()]
24 | [System.String] $Id = [System.Guid]::NewGuid().ToString(),
25 |
26 | ## Paragraph style Name/Id reference.
27 | [Parameter(ValueFromPipelineByPropertyName)]
28 | [AllowNull()]
29 | [System.String] $Style = $null,
30 |
31 | ## Tab indent
32 | [Parameter(ValueFromPipelineByPropertyName)]
33 | [ValidateRange(0,10)]
34 | [System.Int32] $Tabs = 0,
35 |
36 | [Parameter(ValueFromPipelineByPropertyName)]
37 | [System.Management.Automation.SwitchParameter] $NoIncrementCounter
38 | )
39 | process
40 | {
41 | if (-not $NoIncrementCounter)
42 | {
43 | $pscriboDocument.Properties['Paragraphs']++
44 | }
45 |
46 | $pscriboParagraph = [PSCustomObject] @{
47 | Id = $Id
48 | Type = 'PScribo.Paragraph'
49 | Style = $Style
50 | Tabs = $Tabs
51 | Sections = (New-Object -TypeName System.Collections.ArrayList)
52 | Orientation = $script:currentOrientation
53 | IsSectionBreakEnd = $false
54 | }
55 | return $pscriboParagraph
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Examples/Example34.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding()]
2 | param (
3 | [System.String[]] $Format = 'Html',
4 | [System.String] $Path = '~\Desktop',
5 | [System.Management.Automation.SwitchParameter] $PassThru
6 | )
7 |
8 | Import-Module PScribo -Force -Verbose:$false
9 |
10 | $example34 = Document -Name 'PScribo Example 34' {
11 |
12 | <#
13 | Captions can be added to all tables. Note: List tables with a single
14 | row support table captions (as they output a separate table per row
15 | and the table numbering is then broken!).
16 |
17 | The default position is below the table, but this can be overridden
18 | by defining a custom table style using -CaptionLocation 'Above'.
19 |
20 | Table captions are prefixed with the word 'Table'. The prefix can be
21 | changed by defining a custom table style using the -CaptionPrefix
22 | parameter.
23 |
24 | Captions can be styled by defining the required style and assigning
25 | it to the table style's -CaptionStyle parameter.
26 | #>
27 |
28 | $servers = @(
29 | [Ordered] @{ 'Computer Name' = 'DC1'; 'Domain Name' = 'example.local'; FQDN = 'dc1.example.local'; 'IP Address' = '192.168.0.1' }
30 | [Ordered] @{ 'Computer Name' = 'DC2'; 'Domain Name' = 'example.local'; FQDN = 'dc2.example.local'; 'IP Address' = '192.168.0.2' }
31 | [Ordered] @{ 'Computer Name' = 'DC3'; 'Domain Name' = 'example.local'; FQDN = 'dc3.example.local'; 'IP Address' = '192.168.0.3' }
32 | )
33 |
34 | Table -Hashtable $servers -List -Key 'Computer Name' -Caption '- Server Information'
35 |
36 | <#
37 | The table above, will be rendered like so:
38 |
39 | Computer Name DC1 DC2 DC3
40 | ------------- --- --- ---
41 | DomainName example.local example.local example.local
42 | FQDN dc1.example.local dc2.example.local dc3.example.local
43 | IpAddress 192.168.0.1 192.168.0.2 192.168.0.3
44 |
45 | Table 1 - Server Information
46 | #>
47 | }
48 | $example34 | Export-Document -Path $Path -Format $Format -PassThru:$PassThru
49 |
--------------------------------------------------------------------------------
/Tests/Plugins/Json/Out-JsonSection.Tests.ps1:
--------------------------------------------------------------------------------
1 | $here = Split-Path -Path $MyInvocation.MyCommand.Path -Parent;
2 | $pluginRoot = Split-Path -Path $here -Parent;
3 | $testRoot = Split-Path -Path $pluginRoot -Parent;
4 | $moduleRoot = Split-Path -Path $testRoot -Parent;
5 | Import-Module "$moduleRoot\PScribo.psm1" -Force;
6 |
7 | InModuleScope 'PScribo' {
8 |
9 | Describe 'Plugins\Json\Out-JsonSection' {
10 |
11 | $Document = Document -Name 'TestDocument' -ScriptBlock { }
12 | $pscriboDocument = $Document
13 |
14 | It 'calls Out-JsonParagraph' {
15 | Mock -CommandName Out-JsonParagraph
16 |
17 | Section -Name TestSection -ScriptBlock { Paragraph 'TestParagraph' } | Out-JsonSection
18 |
19 | Assert-MockCalled -CommandName Out-JsonParagraph -Exactly 1
20 | }
21 |
22 | It 'calls Out-JsonParagraph twice' {
23 | Mock -CommandName Out-JsonParagraph
24 |
25 | Section -Name TestSection -ScriptBlock { Paragraph 'TestParagraph'; Paragraph 'TestParagraph'; } | Out-JsonSection
26 |
27 | Assert-MockCalled -CommandName Out-JsonParagraph -Exactly 3
28 | }
29 |
30 | It 'calls Out-JsonTable' {
31 | Mock -CommandName Out-JsonTable
32 |
33 | Section -Name TestSection -ScriptBlock { Get-Process | Select-Object -First 3 | Table TestTable } | Out-JsonSection
34 |
35 | Assert-MockCalled -CommandName Out-JsonTable -Exactly 1
36 | }
37 |
38 | It 'warns on call Out-JsonTOC' {
39 | Mock -CommandName Out-JsonTOC
40 |
41 | Section -Name TestSection -ScriptBlock { TOC 'TestTOC' } | Out-JsonSection -WarningAction SilentlyContinue
42 |
43 | Assert-MockCalled Out-JsonTOC -Exactly 0
44 | }
45 |
46 | It 'calls nested Out-JsonSection' {
47 | ## Note this must be called last in the Describe script block as the Out-XmlSection gets mocked!
48 | Mock -CommandName Out-JsonSection
49 |
50 | Section -Name TestSection -ScriptBlock { Section -Name SubSection { } } | Out-JsonSection
51 |
52 | Assert-MockCalled -CommandName Out-JsonSection -Exactly 1
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------