├── BlogPost ├── PlasterManifest.ps1 ├── PlasterManifest.xml └── blogPost.md ├── Function ├── PlasterManifest.xml ├── functionTemplate.ps1 └── testsTemplate.ps1 ├── Module ├── .gitignore ├── CommandFlow.ps1 ├── PlasterManifest.xml ├── README.md ├── basicTest.ps1 ├── default.build.ps1 └── template.psm1 ├── PlasterTemplates.psd1 ├── README.md └── Tests └── PlasterTemplates.tests.ps1 /BlogPost/PlasterManifest.ps1: -------------------------------------------------------------------------------- 1 | PlasterManifest { 2 | Metadata { 3 | Title = "Blog Post" 4 | TemplateName = 'BlogPost' 5 | Author = "David Christian" 6 | Description = "Creates a new blog post draft for OverPoweredShell.com" 7 | TemplateVersion = '0.0.1' 8 | } 9 | 10 | Parameters { 11 | text -Name PostTitle -Prompt "Title of your new post" 12 | } 13 | 14 | Content { 15 | TemplateFile -Source 'blogPost.md' -Destination '${PLASTER_PARAM_PostTitle}.md' 16 | } 17 | } | Export-PlasterManifest -Destination .\PlasterManifest.xml -Verbose -------------------------------------------------------------------------------- /BlogPost/PlasterManifest.xml: -------------------------------------------------------------------------------- 1 |  3 | 4 | BlogPost 5 | c66f23d4-5e74-4606-b194-f2c5d4db9a19 6 | 0.0.1 7 | Blog Post 8 | Creates a new blog post draft for OverPoweredShell.com 9 | David Christian 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /BlogPost/blogPost.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | <% 4 | "title: $PLASTER_PARAM_PostTitle" 5 | %> 6 | --- 7 | 8 | Write some stuff about your post here! 9 | 10 | **The Good Stuff:** 11 | Is it really good though? 12 | 13 | 14 | -------------------------------------------------------------------------------- /Function/PlasterManifest.xml: -------------------------------------------------------------------------------- 1 |  2 | 4 | 5 | FunctionTemplate 6 | c0b57946d-f52f-4168-b152-4fdb334b9fca 7 | 0.0.1 8 | DC Custom Function Template 9 | Plaster template to create an advanced function with tests. 10 | David Christian 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /Function/functionTemplate.ps1: -------------------------------------------------------------------------------- 1 | <% 2 | "function $PLASTER_PARAM_FunctionName" 3 | %> 4 | { 5 | <% 6 | If ($PLASTER_PARAM_Help -eq 'Yes') 7 | { 8 | @" 9 | <# 10 | .Synopsis 11 | Short description 12 | .DESCRIPTION 13 | Long description 14 | .EXAMPLE 15 | Example of how to use this cmdlet 16 | #> 17 | "@ 18 | } 19 | %> 20 | <% 21 | if ($PLASTER_PARAM_CmdletBinding -eq 'Simple') 22 | { 23 | @" 24 | [CmdletBinding()] 25 | "@ 26 | } 27 | else 28 | { 29 | @' 30 | [CmdletBinding(DefaultParameterSetName='Parameter Set 1', 31 | SupportsShouldProcess=$true, 32 | PositionalBinding=$false, 33 | HelpUri = 'http://www.microsoft.com/', 34 | ConfirmImpact='Medium')] 35 | '@ 36 | } 37 | %> 38 | Param 39 | ( 40 | <% 41 | if ($PLASTER_PARAM_ComputerName -eq 'Yes') 42 | { 43 | @' 44 | [Parameter( 45 | ValueFromPipeline=$true, 46 | ValueFromPipelineByPropertyName=$true, 47 | Position=0)] 48 | [string[]] 49 | $ComputerName 50 | '@ 51 | } 52 | %> 53 | ) 54 | <% 55 | if ($PLASTER_PARAM_PipelineSupport -eq 'Yes') 56 | { 57 | @' 58 | begin 59 | { 60 | 61 | } 62 | process 63 | { 64 | '@ 65 | } 66 | %> 67 | <% 68 | if ($PLASTER_PARAM_ComputerName -eq 'Yes' -and $PLASTER_PARAM_PipelineSupport -eq 'Yes') 69 | { 70 | @' 71 | forEach ($computer in $ComputerName) 72 | { 73 | 74 | } 75 | '@ 76 | } 77 | elseif ($PLASTER_PARAM_ComputerName -eq 'Yes') 78 | { 79 | @' 80 | forEach ($computer in $ComputerName) 81 | { 82 | 83 | } 84 | '@ 85 | } 86 | %> 87 | <% 88 | if ($PLASTER_PARAM_PipelineSupport -eq 'Yes') 89 | { 90 | @' 91 | } 92 | end 93 | { 94 | 95 | } 96 | '@ 97 | } 98 | %> 99 | } -------------------------------------------------------------------------------- /Function/testsTemplate.ps1: -------------------------------------------------------------------------------- 1 | <% 2 | "Describe $PLASTER_PARAM_FunctionName {" 3 | %> 4 | It "Needs to have real tests" { 5 | $true | Should be $true 6 | } 7 | } -------------------------------------------------------------------------------- /Module/.gitignore: -------------------------------------------------------------------------------- 1 | Output/ -------------------------------------------------------------------------------- /Module/CommandFlow.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [Parameter()] 3 | [string] 4 | $DestinationPath, 5 | 6 | [Parameter()] 7 | [switch] 8 | $HideGraph 9 | ) 10 | 11 | $exportParams = @{ 12 | ShowGraph = $true 13 | } 14 | 15 | if($HideGraph) 16 | { 17 | $exportParams.ShowGraph = $false 18 | } 19 | 20 | if($DestinationPath) 21 | { 22 | $exportParams.DestinationPath = $DestinationPath 23 | } 24 | 25 | graph CommandFlow { 26 | $moduleRoot = Split-Path -Path $PSScriptRoot -Parent 27 | $scripts = @{} 28 | $folders = @() 29 | 30 | if (Test-Path -Path "$moduleRoot\Public") 31 | { 32 | $folders += "$moduleRoot\Public\*ps1" 33 | } 34 | 35 | if (Test-Path -Path "$moduleRoot\Internal") 36 | { 37 | $folders += "$moduleRoot\Internal\*ps1" 38 | } 39 | 40 | Get-ChildItem -Path $folders | 41 | ForEach-Object -Process { 42 | $scripts[$PSItem.BaseName] = $PSItem.FullName 43 | } 44 | 45 | $scriptNames = $scripts.Keys | Sort-Object 46 | ForEach ($script in $scriptNames) 47 | { 48 | 49 | node $script 50 | $contents = Get-Content -Path $scripts[$script] -ErrorAction Stop 51 | $errors = $null 52 | $commands = ([System.Management.Automation.PSParser]::Tokenize($contents, [ref]$errors) | 53 | Where-Object -FilterScript {$PSItem.Type -eq 'Command'}).Content 54 | ForEach ($command in $commands) 55 | { 56 | If ($scripts[$command]) 57 | { 58 | Edge $script -To $command 59 | } 60 | } 61 | } 62 | } | Export-PSGraph @exportParams -------------------------------------------------------------------------------- /Module/PlasterManifest.xml: -------------------------------------------------------------------------------- 1 |  2 | 4 | 5 | ModuleTemplate 6 | f7717d26-d77f-4358-8480-5928f7766bff 7 | 1.0.0 8 | DC Custom Module Template 9 | Plaster template to create a module 10 | David Christian 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | Setting up your project 48 | 49 | 50 | Creating you folders for module: 51 | 52 | 53 | 54 | 55 | 56 | Setting up support for Pester 57 | 58 | 59 | 60 | Setting up support for Git 61 | 62 | 63 | Setting up support for Invoke-Build 64 | 65 | 66 | Setting up support for PSGraph 67 | 68 | 69 | 70 | Setting up support for PlatyPS 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /Module/README.md: -------------------------------------------------------------------------------- 1 | <% 2 | "# $($PLASTER_PARAM_ModuleName)" 3 | "" 4 | "$PLASTER_PARAM_ModuleDesc" 5 | %> -------------------------------------------------------------------------------- /Module/basicTest.ps1: -------------------------------------------------------------------------------- 1 | $moduleRoot = Resolve-Path "$PSScriptRoot\.." 2 | $moduleName = Split-Path $moduleRoot -Leaf 3 | 4 | Describe "General project validation: $moduleName" { 5 | 6 | $scripts = Get-ChildItem $moduleRoot -Include *.ps1, *.psm1, *.psd1 -Recurse 7 | 8 | # TestCases are splatted to the script so we need hashtables 9 | $testCase = $scripts | Foreach-Object {@{file = $_}} 10 | It "Script should be valid powershell" -TestCases $testCase { 11 | param($file) 12 | 13 | $file.fullname | Should Exist 14 | 15 | $contents = Get-Content -Path $file.fullname -ErrorAction Stop 16 | $errors = $null 17 | $null = [System.Management.Automation.PSParser]::Tokenize($contents, [ref]$errors) 18 | $errors.Count | Should Be 0 19 | } 20 | } -------------------------------------------------------------------------------- /Module/default.build.ps1: -------------------------------------------------------------------------------- 1 | <% 2 | $buildParams = @("task . Clean", "Build") 3 | if ($PLASTER_PARAM_Pester -eq "Yes") 4 | { 5 | $buildParams += "Tests" 6 | } 7 | 8 | if ($PLASTER_PARAM_PlatyPS -eq "Yes") 9 | { 10 | $buildParams += "ExportHelp" 11 | } 12 | 13 | if ($PLASTER_PARAM_PSGraph -eq "Yes") 14 | { 15 | $buildParams += "GenerateGraph" 16 | } 17 | 18 | $buildParams += "Stats" 19 | 20 | $buildParams -join ", " 21 | %> 22 | <% 23 | if ($PLASTER_PARAM_Pester -eq "Yes") 24 | { 25 | "task Tests ImportCompipledModule, Pester" 26 | } 27 | 28 | %> 29 | <% 30 | $tasks = @("task CreateManifest CopyPSD, UpdatPublicFunctionsToExport") 31 | if ($PLASTER_PARAM_FunctionFolders -contains 'DSCResources') 32 | { 33 | $tasks += "UpdateDSCResourceToExport" 34 | } 35 | ($tasks -join ", ") 36 | %> 37 | task Build Compile, CreateManifest 38 | task Stats RemoveStats, WriteStats 39 | 40 | $script:ModuleName = Split-Path -Path $PSScriptRoot -Leaf 41 | $script:ModuleRoot = $PSScriptRoot 42 | $script:OutPutFolder = "$PSScriptRoot\Output" 43 | <% 44 | $folders = @() 45 | if ($PLASTER_PARAM_FunctionFolders -contains 'Public') 46 | { 47 | $folders += "'Public'" 48 | } 49 | 50 | if ($PLASTER_PARAM_FunctionFolders -contains 'Internal') 51 | { 52 | $folders += "'Internal'" 53 | } 54 | 55 | if ($PLASTER_PARAM_FunctionFolders -contains 'Classes') 56 | { 57 | $folders += "'Classes'" 58 | } 59 | 60 | if ($PLASTER_PARAM_FunctionFolders -contains 'DSCResources') 61 | { 62 | $folders += "'DSCResources'" 63 | } 64 | 65 | $importfolders = $folders -join ", " 66 | 67 | '$script:ImportFolders = @({0})' -f $importfolders 68 | %> 69 | $script:PsmPath = Join-Path -Path $PSScriptRoot -ChildPath "Output\$($script:ModuleName)\$($script:ModuleName).psm1" 70 | $script:PsdPath = Join-Path -Path $PSScriptRoot -ChildPath "Output\$($script:ModuleName)\$($script:ModuleName).psd1" 71 | <% 72 | if ($PLASTER_PARAM_PlatyPS -eq "Yes") 73 | { 74 | '$script:HelpPath = Join-Path -Path $PSScriptRoot -ChildPath "Output\$($script:ModuleName)\en-US"' 75 | } 76 | %> 77 | 78 | $script:PublicFolder = 'Public' 79 | $script:DSCResourceFolder = 'DSCResources' 80 | 81 | 82 | task "Clean" { 83 | if (-not(Test-Path $script:OutPutFolder)) 84 | { 85 | New-Item -ItemType Directory -Path $script:OutPutFolder > $null 86 | } 87 | 88 | Remove-Item -Path "$($script:OutPutFolder)\*" -Force -Recurse 89 | } 90 | 91 | $compileParams = @{ 92 | Inputs = { 93 | foreach ($folder in $script:ImportFolders) 94 | { 95 | Get-ChildItem -Path $folder -Recurse -File -Filter '*.ps1' 96 | } 97 | } 98 | 99 | Output = { 100 | $script:PsmPath 101 | } 102 | } 103 | 104 | task Compile @compileParams { 105 | if (Test-Path -Path $script:PsmPath) 106 | { 107 | Remove-Item -Path $script:PsmPath -Recurse -Force 108 | } 109 | New-Item -Path $script:PsmPath -Force > $null 110 | 111 | foreach ($folder in $script:ImportFolders) 112 | { 113 | $currentFolder = Join-Path -Path $script:ModuleRoot -ChildPath $folder 114 | Write-Verbose -Message "Checking folder [$currentFolder]" 115 | 116 | if (Test-Path -Path $currentFolder) 117 | { 118 | $files = Get-ChildItem -Path $currentFolder -File -Filter '*.ps1' 119 | foreach ($file in $files) 120 | { 121 | Write-Verbose -Message "Adding $($file.FullName)" 122 | Get-Content -Path $file.FullName >> $script:PsmPath 123 | } 124 | } 125 | } 126 | } 127 | 128 | task CopyPSD { 129 | New-Item -Path (Split-Path $script:PsdPath) -ItemType Directory -ErrorAction 0 130 | $copy = @{ 131 | Path = "$($script:ModuleName).psd1" 132 | Destination = $script:PsdPath 133 | Force = $true 134 | Verbose = $true 135 | } 136 | Copy-Item @copy 137 | } 138 | 139 | task UpdatPublicFunctionsToExport -if (Test-Path -Path $script:PublicFolder) { 140 | $publicFunctions = (Get-ChildItem -Path $script:PublicFolder | 141 | Select-Object -ExpandProperty BaseName) -join "', '" 142 | 143 | $publicFunctions = "FunctionsToExport = @('{0}')" -f $publicFunctions 144 | 145 | (Get-Content -Path $script:PsdPath) -replace "FunctionsToExport = '\*'", $publicFunctions | 146 | Set-Content -Path $script:PsdPath 147 | } 148 | 149 | <% 150 | if ($PLASTER_PARAM_FunctionFolders -contains 'DSCResources') 151 | { 152 | @' 153 | task UpdateDSCResourceToExport -if (Test-Path -Path $script:DSCResourceFolder) { 154 | $resources = (Get-ChildItem -Path $script:DSCResourceFolder | 155 | Select-Object -ExpandProperty BaseName) -join "', '" 156 | 157 | $resources = "'{0}'" -f $resources 158 | 159 | (Get-Content -Path $script:PsdPath) -replace "'_ResourcesToExport_'", $resources | 160 | Set-Content -Path $script:PsdPath 161 | } 162 | '@ 163 | } 164 | %> 165 | 166 | task ImportCompipledModule -if (Test-Path -Path $script:PsmPath) { 167 | Get-Module -Name $script:ModuleName | 168 | Remove-Module -Force 169 | Import-Module -Name $script:PsdPath -Force 170 | } 171 | 172 | <% 173 | if ($PLASTER_PARAM_Pester -eq "Yes") 174 | { 175 | @' 176 | task Pester { 177 | $resultFile = "{0}\testResults{1}.xml" -f $script:OutPutFolder, (Get-date -Format 'yyyyMMdd_hhmmss') 178 | $testFolder = Join-Path -Path $PSScriptRoot -ChildPath 'Tests\*' 179 | Invoke-Pester -Path $testFolder -OutputFile $resultFile -OutputFormat NUnitxml 180 | } 181 | '@ 182 | } 183 | %> 184 | 185 | <% 186 | if ($PLASTER_PARAM_PSGraph -eq "Yes") 187 | { 188 | @' 189 | task GenerateGraph -if (Test-Path -Path 'Graphs') { 190 | $Graphs = Get-ChildItem -Path "Graphs\*" 191 | 192 | Foreach ($graph in $Graphs) 193 | { 194 | $graphLocation = [IO.Path]::Combine($script:OutPutFolder, $script:ModuleName, "$($graph.BaseName).png") 195 | . $graph.FullName -DestinationPath $graphLocation -Hide 196 | } 197 | } 198 | '@ 199 | } 200 | %> 201 | 202 | 203 | task RemoveStats -if (Test-Path -Path "$($script:OutPutFolder)\stats.json") { 204 | Remove-Item -Force -Verbose -Path "$($script:OutPutFolder)\stats.json" 205 | } 206 | 207 | task WriteStats { 208 | $folders = Get-ChildItem -Directory | 209 | Where-Object {$PSItem.Name -ne 'Output'} 210 | 211 | $stats = foreach ($folder in $folders) 212 | { 213 | $files = Get-ChildItem "$($folder.FullName)\*" -File 214 | if($files) 215 | { 216 | Get-Content -Path $files | 217 | Measure-Object -Word -Line -Character | 218 | Select-Object -Property @{N = "FolderName"; E = {$folder.Name}}, Words, Lines, Characters 219 | } 220 | } 221 | $stats | ConvertTo-Json > "$script:OutPutFolder\stats.json" 222 | } 223 | 224 | <% 225 | if ($PLASTER_PARAM_PlatyPS -eq "Yes") 226 | { 227 | @' 228 | task ExportHelp -if (Test-Path -Path "$script:ModuleRoot\Help") { 229 | New-ExternalHelp -Path "$script:ModuleRoot\Help" -OutputPath $script:HelpPath 230 | } 231 | '@ 232 | } 233 | %> -------------------------------------------------------------------------------- /Module/template.psm1: -------------------------------------------------------------------------------- 1 | $functionFolders = @('Public', 'Internal', 'Classes') 2 | ForEach ($folder in $functionFolders) 3 | { 4 | $folderPath = Join-Path -Path $PSScriptRoot -ChildPath $folder 5 | If (Test-Path -Path $folderPath) 6 | { 7 | Write-Verbose -Message "Importing from $folder" 8 | $functions = Get-ChildItem -Path $folderPath -Filter '*.ps1' 9 | ForEach ($function in $functions) 10 | { 11 | Write-Verbose -Message " Importing $($function.BaseName)" 12 | . $($function.FullName) 13 | } 14 | } 15 | } 16 | $publicFunctions = (Get-ChildItem -Path "$PSScriptRoot\Public" -Filter '*.ps1').BaseName 17 | Export-ModuleMember -Function $publicFunctions -------------------------------------------------------------------------------- /PlasterTemplates.psd1: -------------------------------------------------------------------------------- 1 | @{ 2 | RootModule = 'PlasterTemplates' 3 | ModuleVersion = '0.0.1' 4 | GUID = '66a75c73-a800-473b-9bff-5942a3363a36' 5 | Author = 'David Christian' 6 | CompanyName = 'OverPoweredShell.com' 7 | Description = 'Collection of Plaster Templates Created by David Christian' 8 | PrivateData = @{ 9 | PSData = @{ 10 | Extensions = @{ 11 | Module = 'Plaster' 12 | Details = @{ 13 | TemplatePaths = @('Function', 'Module') 14 | } 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Plaster Templates by David Christian 2 | 3 | A central repository for my Plater Templates -------------------------------------------------------------------------------- /Tests/PlasterTemplates.tests.ps1: -------------------------------------------------------------------------------- 1 | Describe PlasterTemplates { 2 | BeforeAll { 3 | $moduleRoot = "$PSScriptRoot\.." 4 | $moduleData = Import-PowerShellDataFile -Path "$moduleRoot\PlasterTemplates.psd1" 5 | } 6 | 7 | It "Should have module data" { 8 | $moduleData | Should not be $null 9 | } 10 | 11 | It "Should have Plaster Extensions" { 12 | $moduleData.PrivateData.PSData.Extensions.Module -contains 'Plaster' | Should be $true 13 | } 14 | 15 | ForEach($templatePath in $moduleData.PrivateData.PSData.Extensions.Details.TemplatePaths) 16 | { 17 | $manifestPath = [System.IO.Path]::Combine($moduleRoot,$templatePath,"PlasterManifest.Xml") 18 | 19 | It "Should have a manifest for Path [$templatePath]" { 20 | Test-Path -Path $manifestPath | Should be $true 21 | } 22 | } 23 | } --------------------------------------------------------------------------------