Downloads:
970
Downloads of v 0.2.0:
970
Last Update:
22 Nov 2016
Package Maintainer(s):
Software Author(s):
- Aaron Jensen
Tags:
powershell module help tools- Software Specific:
- Software Site
- Software License
- Package Specific:
- Package outdated?
- Package broken?
- Contact Maintainers
- Contact Site Admins
- Software Vendor?
- Report Abuse
- Download
Silk
- 1
- 2
- 3
0.2.0 | Updated: 22 Nov 2016
- Software Specific:
- Software Site
- Software License
- Package Specific:
- Package outdated?
- Package broken?
- Contact Maintainers
- Contact Site Admins
- Software Vendor?
- Report Abuse
- Download
Downloads:
970
Downloads of v 0.2.0:
970
Maintainer(s):
Software Author(s):
- Aaron Jensen
Silk 0.2.0
Legal Disclaimer: Neither this package nor Chocolatey Software, Inc. are affiliated with or endorsed by Aaron Jensen. The inclusion of Aaron Jensen trademark(s), if any, upon this webpage is solely to identify Aaron Jensen goods or services and not for commercial purposes.
- 1
- 2
- 3
All Checks are Passing
3 Passing Tests
Deployment Method: Individual Install, Upgrade, & Uninstall
To install Silk, run the following command from the command line or from PowerShell:
To upgrade Silk, run the following command from the command line or from PowerShell:
To uninstall Silk, run the following command from the command line or from PowerShell:
Deployment Method:
This applies to both open source and commercial editions of Chocolatey.
1. Enter Your Internal Repository Url
(this should look similar to https://community.chocolatey.org/api/v2/)
2. Setup Your Environment
1. Ensure you are set for organizational deployment
Please see the organizational deployment guide
2. Get the package into your environment
Option 1: Cached Package (Unreliable, Requires Internet - Same As Community)-
Open Source or Commercial:
- Proxy Repository - Create a proxy nuget repository on Nexus, Artifactory Pro, or a proxy Chocolatey repository on ProGet. Point your upstream to https://community.chocolatey.org/api/v2/. Packages cache on first access automatically. Make sure your choco clients are using your proxy repository as a source and NOT the default community repository. See source command for more information.
- You can also just download the package and push it to a repository Download
-
Open Source
-
Download the package:
Download - Follow manual internalization instructions
-
-
Package Internalizer (C4B)
-
Run: (additional options)
choco download silk --internalize --source=https://community.chocolatey.org/api/v2/
-
For package and dependencies run:
choco push --source="'INTERNAL REPO URL'"
- Automate package internalization
-
Run: (additional options)
3. Copy Your Script
choco upgrade silk -y --source="'INTERNAL REPO URL'" [other options]
See options you can pass to upgrade.
See best practices for scripting.
Add this to a PowerShell script or use a Batch script with tools and in places where you are calling directly to Chocolatey. If you are integrating, keep in mind enhanced exit codes.
If you do use a PowerShell script, use the following to ensure bad exit codes are shown as failures:
choco upgrade silk -y --source="'INTERNAL REPO URL'"
$exitCode = $LASTEXITCODE
Write-Verbose "Exit code was $exitCode"
$validExitCodes = @(0, 1605, 1614, 1641, 3010)
if ($validExitCodes -contains $exitCode) {
Exit 0
}
Exit $exitCode
- name: Install silk
win_chocolatey:
name: silk
version: '0.2.0'
source: INTERNAL REPO URL
state: present
See docs at https://docs.ansible.com/ansible/latest/modules/win_chocolatey_module.html.
chocolatey_package 'silk' do
action :install
source 'INTERNAL REPO URL'
version '0.2.0'
end
See docs at https://docs.chef.io/resource_chocolatey_package.html.
cChocoPackageInstaller silk
{
Name = "silk"
Version = "0.2.0"
Source = "INTERNAL REPO URL"
}
Requires cChoco DSC Resource. See docs at https://github.com/chocolatey/cChoco.
package { 'silk':
ensure => '0.2.0',
provider => 'chocolatey',
source => 'INTERNAL REPO URL',
}
Requires Puppet Chocolatey Provider module. See docs at https://forge.puppet.com/puppetlabs/chocolatey.
4. If applicable - Chocolatey configuration/installation
See infrastructure management matrix for Chocolatey configuration elements and examples.
This package was approved by moderator flcdrg on 26 Nov 2016.
PowerShell module for publishing another module's help system as a website.
# 0.2.0 (21 November 2016)
* Improved `about_Silk` help topic.
* Added example scripts `Invoke-Build.ps1`, `Publish-Module.ps1`, and `New-Website.ps1` to show how to use Silk.
md5: 6A2AA9E5FD90BC15B51CA32113271B34 | sha1: 36A6C7FFF88DED2F28E846320721BC2A758B9C29 | sha256: 605E6AD93DFEA7F777735558A01B286602C156D1062E7A5872F84410128E1B92 | sha512: 6037A6FCFBB13955E9554BDA72522A1F9406132A2D8986C71CA94724391525610E454DA4F5757E81A0DB57FAE75C0363EC47C69BD9BD00BDBB4FF91CF13CE6EA
md5: C0C47419C0641F4638E3758F4E997C2B | sha1: E412DEA7B234D73048213AB9391500501DEB46CD | sha256: 8339DEB284895BC2D8B41C762C9D967DD8A62E420E46B877457A4361DCF42068 | sha512: ADB5EE24A22B9E3C0C35E4C8C8332B1E55F87AF0232BD4AF3D72F4419FB9F33AB6456ED31965BD0FCF980C85F5CBE61EEA3B4442A135B603D93406B97204C0AE
NAME
Silk
SYNOPSIS
Silk is a PowerShell module for authoring, building, and publishing
PowerShell modules and creating a website from a module's help
topics.
DESCRIPTION
Silk is a PowerShell module for PowerShell module authors. Use it to:
* Automatically version of your module
* Easily build your module, including any compiled assemblies
* Publish your module as a Chocolatey and/or NuGet package
* Publish your module to the PowerShell gallery
* Convert your module's help as a website
If you look in Silk's Examples directory, you'll see three scripts
that demonstrate its capabilities:
* `Invoke-Build.ps1` shows how to build and package your module with
Silk
* `Publish-Module.ps1` shows how to publish your module to
Chocolatey, NuGet, and the PowerShell Gallery.
* `Publish-Website.ps1` shows how to publish your module's help to a
website.
## Versioning and Building
To get started, create a `build.ps1` file in the root of your
repository. In your `build.ps1` file, import Silk. Use Silk's
`Set-ModuleVersion` function to set your module's version and
compile any code.
Set-ModuleVersion -ManifestPath "PATH TO MODULE'S *.psd1 FILE" `
-Version "VERSION TO BUILD" `
-ReleaseNotesPath 'PATH TO RELEASE NOTES FILE'
`Set-ModuleVersion` will also set the version in a .nuspec file (for
creating Chocolatey and NuGet packages) and an AssemblyInfo.cs file
(for versioning your module's assembly.
`Set-ModuleVersion` will build a Visual Studio solution if you pass
its path via the `SolutionPath` parameter.
Silk expects your release notes files to be written in Markdown. It
expects each level-1 header (marked with a single `#` at the
beginning of a line) to be a version number, and everything after
that header to the next level-1 header (or the end of the file) to
be the release notes for that version. When `Set-ModuleVersion` sets
the version in a release notes file, it only sets the first level-1
header it finds.
See the `RELEASE_NOTES.md` included with the Silk module for an
example.
# Packaging and Preparing to Release
Silk can do the following actions to prepare your module for a
release:
* The `Set-ReleaseNotesReleaseDate` function set the release date in
your release notes file.
* The `Set-ModuleManifestMetadata` function sets the release notes
and tags fields in your module manifest (i.e. .psd1 file).
* Thge `Set-ModuleNuspec` function sets metadata in a .nuspec file
(for Chocolatey and NuGet packages). The .nuspec file's description,
version, tags, and copyright fields are set from your module's
manifest (i.e. .psd1) file. The .nuspec file's releaseNotes property
is pulled from your release notes file.
* The `New-NugetPackage` function will create a NuGet package from a
.nuspec file.
* The `New-ChocolateyPackage` function will create a Chocolatey
package from a .nuspec file.
## Publishing/Releasing a Module
Silk has the following functions you can use to publish/release your
module:
* `Publish-NuGetPackage` will publish your module's .nupkg file to
nuget.org. (You create a .nupkg file from a .nuspec file with the
`New-NuGetPackage` function.)
* `Pulish-ChocolateyPackage` will publish your module's .nupkg file
to chocolatey.org. (You create a .nupkg file from a .nuspec file
with the `New-ChocolateyPackage` function.
* `Publish-PowerShellGalleryModule` will publish your module to the
PowerShell Gallery (https://powershellgallery.com).
## Creating a Website from a Module's Help Topics
Silk has the following functions for generating a website from a
module's help topics. Silk assumes your help is written in Markdown.
Silk will auto-link to commands inside your module. Surround your
module's command names, script names, and about topics in backticks,
and Silk will convert it to a link to that item's help topic. For
example, `about_Silk` will get converted to `<a
href="about_Silk.html">about_Silk</a>`.
* `Convert-ModuleHelpToHtml` converts the help for each command in a
module to an .html page/file.
* `New-ModuleHelpIndex` creates an index.html page that includes
links to a module's `about_` help topics, standalone scripts, and
commands. The commands are organized into three tabs: one organized
by tags, one organized alphabetically by command name, and one
organized alphabetically by verb.
* `Convert-ABoutTopicToHtml` converts about topics to HTML pages.
<#
.SYNOPSIS
Sets the version number for the LibGit2 module.
#>
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
[CmdletBinding()]
param(
[Version]
# The version to build. If not supplied, build the version as currently defined.
$Version,
[Switch]
# Build and create packages that will be published.
$ForRelease
)
#Requires -Version 4
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
& (Join-Path -Path $PSScriptRoot -ChildPath 'Silk\Import-Silk.ps1' -Resolve)
$manifestPath = Join-Path -Path $PSScriptRoot -ChildPath 'Silk\Silk.psd1'
$manifest = Test-ModuleManifest -Path $manifestPath
if( -not $manifest )
{
return
}
$nuspecPath = Join-Path -Path $PSScriptRoot -ChildPath 'Silk.nuspec' -Resolve
$releaseNotesPath = Join-Path -Path $PSScriptRoot -ChildPath 'RELEASE_NOTES.md' -Resolve
# If you need to compile an assembly or other code, add SolutionPath and AssemblyInfoPath parameters, e.g.
# -SolutionPath (Join-Path -Path $PSScriptRoot -ChildPath 'Source\Silk.sln' -Resolve) `
# -AssemblyInfoPath (Join-Path -Path $PSScriptRoot -ChildPath 'Source\Silk\Properties\AssemblyInfo.cs' -Resolve)
Set-ModuleVersion -ManifestPath $manifestPath `
-Version $Version `
-ReleaseNotesPath $releaseNotesPath `
-NuspecPath $nuspecPath
Import-Module -Name (Join-Path -Path $PSScriptRoot -ChildPath 'Tools\Pester' -Resolve)
$result = Invoke-Pester -Script (Join-Path -Path $PSScriptRoot -ChildPath 'Tests') -PassThru
if( $result.FailedCount )
{
exit
}
if( -not $ForRelease )
{
return
}
$valid = Assert-ModuleVersion -ManifestPath $manifestPath -ReleaseNotesPath $releaseNotesPath -NuspecPath $nuspecPath -ExcludeAssembly 'LibGit2Sharp.dll'
if( -not $valid )
{
Write-Error -Message ('Silk isn''t at the right version. Please use the -Version parameter to set the version.')
return
}
Set-ReleaseNotesReleaseDate -ManifestPath $manifestPath -ReleaseNotesPath $releaseNotesPath
$tags = @( 'powershell', 'module', 'help', 'tools' )
Set-ModuleManifestMetadata -ManifestPath $manifestPath -Tag $tags -ReleaseNotesPath $releaseNotesPath
$outputDirectory = Join-Path -Path $PSScriptRoot -ChildPath 'Output'
if( (Test-Path -Path $outputDirectory -PathType Container) )
{
Get-ChildItem -Path $outputDirectory | Remove-Item -Recurse
}
else
{
New-Item -Path $outputDirectory -ItemType 'directory'
}
Set-ModuleNuspec -ManifestPath $manifestPath `
-NuspecPath $nuspecPath `
-ReleaseNotesPath $releaseNotesPath `
-Tags $tags `
-PackageID 'Silk.PowerShell' `
-PackageTitle 'Silk.PowerShell'
New-NuGetPackage -OutputDirectory (Join-Path -Path $outputDirectory -ChildPath 'nuget.org') `
-ManifestPath $manifestPath `
-NuspecPath $nuspecPath `
-NuspecBasePath $PSScriptRoot `
-PackageName 'Silk.PowerShell'
Set-ModuleNuspec -ManifestPath $manifestPath `
-NuspecPath $nuspecPath `
-ReleaseNotesPath $releaseNotesPath `
-Tags $tags `
-PackageID 'Silk' `
-PackageTitle 'Silk'
New-ChocolateyPackage -OutputDirectory (Join-Path -Path $outputDirectory -ChildPath 'chocolatey.org') `
-ManifestPath $manifestPath `
-NuspecPath $nuspecPath
$source = Join-Path -Path $PSScriptRoot -ChildPath 'Silk'
$destination = Join-Path -Path $outputDirectory -ChildPath 'Silk'
robocopy.exe $source $destination /MIR /NJH /NJS /NP /NDL /XD /XF '*.pdb'
$examplesDir = Join-Path -Path $destination -ChildPath 'Examples'
New-Item -Path $examplesDir -ItemType 'Directory'
Get-ChildItem -Path (Join-Path -Path $PSScriptRoot -ChildPath 'build.ps1') |
Copy-Item -Destination (Join-Path -Path $examplesDir -ChildPath 'Invoke-Build.ps1')
Get-ChildItem -Path (Join-Path -Path $PSScriptRoot -ChildPath 'New-Website.ps1') |
Copy-Item -Destination $examplesDir
Get-ChildItem -Path (Join-Path -Path $PSScriptRoot -ChildPath 'Publish-Silk.ps1') |
Copy-Item -Destination (Join-Path -Path $examplesDir -ChildPath 'Publish-Module.ps1')
Get-ChildItem -Path 'RELEASE_NOTES.md','LICENSE','NOTICE' | Copy-Item -Destination $destination
<#
.SYNOPSIS
Creates the get-libgit2.org website.
.DESCRIPTION
The `New-Website.ps1` script generates the get-libgit2.org website. It uses the Silk module for Markdown to HTML conversion.
#>
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
[CmdletBinding()]
param(
)
#Requires -Version 4
Set-StrictMode -Version 'Latest'
function Out-HtmlPage
{
param(
[Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
[Alias('Html')]
# The contents of the page.
$Content,
[Parameter(Mandatory=$true)]
# The title of the page.
$Title,
[Parameter(Mandatory=$true)]
# The path under the web root of the page.
$VirtualPath
)
begin
{
Set-StrictMode -Version 'Latest'
}
process
{
$webRoot = Join-Path -Path $PSScriptRoot -ChildPath 'get-silk.org'
$path = Join-Path -Path $webRoot -ChildPath $VirtualPath
$templateArgs = @(
$Title,
$Content,
(Get-Date).Year
)
@'
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>{0}</title>
<link href="silk.css" type="text/css" rel="stylesheet" />
<link href="styles.css" type="text/css" rel="stylesheet" />
</head>
<body>
<ul id="SiteNav">
<li><a href="index.html">Get-Silk</a></li>
<li><a href="documentation.html">-Documentation</a></li>
<li><a href="releasenotes.html">-ReleaseNotes</a></li>
<li><a href="http://pshdo.com">-Blog</a></li>
<li><a href="http://github.com/pshdo/Silk">-Project</a></li>
</ul>
{1}
<div class="Footer">
Copyright {2} <a href="http://pshdo.com">Aaron Jensen</a>.
</div>
</body>
</html>
'@ -f $templateArgs | Set-Content -Path $path
}
end
{
}
}
$silkRoot = Join-Path -Path $PSScriptRoot -ChildPath '.\Silk' -Resolve
if( (Get-Module -Name 'Blade') )
{
Remove-Module 'Blade'
}
$headingMap = @{ }
& (Join-Path -Path $silkRoot -ChildPath 'Import-Silk.ps1' -Resolve)
try
{
Convert-ModuleHelpToHtml -ModuleName 'Silk' -HeadingMap $headingMap -Script 'Import-Silk.ps1' |
ForEach-Object { Out-HtmlPage -Title ('PowerShell - {0} - Silk' -f $_.Name) -VirtualPath ('{0}.html' -f $_.Name) -Content $_.Html }
}
finally
{
}
$tagsPath = Join-Path -Path $PSScriptRoot -ChildPath 'tags.json'
New-ModuleHelpIndex -TagsJsonPath $tagsPath -ModuleName 'Silk' -Script 'Import-Silk.ps1' |
Out-HtmlPage -Title 'PowerShell - Silk Module Documentation' -VirtualPath '/documentation.html'
$moduleTitle = 'Silk: PowerShell module for PowerShell module authors and projects'
Get-Item -Path (Join-Path -Path $PSScriptRoot -ChildPath 'Silk\en-US\about_Silk.help.txt') |
Convert-AboutTopicToHtml -ModuleName 'Silk' -Script 'Import-Silk.ps1' |
ForEach-Object {
$_ -replace '<h1>about_Silk</h1>','<h1>Silk</h1>'
} |
Out-HtmlPage -Title $moduleTitle -VirtualPath '/index.html'
$releaseNotesPath = Join-Path -Path $PSScriptRoot -ChildPath 'RELEASE_NOTES.md'
Get-Content -Path $releaseNotesPath -Raw |
Edit-HelpText -ModuleName 'Silk' |
Convert-MarkdownToHtml |
Out-HtmlPage -Title ('Release Notes - {0}' -f $moduleTitle) -VirtualPath '/releasenotes.html'
$silkCssPath = Join-Path -Path $silkRoot -ChildPath 'Resources\silk.css' -Resolve
$webroot = Join-Path -Path $PSScriptRoot -ChildPath 'get-silk.org'
Copy-Item -Path $silkCssPath -Destination $webroot -Verbose
<#
.SYNOPSIS
Packages and publishes Silk packages.
.DESCRIPTION
The `Publish-Silk.ps1` script packages and publishes a version of the Silk module. It uses the version defined in the Silk.psd1 file. Before publishing, it adds the current date to the version in the release notes, updates the module's website, then tags the latest revision with the version number. It then publishes the module to NuGet, Chocolatey, and the PowerShell Gallery. If the version of Silk being published already exists in a location, it is not re-published. If the PowerShellGet module isn't installed, the module is not publishes to the PowerShell Gallery.
.EXAMPLE
Publish-Silk.ps1
Yup. That's it.
#>
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
[CmdletBinding(SupportsShouldProcess=$true)]
param(
)
#Requires -Version 4
Set-StrictMode -Version Latest
& (Join-Path -Path $PSScriptRoot -ChildPath 'Silk\Import-Silk.ps1' -Resolve)
$silkRoot = Join-Path -Path $PSScriptRoot -ChildPath 'Output\Silk'
$releaseNotesPath = Join-Path -Path $silkRoot -ChildPath 'RELEASE_NOTES.md' -Resolve
$manifestPath = Join-Path -Path $silkRoot -ChildPath 'Silk.psd1'
$manifest = Test-ModuleManifest -Path $manifestPath
if( -not $manifest )
{
return
}
$nupkgPath = Join-Path -Path $PSScriptRoot `
-ChildPath ('Output\nuget.org\Silk.PowerShell.{0}.nupkg' -f $manifest.Version)
Publish-NuGetPackage -NupkgPath $nupkgPath
$nupkgPath = Join-Path -Path $PSScriptRoot `
-ChildPath ('Output\chocolatey.org\Silk.{0}.nupkg' -f $manifest.Version)
Publish-ChocolateyPackage -NupkgPath $nupkgPath
$tags = @( 'powershell', 'module', 'help', 'tools' )
Publish-PowerShellGalleryModule -ManifestPath $manifestPath `
-ModulePath $silkRoot `
-ReleaseNotesPath $releaseNotesPath `
-LicenseUri 'http://www.apache.org/licenses/LICENSE-2.0' `
-ProjectUri 'http://get-silk.org' `
-Tags $tags
4
function Convert-AboutTopicToHtml
{
<#
.SYNOPSIS
Converts an about topic into HTML.
.DESCRIPTION
The `Convert-AboutTopicToHtml` converts a PowerShell about topic into HTML. The about topic is expected to be [formatted like PowerShell's internal topics](https://msdn.microsoft.com/en-us/library/Dd878343.aspx):
TOPIC
about_<subject or module name>
SHORT DESCRIPTION
A short, one-line description of the topic contents.
LONG DESCRIPTION
A detailed, full description of the subject or purpose of the module.
EXAMPLES
Examples of how to use the module or how the subject feature works in practice.
KEYWORDS
Terms or titles on which you might expect your users to search for the information in this topic.
SEE ALSO
Text-only references for further reading. Hyperlinks cannot work in the Windows PowerShell console.
`Convert-AboutTopicToHtml` does the following:
* Removes the `TOPIC` AND `SHORT DESCRIPTION` headers
* Wraps the topic name in an <h1> tag
* Renames the `LONG DESCRIPTION` heading to '<h2>Description</h2>
* Wraps all other headers in <h2> elements.
* Converts the bodies of each section to HTML
Lines that don't begin with spaces are assumed to be headers.
Lines that begin with spaces are assumed to be content written in Markdown.
The `SEE ALSO` section is parsed, one line at a time for links, command names, and other help topics, e.g.
SEE ALSO
https://msdn.microsoft.com/en-us/library/Dd878343.aspx
about_Silk
Convert-AboutTopicToHtml
Would convert into a three item list, the first a link to the web, the second a link to the `about_Silk.html` topic, and the third to the `Convert-AboutTopicToHtml.html` page.
#>
[CmdletBinding()]
param(
[Parameter(Mandatory=$true,ValueFromPipeline=$true)]
# The name of the help topic, include the `about_` prefix, or a `FileInfo` object representing the help topic, or the help topic as a giant string.
$InputObject,
[string]
# The name of the topic you're converting. Only used if `InputObject` is the text of the about topic.
$TopicName,
[Parameter(Mandatory=$true)]
[string]
# The name of the module being documented.
$ModuleName,
[string]
# The heading used for the topic's name. Default is `TOPIC`.
$TopicHeading = 'TOPIC',
[string]
# The heading used for the topic's short description. Default is `SHORT DESCRIPTION`.
$ShortDescriptionHeading = 'SHORT DESCRIPTION',
[string]
# The heading used for the topic's long description. Default is `LONG DESCRIPTION`.
$LongDescriptionHeading = 'LONG DESCRIPTION',
[string]
# The heading used for the topic's `See Also` section. Default is `SEE ALSO`.
$SeeAlsoHeading = 'SEE ALSO',
[hashtable]
# A hashtable of headings to use. They key should be the section name. The value should be the heading name.
$HeadingMap = @{},
[string[]]
# The names of any scripts in the module.
$Script
)
begin
{
Set-StrictMode -Version 'Latest'
}
process
{
function Complete-Section
{
param(
[string]
$Heading,
[Parameter(Mandatory=$true)]
[AllowEmptyString()]
[string]
$Body
)
$Body = $Body.Trim()
switch( $Heading )
{
$TopicHeading
{
# We just don't want to do any Markdown conversion.
}
$SeeAlsoHeading
{
$lines = $Body -split ([Environment]::NewLine) |
Convert-RelatedLinkToHtml -ModuleName $ModuleName -Script $Script |
ForEach-Object { '<li>{0}</li>' -f $_ }
$Body = @'
<ul>
{0}
</ul>
'@ -f ($lines -join [Environment]::NewLine)
}
default
{
$Body = $Body | Edit-HelpText -ModuleName $ModuleName | Convert-MarkdownToHtml
}
}
$topic | Add-Member -Name $Heading -MemberType NoteProperty -Value $Body
}
if( $InputObject -is [IO.FileInfo] )
{
[string[]]$lines = $InputObject | Get-Content
$TopicName = $InputObject.BaseName -replace '\.help$' -f ''
}
elseif( $InputObject -is [string] -and $InputObject -match '^about_' )
{
[string[]]$lines = Get-Help -Name $InputObject
if( -not $lines )
{
Write-Error ('About topic ''{0}'' not found.' -f $InputObject)
return
}
$TopicName = $InputObject
}
else
{
$lines = $InputObject -split ([Environment]::NewLine)
}
$topic = [pscustomobject]@{ }
$currentHeader = $null
$currentContent = $null
$sectionOrder = New-Object 'Collections.Generic.List[string]'
$lastLineIdx = $lines.Count - 1
for( $idx = 0; $idx -lt $lines.Count; ++$idx )
{
$line = $lines[$idx]
if( -not $line -or $line -match '^\s+' )
{
if( $line.StartsWith(' ') )
{
$line = $line -replace '^ ',''
}
elseif( $line.StartsWith(' ') )
{
$line = $line -replace '^ ',''
}
[void]$currentContent.AppendLine( $line )
if( $idx -eq $lastLineIdx )
{
Complete-Section -Heading $currentHeader -Body $currentContent.ToString()
}
continue
}
else
{
# Header
if( $currentHeader )
{
Complete-Section -Heading $currentHeader -Body $currentContent.ToString()
}
$currentContent = New-Object 'Text.StringBuilder'
$currentHeader = [Globalization.CultureInfo]::CurrentCulture.TextInfo.ToTitleCase( $line.ToLowerInvariant() )
$sectionOrder.Add( $currentHeader )
}
}
if( -not ($topic | Get-Member -Name $TopicHeading) )
{
Write-Warning ('Topic ''{0}'' doesn''t have a ''{1}'' heading. Defaulting to {0}. Use the `TopicHeading` parameter to set the topic''s topic heading.' -f $TopicName,$TopicHeading)
Complete-Section -Heading 'TOPIC' -Body $TopicName
}
if( -not ($topic | Get-Member -Name $ShortDescriptionHeading) )
{
Write-Warning ('Topic ''{0}'' doesn''t have a ''{1}'' heading. Use the `ShortDescription` parameter to set the topic''s SHORT DESCRIPTION heading.' -f $TopicName,$ShortDescriptionHeading)
Complete-Section -Heading 'SHORT DESCRIPTION' -Body ''
}
if( -not $HeadingMap.ContainsKey($LongDescriptionHeading) )
{
$HeadingMap[$LongDescriptionHeading] = 'Description'
}
$content = New-Object 'Text.StringBuilder'
foreach( $section in $sectionOrder )
{
if( $section -eq $TopicHeading -or $section -eq $ShortDescriptionHeading )
{
continue
}
$heading = $section
if( $HeadingMap.ContainsKey($section) )
{
$heading = $HeadingMap[$section]
}
[void]$content.AppendLine( ('<h2>{0}</h2>' -f $heading) )
[void]$content.AppendLine( $topic.$Section )
}
@'
<h1>{0}</h1>
{1}
{2}
'@ -f $topic.$TopicHeading,$topic.$ShortDescriptionHeading,$content
}
end
{
}
}
function Convert-HelpToHtml
{
<#
.SYNOPSIS
Converts a command's help topic to HTML.
.DESCRIPTION
The `Convert-HelpToHtml` function convert's a command's help topic to HTML. This HTML can then be used in a complete HTML page. It will output the following parts of a help topic, in the following order:
* Name (in an `h1` element). You can override this name with the `DisplayName` parameter.
* Synopsis
* Syntax (which you can override with the `Syntax` parameter)
* Description
* Related Commands (i.e. `.LINK`)
* Parameters
* Parameters
* Input Types (i.e. `.INPUTS`)
* Return Types (i.e. `.OUTPUTS`)
* Notes
* Examples
`Convert-HelpToHtml` converts all help text to HTML using [MarkdownSharp](https://code.google.com/p/markdownsharp/), a C# [Markdown](https://daringfireball.net/projects/markdown/) implementation. Markdown "allows you to write using an easy-to-read, easy-to-write plain text format, [that is converted] to structurally valid XHTML (or HTML)". This makes your help web-friendly.
If you want to convert an entire module's help to HTML, including any scripts and DSC resources, use the `Convert-ModuleHelpToHtml` function. When converting help for a module, pass the module's name with the `ModuleName` parameter, and any of the module's commands or about topics found enclosed in backticks (Markdown's span of code indicators) will be converted to an anchor element whose `href` attribute is the command's name with a .html extension. For example, this help text:
> Silk's `Convert-HelpToHtml` function converts help text written with Markdown into HTML.
would get converted to
> Silk's <a href="Convert-HelpToHtml.html">Convert-HelpToHtml</a> function converts help text written with Markdown into HTML.
`Convert-HelpToHtml` assumes you'll take its output, wrap it in a full HTML page, and save all of these generated pages into the same directory. For example,
$html = Convert-HelpToHtml -Name 'Convert-HelpToHtml' -ModuleName 'Silk'
@"
<!DOCTYPE html>
<html>
<head>
<title>Convert-HelpToHTml</title>
<link href="silk.css" type="text/css" rel="stylesheet" />
</head>
<body>
$html
</body>
</html>
"@ | Set-Content -Path (Join-Path -Path $webRoot -ChildPath 'Convert-HelpToHtml.html')
`Convert-HelpToHtml` outputs HTML 5 (or tries to). For the best cross-browser compatability, make sure you define a doctype on each page. This is especially important for Internet Explorer. If you don't use a doctype, IE will display your pages in quirks mode, which won't display things correctly.
Silk ships with a default cascading stylesheet (CSS) in the `Resources` directory. Copy this file into your webroot and link to it in each of your pages (via the `link` tag). To customize the appearance of your pages, we recommend you create your own stylesheet and link to it in each of your pages. Make all your style changes in yoru stylesheet. Future versions of Silk will contain fixes/enhancements to the default stylesheet. Using your own will make upgrading easier.
.LINK
https://daringfireball.net/projects/markdown/
.LINK
Convert-ModuleHelpToHtml
.EXAMPLE
Convert-HelpToHtml -Name 'Get-Module'
Demonstrates how to use `Convert-HelpToHtml` to generate help for a command. You can pass multiple command names to the `Name` parameter.
.EXAMPLE
Get-Command -Module 'Silk' | Convert-HelpToHtml -ModuleName 'Silk'
Demonstrates how you can pipe commands to `Convert-HelpToHtml` to generate help for them.
.EXAMPLE
Convert-HelpToHtml -Name 'Set-TargetResource' -DisplayName 'My_Dsc_Resource' -Syntax (Get-DscResource -Name 'My_Dsc_Resource' -Syntax)
Demonstrates how you can document DSC resources. In this case, the resource's `Set-TargetResource` function contains the help to convert. Because the syntax for using a DSC resource is different than a PowerShell function/cmdlet, we pass the resource's syntax with the `Syntax` parameter.
#>
param(
[Parameter(Mandatory=$true,ValueFromPipeline=$true)]
[string[]]
# The name of the command(s) to document.
$Name,
[string]
# The display name. When supplied, it is used as the command's name instead of `Name`. Useful if the command name being documented is different than its public name, e.g. DSC resources.
$DisplayName,
[string[]]
# The syntax of the command. Useful when showing syntax for DSC resources.
#
# You can get the syntax for a DSC resource with the `Get-DscResource` cmdlet:
#
# Get-DscResource -Name 'My_Dsc_Resource' -Syntax
$Syntax,
[string]
# The name of the module whose help is getting converted. Supplying this value will cause any of the module's cmdlets/functions surrounded by backticks (e.g. `Convert-HelpToHtml`) in help text to get replaced with an HTML link to that command's help topic.
$ModuleName,
[string[]]
# The names of any scripts in the module. Supplying these values will cause any script names surround in backticks (e.g. `script.ps1`) in help text to get replaced with an HTML link to that script's help topic.
$Script
)
begin
{
Set-StrictMode -Version 'Latest'
}
process
{
foreach( $commandName in $Name )
{
$html = New-Object 'Text.StringBuilder'
$fullCommandName = $commandName
if( (Get-Help -Name $commandName | Measure-Object).Count -gt 1 )
{
$fullCommandName = '{0}\{1}' -f $ModuleName,$commandName
}
Write-Verbose -Message $fullCommandName
$help = Get-Help -Name $fullCommandName -Full
if( -not $DisplayName )
{
$DisplayName = $commandName
if( [IO.Path]::IsPathRooted($DisplayName) )
{
$DisplayName = Split-Path -Leaf -Path $DisplayName
}
}
[void]$html.AppendFormat( '<h1>{0}</h1>{1}', $DisplayName, [Environment]::NewLine )
$synopsis = $help.Synopsis | Convert-MarkdownToHtml
if( $synopsis )
{
[void]$html.AppendFormat( '<div class="Synopsis">{0}{1}{0}</div>{0}', [Environment]::NewLine, $synopsis )
}
if( -not $Syntax )
{
$help.Syntax |
ForEach-Object { $_.syntaxItem } |
Where-Object { [IO.Path]::IsPathRooted($_.name) } |
ForEach-Object { $_.Name = Split-Path -Leaf -Path $_.name }
$Syntax = $help.Syntax | Out-HtmlString | Format-ForHtml | ForEach-Object { $_ -split "`n" }
}
if( $Syntax )
{
[void]$html.AppendLine( @"
<h2>Syntax</h2>
<pre class="Syntax"><code>{0}</code></pre>
"@ -f ($Syntax -join "</code></pre>$([Environment]::NewLine)<pre class=""Syntax""><code>") )
}
$description = $null
if( $help | Get-Member -Name 'Description' )
{
$description = $help.Description | Out-HtmlString | Convert-MarkdownToHtml
}
if( $description )
{
[void]$html.AppendLine( @"
<h2>Description</h2>
<div class="Description">
$description
</div>
"@ )
}
[string[]]$relatedCommands = $help | Convert-RelatedLinkToHtml -ModuleName $ModuleName -Script $Script
if( $relatedCommands )
{
$relatedCommands = $relatedCommands | ForEach-Object { "<li>{0}</li>" -f $_ }
[void]$html.AppendLine( @"
<h2>Related Commands</h2>
<ul class="RelatedCommands">
{0}
</ul>
"@ -f ($relatedCommands -join ([Environment]::NewLine)) )
}
$commonParameterNames = @{
'Verbose' = $true;
'Debug' = $true;
'WarningAction' = $true;
'WarningVariable' = $true;
'ErrorAction' = $true;
'ErrorVariable' = $true;
'OutVariable' = $true;
'OutBuffer' = $true;
'WhatIf' = $true;
'Confirm' = $true;
}
$hasCommonParameters = $false
$parameters = $help |
Select-Object -ExpandProperty 'Parameters' |
Where-Object { $_ | Get-Member -Name 'parameter' } |
Select-Object -ExpandProperty 'parameter' |
Where-Object { $_ } |
ForEach-Object {
if( $commonParameterNames.ContainsKey( $_.name ) )
{
$hasCommonParameters = $true
}
$defaultValue = ' '
if( $_ | Get-Member -Name 'DefaultValue' )
{
$defaultValue = $_.DefaultValue
}
$typeLink = Get-TypeDocumentationLink -CommandName $commandName -TypeName $_.type.name
$paramDescription = $_ |
Where-Object { $_ | Get-Member -name 'Description' } |
Select-Object -ExpandProperty 'Description' |
Out-HtmlString |
Convert-MarkdownToHtml
@"
<tr valign='top'>
<td>{0}</td>
<td>{1}</td>
<td class="ParamDescription">{2}</td>
<td>{3}</td>
<td>{4}</td>
<td>{5}</td>
</tr>
"@ -f $_.Name,$typeLink,$paramDescription,$_.Required,$_.PipelineInput,$defaultValue
}
if( $parameters )
{
$commonParameters = ''
if( $hasCommonParameters )
{
$commonParameters = @"
<tr valign="top">
<td><a href="http://technet.microsoft.com/en-us/library/dd315352.aspx">CommonParameters</a></td>
<td></td>
<td>This cmdlet supports common parameters. For more information type <br> <code>Get-Help about_CommonParameters</code>.</td>
<td></td>
<td></td>
<td></td>
</tr>
"@
}
[void]$html.AppendLine( (@"
<h2> Parameters </h2>
<table id="Parameters">
<tr>
<th>Name</th>
<th>Type</th>
<th>Description</th>
<th>Required?</th>
<th>Pipeline Input</th>
<th>Default Value</th>
</tr>
{0}
{1}
</table>
"@ -f ($parameters -join [Environment]::NewLine),$commonParameters))
}
$inputTypes = @()
if( ($help | Get-Member -Name 'inputTypes') -and ($help.inputTypes | Get-Member 'inputType') )
{
$inputTypes = $help.inputTypes.inputType |
Where-Object { ($_ | Get-Member -Name 'type') -and $_.type -and $_.type.name -match '^([^\s]+)\s*(.*)?$' } |
ForEach-Object {
$typeLink = Get-TypeDocumentationLink -CommandName $commandName -TypeName $Matches[1].Trim('.')
'{0}. {1}' -f $typeLink,$matches[2]
} |
Convert-MarkdownToHtml
}
if( $inputTypes )
{
[void]$html.AppendLine( @"
<h2>Input Types</h2>
<div class="InputTypes">
{0}
</div>
"@ -f ($inputTypes -join [Environment]::NewLine))
}
$returnValues =@()
if( ($help | Get-Member -Name 'returnValues') -and ($help.returnValues | Get-Member -Name 'returnValue') )
{
$returnValues = $help.returnValues.returnValue |
Where-Object { ($_ | Get-Member -Name 'type') -and $_.type -and $_.type.name -match '^([^\s]+)\s*(.*)?$' } |
ForEach-Object {
$typeLink = Get-TypeDocumentationLink -CommandName $commandName -TypeName $Matches[1].Trim('.')
'{0}. {1}' -f $typeLink,$matches[2]
} |
Convert-MarkdownToHtml
}
if( $returnValues )
{
[void]$html.AppendLine( @"
<h2>Return Values</h2>
<div class="ReturnValues">
{0}
</div>
"@ -f ($returnValues -join [Environment]::NewLine))
}
$notes = ''
if( $help | Get-Member -Name 'AlertSet' )
{
$notes = $help.AlertSet | Out-HtmlString | ForEach-Object { $_ -replace "\r?\n ",[Environment]::NewLine } | Convert-MarkdownToHtml
}
if( $notes )
{
[void]$html.AppendLine( @"
<h2>Notes</h2>
<div class="Notes">
{0}
</div>
"@ -f $notes)
}
$examples = @()
if( $help | Get-Member -Name 'Examples' )
{
$examples = $help.Examples |
Where-Object { $_ } |
Where-Object { $_ | Get-Member -Name 'example' } |
Select-Object -ExpandProperty 'example' |
ForEach-Object {
$title = $_.title.Trim(('-',' '))
$code = ''
if( $_.code )
{
$code = $_.code | Out-HtmlString
$code = '<pre><code>{0}</code></pre>' -f $code
}
$remarks = $_.remarks | Out-HtmlString | Convert-MarkdownToHtml
@"
<h2>{0}</h2>
{1}
{2}
"@ -f $title,$code,($remarks -join [Environment]::NewLine)
}
}
if( $examples )
{
[void]$html.AppendLine( ($examples -join ([Environment]::NewLine * 2)) )
}
$html.ToString()
}
}
end
{
}
}
filter Convert-MarkdownToHtml
{
if( $_ )
{
$markdown.Transform( $_ ).Trim()
}
}
function Convert-ModuleHelpToHtml
{
<#
.SYNOPSIS
Converts a module's help into HTML.
.DESCRIPTION
The `Convert-ModuleHelpToHtml` function converts a module's help into HTML. It returns an object for each command and about help topic in the module. The object
#>
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)]
[string]
# The name of the module whose help to convert.
$ModuleName,
[string[]]
# Any scripts included in the module whose help should get generated. Scripts are assumed to be in the root of the module.
$Script,
[hashtable]
# A hashtable of headings to use. They key should be the section name. The value should be the heading name. Only used when converting about help topics to HTML.
$HeadingMap,
[Switch]
# Don't generate help for individual commands.
$SkipCommandHelp
)
Set-StrictMode -Version 'Latest'
$commands = Get-Command -Module $ModuleName -CommandType Cmdlet,Function,Filter
$moduleBase = Get-Module -Name $ModuleName |
Select-Object -ExpandProperty 'ModuleBase'
$aboutTopics = @()
if( (Test-Path -Path (Join-Path -Path $moduleBase -ChildPath 'en-US') -PathType Container) )
{
$aboutTopics = Get-ChildItem -Path $moduleBase -Filter 'en-US\about_*.help.txt'
}
$dscResources = Join-Path -Path $moduleBase -ChildPath 'DscResources' |
Where-Object { Test-Path -Path $_ -PathType Container } |
Get-ChildItem -Directory
$scripts = @()
if( $Script )
{
$scripts = $Script |
ForEach-Object { Join-Path -Path $moduleBase -ChildPath $_ } |
Get-Item
}
[int]$numCommands = $commands | Measure-Object | Select-Object -ExpandProperty 'Count'
[int]$numScripts = $scripts | Measure-Object | Select-Object -ExpandProperty 'Count'
[int]$numAboutTopics = $aboutTopics | Measure-Object | Select-Object -ExpandProperty 'Count'
[int]$numDscResources = $dscResources | Measure-Object | Select-Object -ExpandProperty 'Count'
[int]$numPages = $numAboutTopics + $numDscResources + $numScripts
if( -not $SkipCommandHelp )
{
$numPages += $numCommands
}
$activity = 'Generating {0} Module HTML' -f $ModuleName
$count = 0
foreach( $command in $commands )
{
if( -not $SkipCommandHelp )
{
Write-Progress -Activity $activity -PercentComplete ($count++ / $numPages * 100) -CurrentOperation $command.Name -Status 'Commands'
$html = Convert-HelpToHtml -Name $command.Name -Script $Script -ModuleName $ModuleName
[pscustomobject]@{
Name = $command.Name;
Type = 'Command';
Html = $html;
}
}
}
foreach( $scriptItem in $scripts )
{
Write-Progress -Activity $activity -PercentComplete ($count++ / $numPages * 100) -CurrentOperation $command.Name -Status 'Scripts'
$html = Convert-HelpToHtml -Name $scriptItem.FullName -ModuleName $ModuleName -Script $Script
[pscustomobject]@{
Name = $scriptItem.Name;
Type = 'Script'
Html = $html;
}
}
foreach( $aboutTopic in $aboutTopics )
{
$topicName = $aboutTopic.BaseName -replace '\.help',''
Write-Progress -Activity $activity -PercentComplete ($count++ / $numPages * 100) -CurrentOperation $topicName -Status 'About Topics'
$html = $aboutTopic | Convert-AboutTopicToHtml -ModuleName $ModuleName -Script $Script
[pscustomobject]@{
Name = $topicName;
Type = 'AboutTopic';
Html = $html
}
}
foreach( $dscResource in $dscResources )
{
$dscResourceName = $dscResource.BaseName
Write-Progress -Activity $activity -PercentComplete ($count++ / $numPages * 100) -CurrentOperation $dscResourceName -Status 'DSC Resources'
Import-Module -Name $dscResource.FullName
$html = Convert-HelpToHtml -Name 'Set-TargetResource' -DisplayName $dscResourceName -Syntax (Get-DscResource -Name $dscResourceName -Syntax) -ModuleName $ModuleName -Script $Script
[pscustomobject]@{
Name = $dscResourceName;
Type = 'DscResource';
Html = $html;
}
}
}
# 0.2.0 (21 November 2016)
* Improved `about_Silk` help topic.
* Added example scripts `Invoke-Build.ps1`, `Publish-Module.ps1`, and `New-Website.ps1` to show how to use Silk.
<#
.SYNOPSIS
Imports the Silk module.
.DESCRIPTION
Imports the Silk module. If the Silk module is already loaded, it will remove it and then reloaded.
.EXAMPLE
Import-Silk.ps1
Imports the Silk module, re-loading it if its already loaded.
#>
# Copyright 2012 Aaron Jensen
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
[CmdletBinding()]
param(
)
Set-StrictMode -Version Latest
$PSScriptRoot = Split-Path -Parent -Path $MyInvocation.MyCommand.Definition
if( (Get-Module Silk) )
{
Remove-Module Silk -WhatIf:$false
}
Import-Module (Join-Path $PSScriptRoot Silk.psd1 -Resolve) -ErrorAction Stop
<#
.SYNOPSIS
Chocolately install script for Silk.
#>
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.[CmdletBinding()]
param(
)
#Requires -Version 4
Set-StrictMode -Version 'Latest'
$ErrorActionPreference = 'Stop'
$errorCount = $Global:Error.Count
try
{
$env:PSModulePath -split ';' |
Where-Object { $_ } |
Join-Path -ChildPath 'Silk' |
Where-Object { Test-Path -Path $_ -PathType Container } |
Rename-Item -NewName { 'Silk{0}' -f [IO.Path]::GetRandomFileName() } -PassThru |
Remove-Item -Recurse -Force
}
finally
{
for( $idx = $errorCount; $idx -lt $Global:Error.Count; ++$idx )
{
$Global:Error[$idx]
$Global:Error[$idx] | Format-List -Property '*' -Force | Out-String | Write-Verbose
}
}
function Set-ReleaseNotesReleaseDate
{
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)]
[string]
# The path to the module manifest whose release notes to update.
$ManifestPath,
[Parameter(Mandatory=$true)]
[string]
# The path to the release notes file.
$ReleaseNotesPath
)
Set-StrictMode -Version 'Latest'
$manifest = Test-ModuleManifest -Path $ManifestPath
if( -not $manifest )
{
return
}
$setHeader = $false
$releaseNotes = Get-Content -Path $ReleaseNotesPath |
ForEach-Object {
if( $_ -match '^# {0}\s*$' -f [regex]::Escape($manifest.Version.ToString()) )
{
$setHeader = $true
return "# {0} ({1})" -f $manifest.Version,((Get-Date).ToString("d MMMM yyyy"))
}
return $_
}
if( $setHeader )
{
$releaseNotes | Set-Content -Path $releaseNotesPath
}
}
function Set-ModuleVersion
{
<#
.SYNOPSIS
Updates a module's version.
#>
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)]
[string]
# The path to the module's manifest.
$ManifestPath,
[string]
# The path to the module's manifest.
$SolutionPath,
[string]
# Path to an C# file to update with the assembly version.
$AssemblyInfoPath,
[string]
# Path to a release notes file.
$ReleaseNotesPath,
[string]
# Path to the module's Nuspec file.
$NuspecPath,
[Version]
# The version to build. If not provided, pulled from the module's manifest.
$Version,
[string]
# The pre-release version, e.g. alpha.39, rc.1, etc.
$PreReleaseVersion,
[string]
# Build metadata.
$BuildMetadata
)
Set-StrictMode -Version 'Latest'
if( -not $Version )
{
$Version = Test-ModuleManifest -Path $ManifestPath | Select-Object -ExpandProperty 'Version'
if( -not $Version )
{
return
}
}
if( $Version.Build -lt 0 )
{
Write-Error ('Version number must have a build number, i.e. it must have three parts.' -f $Version)
return
}
if( $Version.Revision -ge 0 )
{
Write-Error ('Version number must not have a revision number, i.e. it must only have three parts.' -f $Version)
return
}
$manifest = Test-ModuleManifest -Path $ManifestPath
if( -not $manifest )
{
return
}
$moduleVersionRegex = 'ModuleVersion\s*=\s*(''|")([^''"])+(''|")'
$rawManifest = Get-Content -Raw -Path $manifestPath
if( $rawManifest -notmatch ('ModuleVersion\s*=\s*(''|"){0}(''|")' -f [regex]::Escape($version.ToString())) )
{
$rawManifest = $rawManifest -replace $moduleVersionRegex,('ModuleVersion = ''{0}''' -f $version)
$rawManifest | Set-Content -Path $manifestPath -NoNewline
}
if( $AssemblyInfoPath )
{
$assemblyVersionRegex = 'Assembly(File|Informational)?Version\("[^"]*"\)'
$assemblyVersion = Get-Content -Path $AssemblyInfoPath |
ForEach-Object {
if( $_ -match $assemblyVersionRegex )
{
$infoVersion = ''
if( $Matches[1] -eq 'Informational' )
{
if( $PreReleaseVersion )
{
$infoVersion = '-{0}' -f $PreReleaseVersion
}
if( $BuildMetadata )
{
$infoVersion = '{0}+{1}' -f $infoVersion,$BuildMetadata
}
}
return $_ -replace $assemblyVersionRegex,('Assembly$1Version("{0}{1}")' -f $Version,$infoVersion)
}
elseif( $_ -match 'AssemblyCopyright' )
{
return $_ -replace '\("[^"]*"\)',('("{0}")' -f $manifest.Copyright)
}
$_
}
$assemblyVersion | Set-Content -Path $AssemblyInfoPath
}
if( $ReleaseNotesPath )
{
$newVersionHeader = "# {0}" -f $Version
$updatedVersion = $false
$releaseNotes = Get-Content -Path $releaseNotesPath |
ForEach-Object {
if( -not $updatedVersion -and $_ -match '^#\s+' )
{
$updatedVersion = $true
return $newVersionHeader
}
return $_
}
$releaseNotes | Set-Content -Path $releaseNotesPath
}
if( $SolutionPath )
{
$msbuildRoot = Get-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\MSBuild\ToolsVersions\12.0 -Name 'MSBuildToolsPath' | Select-Object -ExpandProperty 'MSBuildToolsPath'
$msbuildExe = Join-Path -Path $msbuildRoot -ChildPath 'MSBuild.exe' -Resolve
if( -not $msbuildExe )
{
return
}
& $msbuildExe /target:"clean;build" $SolutionPath /v:m /nologo
}
if( $NuspecPath )
{
$nuspec = [xml](Get-Content -Raw -Path $nuspecPath)
if( $nuspec.package.metadata.version -ne $version.ToString() )
{
$nuGetVersion = $version -replace '-([A-Z0-9]+)[^A-Z0-9]*(\d+)$','-$1$2'
$nuspec.package.metadata.version = $nugetVersion
$nuspec.Save( $nuspecPath )
}
}
}
function Set-ModuleNuspec
{
param(
[Parameter(Mandatory=$true)]
[string]
# Path to the module's manifest.
$ManifestPath,
[Parameter(Mandatory=$true)]
[string]
# Path to the module's Nuspec file.
$NuspecPath,
[Parameter(Mandatory=$true)]
[string]
# Path to the releaes notes file.
$ReleaseNotesPath,
[string]
# The ID of the package. If not provided, the existing ID in the .nuspec file is left in place.
$PackageID,
[string]
# The title of the package. If not provided, the existing title in the .nuspec file is left in place.
$PackageTitle,
[string[]]
# Tags to add to the manifest. Tags are space-delimited, so tags shouldn't have spaces.
$Tags
)
Set-StrictMode -Version 'Latest'
$NuspecPath = Resolve-Path -Path $NuspecPath
if( -not $NuspecPath )
{
return
}
$nuspec = [xml](Get-Content -Path $NuspecPath -Raw)
if( -not $nuspec )
{
return
}
$manifest = Test-ModuleManifest -Path $ManifestPath
if( -not $manifest )
{
return
}
$releaseNotes = Get-ModuleReleaseNotes -ManifestPath $ManifestPath -ReleaseNotesPath $ReleaseNotesPath
if( -not $releaseNotes )
{
return
}
$nuspecMetadata = $nuspec.package.metadata
if( $PackageID )
{
$nuspecMetadata.id = $PackageID
}
if( $PackageTitle )
{
$nuspecMetadata.title = $PackageTitle
}
$nuspecMetadata.description = $manifest.Description
$nuspecMetadata.version = $manifest.Version.ToString()
$nuspecMetadata.copyright = $manifest.Copyright
$nuspecMetadata.releaseNotes = $releaseNotes
if( $Tags )
{
$nuspecMetadata.tags = $Tags -join ' '
}
$nuspec.Save( $NuspecPath )
}
#>
# Copyright 2012 Aaron Jensen
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
function Publish-PowerShellGalleryModule
{
<#
.SYNOPSIS
Publishes a module to the PowerShell gallery.
.DESCRIPTION
The `Publish-PowerShellGalleryModule` functin publishes a module to the PowerShell Gallery. If the given version of the module already exists in the Gallery, a warning is written and no other work is done.
If you don't supply a PowerShell Gallery API key via the `ApiKey` parameter, you'll be prompted for it.
Returns a `PSGetItemInfo` object if the module gets published (the object returned by the `Find-Module` cmdlet). If the version of the module already exists in the Gallery, you'll get a warning that the module has already been published.
This function requires the `PowerShellGet` module. If it isn't available, you'll get an error.
.OUTPUTS
PSGetItemInfo
.EXAMPLE
Publish-PowerShellGalleryModule -Name 'Carbon' -Version '2.0.0' -LicenseUri ''http://www.apache.org/licenses/LICENSE-2.0'
#>
[CmdletBinding(SupportsShouldProcess=$true)]
param(
[Parameter(Mandatory=$true)]
[string]
# Path to the module's manifest.
$ManifestPath,
[Parameter(Mandatory=$true)]
[string]
# The path to the module.
$ModulePath,
[Parameter(Mandatory=$true)]
[string]
# The release notes.
$ReleaseNotesPath,
[string]
# The name of the module being published. Defaults to the name in the module manifest.
$Name,
[string]
# The API key for the PowerShell Gallery.
$ApiKey,
[Parameter(Mandatory=$true)]
[string]
# The URL to the module's license.
$LicenseUri,
[string[]]
# Any tags for the module.
$Tags,
[string]
# The URL to the project's home page.
$ProjectUri
)
Set-StrictMode -Version 'Latest'
Use-CallerPreference -Cmdlet $PSCmdlet -Session $ExecutionContext.SessionState
$manifest = Test-ModuleManifest -Path $ManifestPath
if( -not $manifest )
{
return
}
if( -not $Name )
{
$Name = $manifest.Name
}
if( Get-Module -ListAvailable -Name 'PowerShellGet' )
{
if( -not (Find-Module -Name $Name -RequiredVersion $manifest.Version -Repository 'PSGallery' -ErrorAction Ignore) )
{
$releaseNotes = Get-ModuleReleaseNotes -ManifestPath $ManifestPath -ReleaseNotesPath $ReleaseNotesPath
Write-Verbose -Message ('Publishing to PowerShell Gallery.')
if( $PSCmdlet.ShouldProcess('publish module to PowerShell Gallery','','') )
{
if( -not $ApiKey )
{
$ApiKey = Read-Host -Prompt ('Please enter PowerShell Gallery API key')
}
Publish-Module -Path $ModulePath `
-Repository 'PSGallery' `
-NuGetApiKey $ApiKey `
-LicenseUri $LicenseUri `
-ReleaseNotes $releaseNotes `
-Tags $Tags `
-ProjectUri $ProjectUri
Find-Module -Name $Name -RequiredVersion $manifest.Version -Repository 'PSGallery'
}
}
else
{
Write-Warning -Message ('{0} {1} already exists in the PowerShell Gallery.' -f $Name,$manifest.Version)
}
}
else
{
Write-Error -Message ('Unable to publish to PowerShell Gallery: PowerShellGet module not found.')
}
}
# Copyright 2012 Aaron Jensen
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
function Publish-NuGetPackage
{
<#
.SYNOPSIS
Creates and publishes a NuGet package to nuget.org.
#>
[CmdletBinding(SupportsShouldProcess=$true)]
param(
[Parameter(Mandatory=$true)]
[string]
# The path to the module manifest of the module you want to publish.
$NupkgPath,
[object]
# The API key(s) to use. To supply multiple API keys, use a hashtable where each key is a repository server name and the value is the API key for that repository. For example,
#
# @{ 'nuget.org' = '395edfa5-652f-4598-868e-c0a73be02c84' }
#
# If not specified, you'll be prompted for it.
$ApiKey
)
Set-StrictMode -Version 'Latest'
Use-CallerPreference -Cmdlet $PSCmdlet -Session $ExecutionContext.SessionState
$nugetPath = Join-Path -Path $PSScriptRoot -ChildPath '..\bin\NuGet.exe' -Resolve
if( -not $nugetPath )
{
return
}
if( -not (Test-Path -Path $NupkgPath -PathType Leaf) )
{
Write-Error -Message ('NuGet package ''{0}'' does not exist.' -f $NupkgPath)
return
}
$nupkgName = [IO.Path]::GetFileNameWithoutExtension($NupkgPath)
if( $nupkgName -notmatch '^(.+)\.(\d+\.\d+\.\d)+$' )
{
Write-Error -Message ('NuGet package ''{0}'' does not have the version to publish in its name.' -f $nupkgName)
return
}
$packageName = $Matches[1]
$version = $Matches[2]
try
{
$packageUrl = 'https://nuget.org/api/v2/package/{0}/{1}' -f $packageName,$version
try
{
$resp = Invoke-WebRequest -Uri $packageUrl -ErrorAction Ignore
$publish = ($resp.StatusCode -ne 200)
}
catch
{
$publish = $true
}
if( -not $publish )
{
Write-Warning ('NuGet package {0} {1} already published to nuget.org.' -f $packageName,$version)
return
}
if( $PSCmdlet.ShouldProcess(('publish package to nuget.org'),'','') )
{
if( -not $ApiKey )
{
$ApiKey = Read-Host -Prompt ('Please enter your nuget.org API key')
if( -not $ApiKey )
{
Write-Error -Message ('The nuget.org API key is required. Package not published to nuget.org.')
continue
}
}
$verbosity = 'normal'
if( $VerbosePreference -eq 'Continue' )
{
$verbosity = 'detailed'
}
& $nugetPath push $nupkgPath -ApiKey $ApiKey -Source 'https://nuget.org/api/v2/package' -Verbosity $verbosity
$resp = Invoke-WebRequest -Uri $packageUrl
$resp | Select-Object -Property 'StatusCode','StatusDescription',@{ Name = 'Uri'; Expression = { $packageUrl }}
}
}
finally
{
Pop-Location
}
}
# Copyright 2012 Aaron Jensen
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
function Publish-BitbucketDownload
{
<#
.SYNOPSIS
Creates and publishes a ZIP file to Bitbucket so it is available on a project's download page.
.DESCRIPTION
The `Publish-BitbucketDownload` function creates a ZIP file and publishes it to a repository so it is availabe on a project's download page. If the file already exists on Bitbucket, nothing is uploaded.
.LINK
https://bitbucket.org/Swyter/bitbucket-curl-upload-to-repo-downloads
#>
[CmdletBinding()]
param(
[pscredential]
# The Bitbucket credentials to use.
$Credential,
[Parameter(Mandatory=$true)]
[string]
# The account of the project you're uploading a file to.
$Username,
[Parameter(Mandatory=$true)]
[string]
# The name of the project you're uploading a file to.
$ProjectName,
[Parameter(Mandatory=$true)]
[string[]]
# The paths to the files and directories to include in the ZIP file. All files and sub-directories under directory are added.
$Path,
[Parameter(Mandatory=$true)]
[string]
# The path to the manifest of the module being published.
$ManifestPath
)
Set-StrictMode -Version 'Latest'
function Assert-Response
{
param(
[Microsoft.PowerShell.Commands.HtmlWebResponseObject]
$Response,
[Uri]
$ExpectedUri
)
if( -not $Response )
{
Write-Error ('No response.')
return $false
}
if( $Response.BaseResponse.StatusCode -ne [Net.HttpStatusCode]::OK )
{
Write-Error ('Response failed.')
return $false
}
if( $Response.BaseResponse.ResponseUri -ne $ExpectedUri )
{
Write-Error ('Response didn''t finish on URI {0} ({1}).' -f $ExpectedUri,$Response.BaseResponse.ResponseUri)
return $false
}
$errorElement = $Response.ParsedHtml.getElementById('error')
if( $errorElement -and ($errorElement | Get-Member 'innerHtml') -and $erroElement.innerHtml )
{
Write-Error $errorElement.innerHtml
return $false
}
return $true
}
$manifest = Test-ModuleManifest -Path $ManifestPath
if( -not $manifest )
{
return
}
$baseProjectUri = 'https://bitbucket.org/{0}/{1}' -f $Username,$ProjectName
$zipFileName = "{0}-{1}.zip" -f $manifest.Name,$manifest.Version
$zipDownloadUrl = '{0}/downloads/{1}' -f $baseProjectUri,$zipFileName
try
{
$resp = Invoke-WebRequest -Uri $zipDownloadUrl -ErrorAction Ignore
$publish = ($resp.StatusCode -ne 200)
}
catch
{
$publish = $true
}
if( -not $publish )
{
Write-Warning -Message ('{0} file already published.' -f $zipFileName)
return
}
$zipFilePath = Join-Path -Path $env:TEMP -ChildPath $zipFileName
$outFile = '{0}+{1}' -f $manifest.Name,[IO.Path]::GetRandomFileName()
$outFile = Join-Path -Path $env:TEMP -ChildPath $outFile
try
{
if( Test-Path $zipFilePath -PathType Leaf )
{
Remove-Item $zipFilePath
}
Write-Verbose -Message ('Creating {0} ZIP file.' -f $zipFileName)
Compress-Item -Path $Path -OutFile $zipFilePath
$PSDefaultParameterValues.Clear()
$PSDefaultParameterValues['Invoke-WebRequest:PassThru'] = $true
$PSDefaultParameterValues['Invoke-WebRequest:OutFile'] = $outFile
if( -not $Credential )
{
$Credential = Get-Credential -Message ('Enter credentials for {0}' -f $baseProjectUri)
}
$session = $null
$loginUri = 'https://bitbucket.org/account/signin/'
$resp = Invoke-WebRequest -Uri $loginUri -SessionVariable 'session' -Method Get
if( -not (Assert-Response -Response $resp -ExpectedUri $loginUri) )
{
return
}
$PSDefaultParameterValues['Invoke-WebRequest:WebSession'] = $session
$form = $resp.Forms |
Where-Object { $_.Action -eq '/account/signin/' }
$formFields = $form.Fields
$formFields.id_username = $Credential.UserName
$formFields.id_password = $Credential.GetNetworkCredential().Password
$loginUri = 'https://bitbucket.org{0}' -f $form.Action
$body = @{
'username' = $Credential.UserName;
'password' = $Credential.GetNetworkCredential().Password;
'csrfmiddlewaretoken' = $formFields.csrfmiddlewaretoken;
'submit' = '';
'next' = '';
}
$resp = Invoke-WebRequest -Uri $loginUri -Method $form.Method -Body $body -Headers @{ Referer = $loginUri }
if( -not (Assert-Response -Response $resp -ExpectedUri 'https://bitbucket.org/') )
{
exit 1
}
$downloadUri = '{0}/downloads' -f $baseProjectUri
$resp = Invoke-WebRequest -Uri $downloadUri -Method Get
if( -not (Assert-Response -Response $resp -ExpectedUri $downloadUri) )
{
exit 1
}
$csrfToken = $resp.Forms |
Where-Object { $_.Fields.ContainsKey( 'csrfmiddlewaretoken' ) } |
ForEach-Object { $_.Fields.csrfmiddlewaretoken }
Write-Debug $csrfToken
$boundary = [Guid]::NewGuid().ToString()
$bodyStart = @"
--$boundary
Content-Disposition: form-data; name="csrfmiddlewaretoken"
$csrfToken
--$boundary
Content-Disposition: form-data; name="token"
--$boundary
Content-Disposition: form-data; name="files"; filename="$(Split-Path -Leaf -Path $zipFilePath)"
Content-Type: application/octet-stream
"@
$bodyEnd = @"
--$boundary--
"@
$requestInFile = Join-Path -Path $env:TEMP -ChildPath ([IO.Path]::GetRandomFileName())
try
{
$fileStream = New-Object 'System.IO.FileStream' ($requestInFile, [System.IO.FileMode]'Create', [System.IO.FileAccess]'Write')
try
{
$bytes = [Text.Encoding]::UTF8.GetBytes($bodyStart)
$fileStream.Write( $bytes, 0, $bytes.Length )
$bytes = [IO.File]::ReadAllBytes($zipFilePath)
$fileStream.Write( $bytes, 0, $bytes.Length )
$bytes = [Text.Encoding]::UTF8.GetBytes($bodyEnd)
$fileStream.Write( $bytes, 0, $bytes.Length )
}
finally
{
$fileStream.Close()
}
$contentType = 'multipart/form-data; boundary={0}' -f $boundary
$resp = Invoke-WebRequest -Uri $downloadUri `
-Method Post `
-InFile $requestInFile `
-ContentType $contentType `
-Headers @{ Referer = $downloadUri }
if( -not (Assert-Response -Response $resp -ExpectedUri $downloadUri) )
{
return
}
}
finally
{
Remove-Item -Path $requestInFile
}
$numTries = 10
$tryNum = 0
while( $tryNum++ -lt $numTries )
{
try
{
$resp = Invoke-WebRequest -Uri $zipDownloadUrl
$resp | Select-Object -Property 'StatusCode','StatusDescription',@{ Name = 'Uri'; Expression = { $zipDownloadUrl }}
break
}
catch
{
Start-Sleep -Seconds 1
}
}
}
finally
{
if( (Test-Path -Path $outFile -PathType Leaf) )
{
Remove-Item -Path $outFile
}
if( (Test-Path -Path $zipFilePath -PathType Leaf) )
{
Remove-Item -Path $zipFilePath
}
}
}
filter Out-HtmlString
{
<#
.SYNOPSIS
Writes a string out to the pipeline, trimming whitespace.
#>
$_ |
Out-String -Width 9999 |
ForEach-Object { $_.Trim() } |
Where-Object { $_ }
}
# Copyright 2012 Aaron Jensen
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
function New-NuGetPackage
{
<#
.SYNOPSIS
Creates a NuGet package.
#>
[CmdletBinding(SupportsShouldProcess=$true)]
param(
[Parameter(Mandatory=$true)]
[string]
# The path to the module manifest of the module you want to publish.
$ManifestPath,
[Parameter(Mandatory=$true)]
[string]
# The path to the nuspec file for the NuGet package to publish.
$NuspecPath,
[Parameter(Mandatory=$true)]
[string]
# The base directory for the files defined in the `NuspecPath` file.
$NuspecBasePath,
[string]
# The name of the NuGet package, if it is different than the module name.
$PackageName,
[Parameter(Mandatory=$true)]
[string]
# The directory where the .nupkg file should be saved.
$OutputDirectory
)
Set-StrictMode -Version 'Latest'
Use-CallerPreference -Cmdlet $PSCmdlet -Session $ExecutionContext.SessionState
$nugetPath = Join-Path -Path $PSScriptRoot -ChildPath '..\bin\NuGet.exe' -Resolve
if( -not $nugetPath )
{
return
}
if( -not (Test-Path -Path $OutputDirectory -PathType Container) )
{
New-Item -Path $OutputDirectory -ItemType 'directory' -Force
}
$manifest = Test-ModuleManifest -Path $ManifestPath
if( -not $manifest )
{
return
}
if( -not $PackageName )
{
$PackageName = $manifest.Name
}
Push-Location -Path $NuSpecBasePath
try
{
$nupkgPath = Join-Path -Path $OutputDirectory -ChildPath ('{0}.{1}.nupkg' -f $PackageName,$manifest.Version)
if( (Test-Path -Path $nupkgPath -PathType Leaf) )
{
Remove-Item -Path $nupkgPath
}
$verbosity = 'normal'
if( $VerbosePreference -eq 'Continue' )
{
$verbosity = 'detailed'
}
& $nugetPath pack $NuspecPath -BasePath '.' -NoPackageAnalysis -Verbosity $verbosity -OutputDirectory $OutputDirectory
if( -not (Test-Path -Path $nupkgPath -PathType Leaf) )
{
Write-Error ('NuGet package ''{0}'' not found.' -f $nupkgPath)
return
}
}
finally
{
Pop-Location
}
}
function New-ModuleHelpIndex
{
<#
.SYNOPSIS
Creates an index page for a module's help.
#>
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)]
[string]
# The name of the module whose index page to create.
$ModuleName,
[string[]]
# The names of any scripts that should be included.
$Script,
[string]
# The path to the tags file. If not provided, no tag tab is generated.
$TagsJsonPath
)
Set-StrictMode -Version 'Latest'
if( $TagsJsonPath )
{
$tagsJson = Get-Content -Path $TagsJsonPath | ConvertFrom-Json
$tags = @{ }
foreach( $item in $tagsJson )
{
foreach( $tagName in $item.Tags )
{
if( -not $tags.ContainsKey( $tagName ) )
{
$tags[$tagName] = New-Object 'Collections.Generic.List[string]'
}
$tags[$tagName].Add( $item.Name )
}
}
$tagCloud = $tags.Keys | Sort-Object | ForEach-Object {
$commands = $tags[$_] | ForEach-Object { '<li><a href="{0}.html">{0}</a></li>' -f $_ }
@'
<h3>{0}</h3>
<ul>
{1}
</ul>
'@ -f $_,($commands -join ([Environment]::NewLine))
}
}
else
{
$tagCloud = ''
}
$verbs = @{ }
$commands = Get-Command -Module $ModuleName -CommandType Cmdlet,Function,Filter
foreach( $command in $commands )
{
if( -not $verbs.ContainsKey( $command.Verb ) )
{
$verbs[$command.Verb] = New-Object 'Collections.Generic.List[string]'
}
$verbs[$command.Verb].Add( $command.Name )
}
$commandList = Invoke-Command {
$commands | Select-Object -ExpandProperty 'Name'
$moduleBase = Get-Module -Name $ModuleName | Select-Object -ExpandProperty 'ModuleBase'
$dscResourceBase = Join-Path -Path $moduleBase -ChildPath 'DscResources'
if( (Test-Path -Path $dscResourceBase -PathType Container) )
{
Get-ChildItem -Directory -Path $dscResourceBase
}
} |
Sort-Object |
ForEach-Object { '<li><a href="{0}.html">{0}</a></li>' -f $_ }
$commandList = @'
<ul>
{0}
</ul>
'@ -f ($commandList -join ([Environment]::NewLine))
$verbList = $verbs.Keys | Sort-Object | ForEach-Object {
$verb = $_
$verbCommands = $verbs[$verb] | ForEach-Object { '<li><a href="{0}.html">{0}</a></li>' -f $_ }
@'
<h3>{0}</h3>
<ul>
{1}
</ul>
'@ -f $verb,($verbCommands -join ([Environment]::NewLine))
}
$scriptContent = ''
if( $Script )
{
$scriptContent = @"
<h2>Scripts</h2>
<ul>
$($Script | ForEach-Object { '<li><a href="{0}.html">{0}</a></li>' -f $_ })
</ul>
"@
}
$topicList = New-Object 'Collections.Generic.List[string]'
$moduleBase = Get-Module -Name $ModuleName | Select-Object -ExpandProperty 'ModuleBase'
$aboutTopics = @()
if( (Test-Path -Path (Join-Path -Path $moduleBase -ChildPath 'en-US') -PathType Container) )
{
$aboutTopics = Get-ChildItem -Path $moduleBase -Filter 'en-US\about_*.help.txt'
}
foreach( $aboutTopic in $aboutTopics )
{
$topicName = $aboutTopic.BaseName -replace '\.help$',''
$virtualPath = '{0}.html' -f $topicName
$topicList.Add( ('<li><a href="{0}">{1}</a></li>' -f $virtualPath,$topicName) )
}
function New-CommandsMenuItem
{
param(
$ID,
$Name
)
Set-StrictMode -Version 'Latest'
if( -not $tagCloud -and $ID -eq 'ByTag' )
{
return
}
$selectedAttr = ''
if( ($tagCloud -and $ID -eq 'ByTag') -or ($ID -eq 'ByName' -and -not $tagCloud) )
{
$selectedAttr = 'class="selected"'
}
'<li id="{0}MenuItem" {1}><a href="#{0}">{2}</a></li>' -f $ID,$selectedAttr,$Name
}
function New-CommandContentDiv
{
param(
$ID,
$Line
)
Set-StrictMode -Version 'Latest'
if( -not $Line )
{
return
}
$styleAttr = 'display:none;'
if( ($ID -eq 'Tag' -and $tagCloud) -or ($ID -eq 'Name' -and -not $tagCloud) )
{
$styleAttr = ''
}
@'
<div id="By{0}Content" style="{2}">
<a id="By{0}"></a>
{1}
</div>
'@ -f $ID,($Line -join ([Environment]::NewLine)),$styleAttr
}
@"
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script>
jQuery( document ).ready(function() {
jQuery("#CommandsMenu > li").click( function() {
var selectedLi = jQuery("#CommandsMenu li.selected")
selectedLi.removeClass("selected");
var selectedCmdID = selectedLi.attr("id").replace("MenuItem","");
jQuery("#" + selectedCmdID + 'Content').hide();
var li = jQuery(this);
li.addClass("selected");
var id = li.attr( 'id' )
id = id.replace('MenuItem','');
jQuery('#' + id + 'Content').show();
return false;
});
});
</script>
<h2>About Help Topics</h2>
<ul>
$($topicList.ToArray() -join ([Environment]::NewLine))
</ul>
$($scriptContent)
<h2>Commands</h1>
<ul id="CommandsMenu">
$( New-CommandsMenuItem 'ByTag' 'By Tag' )
$( New-CommandsMenuItem 'ByName' 'By Name' )
$( New-CommandsMenuItem 'ByVerb' 'By Verb' )
</ul>
<div id="CommandsContent">
$( New-CommandContentDiv 'Tag' $tagCloud )
$( New-CommandContentDiv 'Name' $commandList )
$( New-CommandContentDiv 'Verb' $verbList )
</div>
"@
}
# Copyright 2012 Aaron Jensen
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
function New-ChocolateyPackage
{
<#
.SYNOPSIS
Creates a NuGet package.
#>
[CmdletBinding(SupportsShouldProcess=$true)]
param(
[Parameter(Mandatory=$true)]
[string]
# The path to the module manifest of the module you want to publish.
$ManifestPath,
[Parameter(Mandatory=$true)]
[string]
# The path to the nuspec file for the NuGet package to publish.
$NuspecPath,
[Parameter(Mandatory=$true)]
[string]
# The directory where the .nupkg file should be saved.
$OutputDirectory
)
Set-StrictMode -Version 'Latest'
Use-CallerPreference -Cmdlet $PSCmdlet -Session $ExecutionContext.SessionState
if( -not (Get-Command -Name 'choco.exe' -ErrorAction Ignore) )
{
Write-Error -Message ('choco.exe not found. Please install Chocoatey from chocolatey.org')
return
}
if( -not (Test-Path -Path $OutputDirectory -PathType Container) )
{
New-Item -Path $OutputDirectory -ItemType 'directory' -Force
}
$manifest = Test-ModuleManifest -Path $ManifestPath
if( -not $manifest )
{
return
}
Push-Location -Path $OutputDirectory
try
{
Get-ChildItem -Path '*.nupkg' | Remove-Item
$verbosity = ''
if( $VerbosePreference -eq 'Continue' )
{
$verbosity = '-v'
}
choco.exe pack $NuspecPath --version=$($manifest.Version) $verbosity
if( -not (Test-Path -Path '*.nupkg' -PathType Leaf) )
{
Write-Error -Message 'Chocolatey package not created.'
}
}
finally
{
Pop-Location
}
}
filter Get-Function
{
<#
.SYNOPSIS
Gets all of a module's functions.
#>
param(
[Parameter(Mandatory=$true,ValueFromPipeline=$true)]
# The file to parse for functions
$Path
)
Write-Verbose "Loading script '$Path'."
$scriptContent = Get-Content "$Path"
if( -not $scriptContent )
{
return @()
}
$errors = [Management.Automation.PSParseError[]] @()
$tokens = [System.Management.Automation.PsParser]::Tokenize( $scriptContent, [ref] $errors )
if( $errors -ne $null -and $errors.Count -gt 0 )
{
Write-Error "Found $($errors.count) error(s) parsing '$Path'."
return
}
Write-Verbose "Found $($tokens.Count) tokens in '$Path'."
for( $idx = 0; $idx -lt $tokens.Count; ++$idx )
{
$token = $tokens[$idx]
if( $token.Type -eq 'Keyword'-and ($token.Content -eq 'Function' -or $token.Content -eq 'Filter') )
{
$atFunction = $true
}
if( $atFunction -and $token.Type -eq 'CommandArgument' -and $token.Content -ne '' )
{
Write-Verbose "Found function '$($token.Content).'"
$token.Content
$atFunction = $false
}
}
}
filter Format-ForHtml
{
<#
.SYNOPSIS
Encodes text for HTML.
#>
if( $_ )
{
[Web.HttpUtility]::HtmlEncode($_)
}
}
function Edit-HelpText
{
<#
.SYNOPSIS
Converts the command names in a block of text to links.
.DESCRIPTION
The `Edit-HelpText` function converts all a module's command names or help topic names into Markdown links. The command names or help topic names should be surrounded by backticks, e.g. `Invoke-Function`, `about_Module`.
#>
[CmdletBinding()]
param(
[Parameter(Mandatory=$true,VAlueFromPipeline=$true)]
# The text to convert.
$InputObject,
[string]
# The name of the module whose command names to convert.
$ModuleName
)
begin
{
Set-StrictMode -Version 'Latest'
$commands = Invoke-Command -ScriptBlock {
Get-Command -Module $ModuleName -CommandType Cmdlet
Get-Command -Module $ModuleName -CommandType Function
Get-Command -Module $ModuleName -CommandType Filter
}
$aliases = Get-Command -Module $ModuleName -CommandType Alias | Get-Alias
$aboutTopicNames = Get-ChildItem -Path (Get-Module -Name $ModuleName).ModuleBase -Filter 'en-US\about_*' |
Select-Object -ExpandProperty 'BaseName' |
ForEach-Object { $_ -replace '\.help$','' }
}
process
{
$regex = $commands | Select-Object -ExpandProperty 'Name' | ForEach-Object { [regex]::Escape( $_ ) }
$regex = $regex -join '|'
$regex = '`({0})`' -f $regex
$replacement = '[$1]($1.html)'
$InputObject |
ForEach-Object { $_ -replace $regex,$replacement } |
ForEach-Object {
$text = $_
foreach( $alias in $aliases )
{
$text = $text -replace ('`({0})`' -f $alias.Name),('[$1]({0}.html)' -f $alias.Definition)
}
foreach( $aboutTopicName in $aboutTopicNames )
{
$text = $text -replace ('`({0})`' -f $aboutTopicName),('[{0}]($1.html)' -f ($aboutTopicName -replace '_','\_'))
}
return $text
}
}
end
{
}
}
# Copyright 2012 Aaron Jensen
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Module manifest for module 'Silk'
#
# Generated by: Aaron Jensen
#
# Generated on: 7/4/2013
#
@{
# Script module or binary module file associated with this manifest
RootModule = 'Silk.psm1'
# Version number of this module.
ModuleVersion = '0.2.0'
# ID used to uniquely identify this module
GUID = 'b4d24de5-aa00-4a18-bbde-ac8bb641751f'
# Author of this module
Author = 'Aaron Jensen'
# Company or vendor of this module
CompanyName = ''
# Copyright statement for this module
Copyright = '(c) 2013 Aaron Jensen. All rights reserved.'
# Description of the functionality provided by this module
Description = 'PowerShell module for publishing another module''s help system as a website.'
# Minimum version of the Windows PowerShell engine required by this module
PowerShellVersion = ''
# Name of the Windows PowerShell host required by this module
PowerShellHostName = ''
# Minimum version of the Windows PowerShell host required by this module
PowerShellHostVersion = ''
# Minimum version of the .NET Framework required by this module
DotNetFrameworkVersion = ''
# Minimum version of the common language runtime (CLR) required by this module
CLRVersion = ''
# Processor architecture (None, X86, Amd64, IA64) required by this module
ProcessorArchitecture = ''
# Modules that must be imported into the global environment prior to importing this module
RequiredModules = @()
# Assemblies that must be loaded prior to importing this module
RequiredAssemblies = @()
# Script files (.ps1) that are run in the caller's environment prior to importing this module
ScriptsToProcess = @()
# Type files (.ps1xml) to be loaded when importing this module
TypesToProcess = @()
# Format files (.ps1xml) to be loaded when importing this module
FormatsToProcess = @( )
# Modules to import as nested modules of the module specified in ModuleToProcess
NestedModules = @()
# Functions to export from this module
FunctionsToExport = '*'
# Cmdlets to export from this module
CmdletsToExport = '*'
# Variables to export from this module
VariablesToExport = '*'
# Aliases to export from this module
AliasesToExport = '*'
# List of all modules packaged with this module
ModuleList = @()
# List of all files packaged with this module
FileList = @()
# Private data to pass to the module specified in ModuleToProcess
PrivateData = @{
PSData = @{
# Tags applied to this module. These help with module discovery in online galleries.
Tags = @('powershell','module','help','tools')
# A URL to the license for this module.
LicenseUri = 'http://www.apache.org/licenses/LICENSE-2.0'
# A URL to the main website for this project.
ProjectUri = 'http://get-silk.org'
# A URL to an icon representing this module.
# IconUri = ''
# ReleaseNotes of this module
ReleaseNotes = @'
* Improved `about_Silk` help topic.
* Added example scripts `Invoke-Build.ps1`, `Publish-Module.ps1`, and `New-Website.ps1` to show how to use Silk.
'@
} # End of PSData hashtable
} # End of PrivateData hashtable
}
# Copyright 2013 Aaron Jensen
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
Add-Type -Path (Join-Path $PSSCriptRoot bin\MarkdownSharp.dll)
$markdown = New-Object MarkdownSharp.Markdown
$markdown.AutoHyperlink = $true
$loadedTypes = @{ }
[AppDomain]::CurrentDomain.GetAssemblies() |
ForEach-Object { $_.GetTypes() } |
Where-Object { $_.IsPublic } |
Sort-Object -Property 'Name' |
ForEach-Object {
if( $loadedTypes.ContainsKey( $_.Name ) )
{
Write-Verbose ("Found multiple <{0}> types <{1}> <{2}>." -f $_.Name,$_.FullName,$loadedTypes[$_.Name])
}
else
{
$loadedTypes[$_.Name] = $_.FullName
}
}
$filesToSkip = @{
'Import-Silk' = $true;
}
Get-Item (Join-Path -Path $PSScriptRoot -ChildPath 'Functions\*.ps1') |
ForEach-Object {
Write-Debug ("Importing function {0}." -f $_.FullName)
. $_.FullName
}
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
function Use-CallerPreference
{
<#
.SYNOPSIS
Sets the PowerShell preference variables in a module's function based on the callers preferences.
.DESCRIPTION
Script module functions do not automatically inherit their caller's variables, including preferences set by common parameters. This means if you call a script with switches like `-Verbose` or `-WhatIf`, those that parameter don't get passed into any function that belongs to a module.
When used in a module function, `Use-CallerPreference` will grab the value of these common parameters used by the function's caller:
* ErrorAction
* Debug
* Confirm
* InformationAction
* Verbose
* WarningAction
* WhatIf
This function should be used in a module's function to grab the caller's preference variables so the caller doesn't have to explicitly pass common parameters to the module function.
This function is adapted from the [`Get-CallerPreference` function written by David Wyatt](https://gallery.technet.microsoft.com/scriptcenter/Inherit-Preference-82343b9d).
There is currently a [bug in PowerShell](https://connect.microsoft.com/PowerShell/Feedback/Details/763621) that causes an error when `ErrorAction` is implicitly set to `Ignore`. If you use this function, you'll need to add explicit `-ErrorAction $ErrorActionPreference` to every function/cmdlet call in your function. Please vote up this issue so it can get fixed.
.LINK
about_Preference_Variables
.LINK
about_CommonParameters
.LINK
https://gallery.technet.microsoft.com/scriptcenter/Inherit-Preference-82343b9d
.LINK
http://powershell.org/wp/2014/01/13/getting-your-script-module-functions-to-inherit-preference-variables-from-the-caller/
.EXAMPLE
Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState
Demonstrates how to set the caller's common parameter preference variables in a module function.
#>
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
#[Management.Automation.PSScriptCmdlet]
# The module function's `$PSCmdlet` object. Requires the function be decorated with the `[CmdletBinding()]` attribute.
$Cmdlet,
[Parameter(Mandatory = $true)]
[Management.Automation.SessionState]
# The module function's `$ExecutionContext.SessionState` object. Requires the function be decorated with the `[CmdletBinding()]` attribute.
#
# Used to set variables in its callers' scope, even if that caller is in a different script module.
$SessionState
)
Set-StrictMode -Version 'Latest'
# List of preference variables taken from the about_Preference_Variables and their common parameter name (taken from about_CommonParameters).
$commonPreferences = @{
'ErrorActionPreference' = 'ErrorAction';
'DebugPreference' = 'Debug';
'ConfirmPreference' = 'Confirm';
'InformationPreference' = 'InformationAction';
'VerbosePreference' = 'Verbose';
'WarningPreference' = 'WarningAction';
'WhatIfPreference' = 'WhatIf';
}
foreach( $prefName in $commonPreferences.Keys )
{
$parameterName = $commonPreferences[$prefName]
# Don't do anything if the parameter was passed in.
if( $Cmdlet.MyInvocation.BoundParameters.ContainsKey($parameterName) )
{
continue
}
$variable = $Cmdlet.SessionState.PSVariable.Get($prefName)
# Don't do anything if caller didn't use a common parameter.
if( -not $variable )
{
continue
}
if( $SessionState -eq $ExecutionContext.SessionState )
{
Set-Variable -Scope 1 -Name $variable.Name -Value $variable.Value -Force -Confirm:$false -WhatIf:$false
}
else
{
$SessionState.PSVariable.Set($variable.Name, $variable.Value)
}
}
}
function Assert-ModuleVersion
{
param(
[Parameter(Mandatory=$true)]
[string]
# The path to the module's manifest.
$ManifestPath,
[string[]]
# Path to any additional assemblies whose versions should get checked.
$AssemblyPath,
[string]
# Path to a release notes file.
$ReleaseNotesPath,
[string]
# The path to the module's nuspec file.
$NuspecPath,
[string[]]
# A list of assembly file names that should be excluded from the version check. Wildcards allowed. Only assembly names are matched
$ExcludeAssembly
)
Set-StrictMode -Version 'Latest'
$errorsAtStart = $Error.Count
$manifest = Test-ModuleManifest -Path $ManifestPath
if( -not $manifest )
{
return
}
$version = $manifest.Version
Write-Verbose -Message ('Checking that {0} module is at version {1}.' -f $manifest.Name,$version)
$badAssemblies = Invoke-Command {
$manifest.RequiredAssemblies |
ForEach-Object {
if( -not [IO.Path]::IsPathRooted($_) )
{
Join-Path -Path (Split-Path -Parent -Path $manifest.Path) -ChildPath $_
}
else
{
$_
}
}
if( $AssemblyPath )
{
$AssemblyPath
}
} |
Where-Object {
foreach( $exclusion in $ExcludeAssembly )
{
if( (Split-Path -Leaf -Path $_) -like $exclusion )
{
return $false
}
}
return $true
} |
Get-Item |
Where-Object {
-not ($_.VersionInfo.FileVersion.ToString().StartsWith($version.ToString())) -or -not ($_.VersionInfo.ProductVersion.ToString().StartsWith($version.ToString()))
} |
ForEach-Object {
' * {0} (FileVersion: {1}; ProductVersion: {2})' -f $_.Name,$_.VersionInfo.FileVersion,$_.VersionInfo.ProductVersion
}
if( $badAssemblies )
{
Write-Error -Message ('The following assemblies are not at version {0}.{1}{2}' -f $version,([Environment]::NewLine),($badAssemblies -join ([Environment]::NewLine)))
}
if( $ReleaseNotesPath )
{
$foundFirstVersion = $false
$releaseNotesVersion = Get-Content -Path $ReleaseNotesPath |
ForEach-Object {
if( -not $foundFirstVersion -and $_ -match '^#\s+(\d+\.\d+\.\d+)' )
{
$foundFirstVersion = $true
return [Version]$Matches[1]
}
}
if( -not $releaseNotesVersion )
{
Write-Error -Message ('Version {0} not found in release notes ({1}).' -f $version,$ReleaseNotesPath)
}
}
if( $NuspecPath )
{
$nuspec = [xml](Get-Content -Raw -Path $NuspecPath)
if( $nuspec )
{
$nuspecVersion = [Version]($nuspec.package.metadata.version)
if( $nuspecVersion )
{
if( $version -ne $nuspecVersion )
{
Write-Error -Message ('Nuspec file ''{0}'' is at version {1}, but should be at version {2}..' -f $NuspecPath,$nuspecVersion,$version)
}
}
else
{
Write-Error -Message ('Nuspec file ''{0}'' contains an invalid version.' -f $NuspecPath)
}
}
else
{
Write-Error -Message ('Nuspec file ''{0}'' does not contain valid XML.' -f $NuspecPath)
}
}
return (($Error.Count - $errorsAtStart) -eq 0)
}
function Split-MarkdownTopic
{
<#
.SYNOPSIS
Parses a Markdown-formatted module help topic, e.g. about_Module.
.DESCRIPTION
A Markdown-formatted help topic should contain four sections, `Topic`, `Short Description`, `Long Description`, and `See Also`. These should all be formatted as level-1 headings. For example:
# Topic
about_Silk
# Short Description
Silk is a PowerShell module used to convert another module's help system into an HTML website.
# Long Description
MOre details here. Yadda, yadda, yadda.
# See Also
about_Silk_AdditionalTopic
#>
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)]
# The root where the config file was found.
$ConfigFileRoot,
[Parameter(Mandatory=$true,ValueFromPipeline=$true)]
# An object containing information about the topic to parse.
$TopicInfo
)
process
{
Set-StrictMode -Version Latest
$path = $TopicInfo.Path
if( -not (Test-Path -Path $path -PathType Leaf) )
{
Write-Error ('Markdown help topic <{0}> not found.' -f $path)
return
}
$content = New-Object Collections.ArrayList
$sectionName = $null
$eof = [Guid]::NewGuid().ToString()
$topic = New-Object PsObject -Property @{ Name = ''; Synopsis = ''; Description = ''; RelatedLinks = ''; FileName = $TopicInfo.FileName }
$lineNum = 0
Invoke-Command { Get-Content -Path $path ; $eof } | ForEach-Object {
if( $_ -match '^# (.*)$' -or $_ -eq $eof )
{
if( $sectionName -or $_ -eq $eof )
{
$topic.$sectionName = $content -join "`n"
$topic.$sectionName = $topic.$sectionName.Trim()
if( $_ -eq $eof )
{
return
}
$content.Clear()
}
$sectionName = $matches[1]
switch -Regex ($sectionName)
{
'Topic|Name'
{
$sectionName = 'Name'
}
'Short Description|Synopsis'
{
$sectionName = 'Synopsis'
}
'Long Description|Description'
{
$sectionName = 'Description'
}
'See Also|(Related )?Links?'
{
$sectionName = 'RelatedLinks'
}
default
{
Write-Error ('{0}: line {1}: Unknown top-level heading <{2}>. Expected <Name>, <Synopsis>, <Description>, or <Link>. <Link> may be used multiple times.' -f $path,$lineNum,$_)
}
}
}
else
{
if( -not $sectionName )
{
Write-Error ('{0}: line {1}: Invalid Markdown help topic: the first line must be `# Name`.' -f $path,$lineNum)
return
}
[void] $content.Add( $_ )
}
++$lineNum
}
if( $TopicInfo | Get-Member Title )
{
$topic.Name = $TopicInfo.Title
}
return $topic
}
}
# Copyright 2012 Aaron Jensen
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
function Publish-ChocolateyPackage
{
<#
.SYNOPSIS
Creates and publishes a NuGet package to nuget.org.
#>
[CmdletBinding(SupportsShouldProcess=$true)]
param(
[Parameter(Mandatory=$true)]
[string]
# The path to the module manifest of the module you want to publish.
$NupkgPath,
[string]
# The API key(s) to use. To supply multiple API keys, use a hashtable where each key is a repository server name and the value is the API key for that repository. For example,
#
# @{ 'nuget.org' = '395edfa5-652f-4598-868e-c0a73be02c84' }
#
# If not specified, you'll be prompted for it.
$ApiKey
)
Set-StrictMode -Version 'Latest'
Use-CallerPreference -Cmdlet $PSCmdlet -Session $ExecutionContext.SessionState
if( -not (Get-Command -Name 'choco.exe' -ErrorAction Ignore) )
{
Write-Error -Message ('Chocolatey is not installed. Go to http://chocolatey.org for installation instructions.')
return
}
if( -not (Test-Path -Path $NupkgPath -PathType Leaf) )
{
Write-Error -Message ('Chocolatey package ''{0}'' does not exist.' -f $NupkgPath)
return
}
$nupkgName = [IO.Path]::GetFileNameWithoutExtension($NupkgPath)
if( $nupkgName -notmatch '^(.+)\.(\d+\.\d+\.\d)+$' )
{
Write-Error -Message ('Chocolatey package ''{0}'' does not have the version to publish in its name.' -f $nupkgName)
return
}
$packageName = $Matches[1]
$version = $Matches[2]
try
{
$packageUrl = 'https://chocolatey.org/api/v2/package/{0}/{1}' -f $packageName,$version
try
{
$resp = Invoke-WebRequest -Uri $packageUrl -ErrorAction Ignore
$publish = ($resp.StatusCode -ne 200)
}
catch
{
$publish = $true
}
if( -not $publish )
{
Write-Warning ('Chocolatey package {0} {1} already published to chocolatey.org.' -f $packageName,$version)
return
}
if( $PSCmdlet.ShouldProcess(('publish package to chocolatey.org'),'','') )
{
if( -not $ApiKey )
{
$ApiKey = Read-Host -Prompt ('Please enter your chocolatey.org API key')
if( -not $ApiKey )
{
Write-Error -Message ('The chocolatey.org API key is required. Package not published to chocolatey.org')
continue
}
}
$verbosity = ''
if( $VerbosePreference -eq 'Continue' )
{
$verbosity = '-v'
}
choco.exe push --source 'https://chocolatey.org' --key $ApiKey $verbosity $nupkgPath
$resp = Invoke-WebRequest -Uri $packageUrl
$resp | Select-Object -Property 'StatusCode','StatusDescription',@{ Name = 'Uri'; Expression = { $packageUrl }}
}
}
finally
{
Pop-Location
}
}
function Get-TypeDocumentationLink
{
param(
[Parameter(Mandatory=$true)]
[string]
# The name of the command where the type was found.
$CommandName,
[Parameter(Mandatory=$true)]
[string]
# The name of the type whose documentation link to return.
$TypeName
)
Set-StrictMode -Version 'Latest'
$displayName = $TypeName
if( $TypeName.EndsWith('[]') )
{
$TypeName = $TypeName -replace '\[\]',''
}
if( $TypeName -eq 'bool' )
{
$TypeName = 'boolean'
}
$type = $null
if( $loadedTypes.ContainsKey( $TypeName ) )
{
$type = [Type]$loadedTypes[$TypeName]
}
else
{
try
{
$type = [Type]$TypeName
}
catch
{
Write-Warning ("[{0}] Type {1} not found." -f $CommandName,$TypeName)
return $displayName
}
}
$typeLink = $TypeName
$typeFullName = $type.FullName
$msdnUri = 'http://msdn.microsoft.com/en-us/library/{0}.aspx' -f $Type.FullName.ToLower()
if( $Type.FullName -notlike 'System.*' )
{
$result = $null
try
{
$result = Invoke-WebRequest -Uri $msdnUri -Method Head -ErrorAction Ignore
}
catch
{
}
if( -not $result )
{
return $displayName
}
}
return '<a href="{0}">{1}</a>' -f $msdnUri,$displayName
}
function Get-ModuleVersion
{
param(
[Parameter(Mandatory=$true)]
[string]
# The path to the module's manifest.
$ManifestPath
)
Set-StrictMode -Version 'Latest'
}
function Get-ModuleReleaseNotes
{
param(
[Parameter(Mandatory=$true)]
[string]
# Path to the module's manifest.
$ManifestPath,
[Parameter(Mandatory=$true)]
[string]
# Path to the releaes notes file.
$ReleaseNotesPath
)
Set-StrictMode -Version 'Latest'
$Version = Test-ModuleManifest -Path $ManifestPath | Select-Object -ExpandProperty 'Version'
if( -not $Version )
{
Write-Error -Message ('Version not found in module manifest ''{0}''.' -f $ManifestPath)
return
}
$foundVersion = $false
$versionReleaseNotes = Get-Content -Path $ReleaseNotesPath |
Where-Object {
$line = $_
if( -not $foundVersion )
{
if( $line -match ('^#\s+{0}' -f [regex]::Escape($version)) )
{
$foundVersion = $true
return
}
}
else
{
if( $line -match ('^#\s+(?!{0})' -f [regex]::Escape($version)) )
{
$foundVersion = $false
}
}
return( $foundVersion )
}
if( -not $versionReleaseNotes )
{
Write-Error -Message ('There are no release notes for version {0} in ''{1}''.' -f $Version,$ReleaseNotesPath)
return
}
$versionReleaseNotes -join [Environment]::NewLine
}
Log in or click on link to see number of positives.
- Silk.0.2.0.nupkg (483445848e88) - ## / 56
- MarkdownSharp.dll (605e6ad93dfe) - ## / 56
- NuGet.exe (8339deb28489) - ## / 54
In cases where actual malware is found, the packages are subject to removal. Software sometimes has false positives. Moderators do not necessarily validate the safety of the underlying software, only that a package retrieves software from the official distribution point and/or validate embedded software against official distribution point (where distribution rights allow redistribution).
Chocolatey Pro provides runtime protection from possible malware.
(c) 2013 Aaron Jensen. All rights reserved.
- Improved
about_Silk
help topic. - Added example scripts
Invoke-Build.ps1
,Publish-Module.ps1
, andNew-Website.ps1
to show how to use Silk.
This package has no dependencies.
Ground Rules:
- This discussion is only about Silk and the Silk package. If you have feedback for Chocolatey, please contact the Google Group.
- This discussion will carry over multiple versions. If you have a comment about a particular version, please note that in your comments.
- The maintainers of this Chocolatey Package will be notified about new comments that are posted to this Disqus thread, however, it is NOT a guarantee that you will get a response. If you do not hear back from the maintainers after posting a message below, please follow up by using the link on the left side of this page or follow this link to contact maintainers. If you still hear nothing back, please follow the package triage process.
- Tell us what you love about the package or Silk, or tell us what needs improvement.
- Share your experiences with the package, or extra configuration or gotchas that you've found.
- If you use a url, the comment will be flagged for moderation until you've been whitelisted. Disqus moderated comments are approved on a weekly schedule if not sooner. It could take between 1-5 days for your comment to show up.