diff --git a/.github/workflows/powershell.yml b/.github/workflows/powershell.yml
new file mode 100644
index 0000000..65efd1a
--- /dev/null
+++ b/.github/workflows/powershell.yml
@@ -0,0 +1,160 @@
+name: PowerShell
+
+on:
+ push:
+ branches: [ "main", "master" ]
+ paths-ignore:
+ - 'docs/**'
+ - 'example/**'
+ - 'Videos/**'
+ - 'Changelog.md'
+ - 'README.md'
+ pull_request:
+
+permissions:
+ contents: read
+
+jobs:
+ build:
+ permissions:
+ contents: read # for actions/checkout to fetch code
+ security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
+ actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status
+ name: Build
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 0 # avoid shallow clone so nbgv can do its work.
+
+ - name: Run PSScriptAnalyzer
+ uses: microsoft/psscriptanalyzer-action@6b2948b1944407914a58661c49941824d149734f
+ with:
+ # Check https://github.com/microsoft/action-psscriptanalyzer for more info about the options.
+ # The below set up runs PSScriptAnalyzer to your entire repository and runs some basic security rules.
+ path: .\src
+ recurse: true
+ # Include your own basic security rules. Removing this option will run all the rules
+ includeRule: '"PSAvoidGlobalAliases", "PSAvoidUsingConvertToSecureStringWithPlainText"'
+ output: results.sarif
+
+ # Upload the SARIF file generated in the previous step
+ - name: Upload SARIF results file
+ uses: github/codeql-action/upload-sarif@v3
+ with:
+ sarif_file: results.sarif
+
+ - uses: dotnet/nbgv@f088059084cb5d872e9d1a994433ca6440c2bf72
+ id: nbgv
+
+ - name: Build
+ shell: pwsh
+ run: ./build.ps1 build ${{ steps.nbgv.outputs.VersionMajor }} ${{ steps.nbgv.outputs.VersionMinor }} ${{ steps.nbgv.outputs.BuildNumber }} ${{ steps.nbgv.outputs.VersionRevision }} ${{ steps.nbgv.outputs.PrereleaseVersionNoLeadingHyphen }}
+
+ - name: Store build output
+ uses: actions/upload-artifact@v4
+ with:
+ name: build
+ path: |
+ publish
+ retention-days: 1
+
+ test7-old:
+ permissions:
+ contents: read # for actions/checkout to fetch code
+ actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status
+ name: Test PowerShell 7 Past Versions
+ needs: Build
+ runs-on: ubuntu-latest
+ container:
+ image: mcr.microsoft.com/powershell:${{ matrix.pwshv }}-ubuntu-22.04
+ strategy:
+ matrix:
+ pwshv: ['7.2', '7.3']
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Download build output
+ uses: actions/download-artifact@v4
+ with:
+ name: build
+ path: publish
+
+ - name: Test
+ shell: pwsh
+ run: ./build.ps1 test
+
+ test7-current:
+ permissions:
+ contents: read # for actions/checkout to fetch code
+ actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status
+ name: Test PowerShell 7.4
+ needs: Build
+ runs-on: ubuntu-latest
+ container:
+ image: mcr.microsoft.com/powershell:${{ matrix.pwshv }}-ubuntu-22.04
+ strategy:
+ matrix:
+ pwshv: ['7.4']
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Download build output
+ uses: actions/download-artifact@v4
+ with:
+ name: build
+ path: publish
+
+ - name: Test
+ shell: pwsh
+ run: ./build.ps1 test
+
+ test5:
+ permissions:
+ contents: read # for actions/checkout to fetch code
+ actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status
+ name: Test PowerShell 5
+ needs: Build
+ runs-on: windows-latest
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Download build output
+ uses: actions/download-artifact@v4
+ with:
+ name: build
+ path: publish
+
+ - name: Test
+ shell: powershell
+ run: ./build.ps1 test
+
+ publish:
+ permissions:
+ contents: read # for actions/checkout to fetch code
+ actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status
+ name: Publish
+ needs: [test7-current]
+ runs-on: ubuntu-latest
+ container:
+ image: mcr.microsoft.com/dotnet/sdk:8.0
+ if: github.ref == 'refs/heads/main'
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Download build output
+ uses: actions/download-artifact@v4
+ with:
+ name: build
+ path: publish
+
+ - name: Publish
+ shell: pwsh
+ run: ./build.ps1 publish
+ env:
+ PSPublishApiKey: ${{ secrets.NUGETAPIKEY }}
diff --git a/.gitignore b/.gitignore
index 598418c..35594bf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -215,3 +215,5 @@ pip-log.txt
.mr.developer.cfg
InstallLocally.ps1
CleanPSHumanizer.ps1
+
+testResults.xml
diff --git a/DoTests.ps1 b/DoTests.ps1
deleted file mode 100644
index fc35c84..0000000
--- a/DoTests.ps1
+++ /dev/null
@@ -1,45 +0,0 @@
-param(
- [Switch]$UsePSCore
-)
-
-function Install-PSCore {
- param(
- $pscoreVerion = '6.2.0-preview.3',
- $os = 'win-x64'
- )
-
- $unZipPath = "$env:TEMP\pscore"
-
- if (!(Test-Path $unZipPath)) {
- $outfile = "$env:TEMP\pscore.zip"
-
- $url = "https://github.com/PowerShell/PowerShell/releases/download/v$($pscoreVerion)/PowerShell-$($pscoreVerion)-$($os).zip"
-
- "Downloading PS Core"
- Invoke-RestMethod $url -OutFile $outfile
-
- "Unzipping PS Core"
- Expand-Archive -Path $outfile -DestinationPath $unZipPath -Force
-
- Remove-Item $outfile -ErrorAction SilentlyContinue
- }
-
- "$unZipPath\pwsh.exe"
-}
-
-if ($UsePSCore) {
- $pwsh = Install-PSCore -os 'win-x64'
- & $pwsh[-1]
-}
-
-$PSVersionTable.PSVersion
-
-if ($null -eq (Get-Module -ListAvailable pester)) {
- Install-Module -Name Pester -Repository PSGallery -Force -Scope CurrentUser
-}
-
-$result = Invoke-Pester -Script $PSScriptRoot\__tests__ -Verbose -PassThru
-
-if ($result.FailedCount -gt 0) {
- throw "$($result.FailedCount) tests failed."
-}
\ No newline at end of file
diff --git a/FileSystem.types.ps1xml b/FileSystem.types.ps1xml
deleted file mode 100644
index cb1683a..0000000
--- a/FileSystem.types.ps1xml
+++ /dev/null
@@ -1,115 +0,0 @@
-
-
-
-
- System.DateTime
-
-
- DateTime
-
- if ((& { Set-StrictMode -Version 1; $this.DisplayHint }) -ieq "Date")
- {
- "{0}" -f $this.ToLongDateString()
- }
- elseif ((& { Set-StrictMode -Version 1; $this.DisplayHint }) -ieq "Time")
- {
- "{0}" -f $this.ToLongTimeString()
- }
- else
- {
- "{0} {1}" -f $this.ToLongDateString(), $this.ToLongTimeString()
- }
-
-
-
-
-
- System.IO.DirectoryInfo
-
-
- Mode
-
- Microsoft.PowerShell.Commands.FileSystemProvider
- Mode
-
-
-
- BaseName
-
- $this.Name
-
-
-
- PSStandardMembers
-
-
- DefaultDisplayProperty
- Name
-
-
-
-
-
-
- System.IO.FileInfo
-
-
- Mode
-
- Microsoft.PowerShell.Commands.FileSystemProvider
- Mode
-
-
-
- VersionInfo
-
- [System.Diagnostics.FileVersionInfo]::GetVersionInfo($this.FullName)
-
-
-
- BaseName
-
- if ($this.Extension.Length -gt 0){$this.Name.Remove($this.Name.Length - $this.Extension.Length)}else{$this.Name}
-
-
-
- PSStandardMembers
-
-
- DefaultDisplayPropertySet
-
- LastWriteTime
- Length
- Name
-
-
-
-
-
-
-
- System.Management.ManagementObject#root\cimv2\Win32_Process
-
-
- ProcessName
- Name
-
-
- Handles
- Handlecount
-
-
- VM
- VirtualSize
-
-
- WS
- WorkingSetSize
-
-
- Path
- $this.ExecutablePath
-
-
-
-
\ No newline at end of file
diff --git a/Humanizer.dll b/Humanizer.dll
deleted file mode 100644
index 179a556..0000000
Binary files a/Humanizer.dll and /dev/null differ
diff --git a/PowerShellHumanizer.Tests.ps1 b/PowerShellHumanizer.Tests.ps1
deleted file mode 100644
index 1f23b20..0000000
--- a/PowerShellHumanizer.Tests.ps1
+++ /dev/null
@@ -1,132 +0,0 @@
-$here = Split-Path -Parent $MyInvocation.MyCommand.Path
-$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '\.Tests\.ps1', '.psd1'
-ipmo "$here\$sut" -Force
-
-Describe 'Functions' {
- Context 'Pluralize' {
- It 'Should convert man to men' {
- ConvertTo-Plural man | Should Be 'men'
- }
- It 'Should convert an array' {
- $output = echo person man woman | ConvertTo-Plural
- $output[0] | Should Be 'people'
- $output[1] | Should Be 'men'
- $output[2] | Should Be 'women'
- }
- }
- Context 'Singularize' {
- $output = echo people men women geese indicies oxen knives | ConvertTo-Singular
- It 'Should convert to singles' {
- $output[0] | Should Be 'person'
- $output[1] | Should Be 'man'
- $output[2] | Should Be 'woman'
- $output[3] | Should Be 'goose'
- $output[4] | Should Be 'indicy'
- $output[5] | Should Be 'ox'
- $output[6] | Should Be 'knife'
- }
-
- }
- Context 'Hyphenate' {
- It 'Should convert to a hyphenated string' {
-
- "Continuing To Make Powershell A Bit More Human" |
- ConvertTo-HyphenatedString |
- Should Be 'continuing-to-make-powershell-a-bit-more-human'
- }
-
- }
- Context 'Number to ordinal words' {
- It 'Should convert to words' {
- ConvertTo-OrdinalWords 121 | Should Be 'hundred and twenty-first'
- }
- It 'Should convert a range to words' {
- $output = 120..122 | ConvertTo-OrdinalWords
- $output[0] | Should Be 'hundred and twentieth'
- $output[1] | Should Be 'hundred and twenty-first'
- $output[2] | Should Be 'hundred and twenty-second'
- }
- }
-}
-
-Describe 'Type Extension Methods' {
- Context 'Strings' {
- It 'Should transform to Upper Case' {
- 'then add nodes under it.'.Transform("UpperCase") | Should Be 'THEN ADD NODES UNDER IT.'
- }
- It 'Should convert to Title Case' {
- 'then add nodes under it.'.ToTitleCase() | Should Be 'Then Add Nodes Under It.'
- }
- It 'Should convert from Title Case' {
- 'FromTitleCase'.Underscore() | Should Be 'from_title_case'
- }
- It 'Should truncate words' {
- 'then add nodes under it.'.Truncate(3,"Words") | Should Match 'then add nodes\W$'
- }
- It 'Should truncate characters' {
- 'then add nodes under it.'.Truncate(3,"Characters") | Should Match 'th\W$'
- }
- It 'Should truncate with optional character' {
- 'then add nodes under it.'.Truncate(7, "Characters", '-') | Should Be 'then ad-'
- }
- It 'Should Dehumanize' {
- 'then add nodes under it.'.Dehumanize() | Should Be 'ThenAddNodesUnderIt'
- }
- It 'Should provide quanity: # word' {
- 'string'.ToQuantity(50) | Should Be '50 strings'
- }
- It 'Should provide quantity: words' {
- 'string'.ToQuantity(50, "Words") | Should Be 'fifty strings'
- }
- It 'Should convert Year to roman numerals' {
- (Get-Date).Year.ToRoman() | Should Be 'MMXVI'
- }
- }
- Context 'Integers' {
- It 'Should ordanalize' {
- (3).Ordinalize() | Should Be '3rd'
- }
- It 'Should convert to word' {
- (3).ToWords() | Should Be 'three'
- }
- It 'Should do math in weeks' {
- (Get-Date 2/13/2016) + (3).Weeks -eq (Get-Date 3/5/2016) | Should Be $true
- }
- }
- Context 'TimeSpan' {
- $past = (Get-Date 2/13/2016).AddMinutes(-1).AddSeconds(-20)
- $time = (Get-Date 2/13/2016) - $past
- It 'Should simplify TimeSpan objects' {
- $time.Humanize() | Should Be '1 minute'
- }
- It 'Should simplify TimeSpan objects with selectable precision' {
- $time.Humanize(2) | Should Be '1 minute, 20 seconds'
- }
- }
- Context 'DateTime' {
- It 'Should display Now as now when UTC is false' {
- (Get-Date).Humanize() | Should Be 'now'
- }
- It 'Should display Now as hours ago when UTC is true' {
- (Get-Date).Humanize($true) | Should Match 'hours'
- }
- }
-}
-
-Describe 'Custom Formats' {
- Context 'TimeSpan' {
- It 'Should display 1 hour' {
- (([TimeSpan]::new(1,0,0))|Out-String).trim() | Should Be '1 hour'
- }
- }
- Context 'FileSystem' {
- $chars = [char[]] ([char]'0'..[char]'9' + [char]'A'..[char]'Z' + [char]'a'..[char]'z')
- $chars = $chars * 126
- (1..(1kb/128)).foreach({-join (Get-Random $chars -Count 126) | Add-Content TestDrive:\testfile.txt })
- It 'Should display 1 KB' {
- ((Get-ChildItem TestDrive:\testfile.txt) | Out-String) | Should Match "1 KB testfile.txt"
- }
- }
-}
-
-Remove-Module PowerShellHumanizer
\ No newline at end of file
diff --git a/PowerShellHumanizer.psd1 b/PowerShellHumanizer.psd1
deleted file mode 100644
index 2184059..0000000
--- a/PowerShellHumanizer.psd1
+++ /dev/null
@@ -1,126 +0,0 @@
-#
-# Module manifest for module 'PowerShellHumanizer'
-#
-# Generated by: Douglas Finke
-#
-# Generated on: 5/7/2014
-#
-
-@{
-
- # Script module or binary module file associated with this manifest.
- RootModule = 'PowerShellHumanizer.psm1'
-
- # Version number of this module.
- ModuleVersion = '3.2'
-
- # ID used to uniquely identify this module
- GUID = '6dc9be51-eb93-4355-8648-0c725c0ac988'
-
- # Author of this module
- Author = 'Douglas Finke and Chris Hunt'
-
- # Company or vendor of this module
- CompanyName = 'No Company'
-
- # Copyright statement for this module
- Copyright = 'c 2015 All rights reserved.'
-
- # Description of the functionality provided by this module
- Description = 'PowerShell Humanizer wraps Humanizer: meets all your .NET needs for manipulating and displaying strings, enums, dates, times, timespans, numbers and quantities'
-
- # 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 Microsoft .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) 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 = @('String.types.ps1xml', 'Int.types.ps1xml','TimeSpan.types.ps1xml','DateTime.types.ps1xml')
-
- # Format files (.ps1xml) to be loaded when importing this module
- FormatsToProcess = @('TimeSpan.format.ps1xml')
-
- # Modules to import as nested modules of the module specified in RootModule/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 RootModule/ModuleToProcess
- PrivateData = @{
- # PSData is module packaging and gallery metadata embedded in PrivateData
- # It's for rebuilding PowerShellGet (and PoshCode) NuGet-style packages
- # We had to do this because it's the only place we're allowed to extend the manifest
- # https://connect.microsoft.com/PowerShell/feedback/details/421837
- PSData = @{
- # The primary categorization of this module (from the TechNet Gallery tech tree).
- Category = "PowerShell Humanizer"
-
- # Keyword tags to help users find this module via navigations and search.
- Tags = @("PowerShell", "Humanizer")
-
- # The web address of an icon which can be used in galleries to represent this module
- #IconUri = "http://pesterbdd.com/images/Pester.png"
-
- # The web address of this module's project or support homepage.
- ProjectUri = "https://github.com/dfinke/PowerShellHumanizer"
-
- # The web address of this module's license. Points to a page that's embeddable and linkable.
- LicenseUri = "https://github.com/dfinke/PowerShellHumanizer/blob/master/LICENSE.txt"
-
- # Release notes for this particular version of the module
- # ReleaseNotes = False
-
- # If true, the LicenseUrl points to an end-user license (not just a source license) which requires the user agreement before use.
- # RequireLicenseAcceptance = ""
-
- # Indicates this is a pre-release/testing version of the module.
- IsPrerelease = 'False'
- }
- }
-
- # HelpInfo URI of this module
- # HelpInfoURI = ''
-
- # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
- # DefaultCommandPrefix = ''
-
-}
-
diff --git a/PowerShellHumanizer.psm1 b/PowerShellHumanizer.psm1
deleted file mode 100644
index 3a7b0ac..0000000
--- a/PowerShellHumanizer.psm1
+++ /dev/null
@@ -1,145 +0,0 @@
-Add-Type -Path "$PSScriptRoot\Humanizer.dll"
-
-$Types = @("$PSScriptRoot\String.types.ps1xml",
- "$PSScriptRoot\Int.types.ps1xml",
- "$PSScriptRoot\TimeSpan.types.ps1xml",
- "$PSScriptRoot\DateTime.types.ps1xml",
- "$PSScriptRoot\CmdletInfo.types.ps1xml")
-
-Update-TypeData -PrependPath $Types
-
-# Must call Update-FormatData with -PrependPath to override built-in defined formats
-Update-FormatData -PrependPath "$PSScriptRoot\TimeSpan.format.ps1xml"
-Update-FormatData -PrependPath "$PSScriptRoot\FileInfo.format.ps1xml"
-
-function ConvertFrom-RomanNumeral {
- param(
- [Parameter(ValueFromPipeline=$true)]
- [string]$RomanNumeral
- )
-
- Process {
- [Humanizer.RomanNumeralExtensions]::FromRoman($RomanNumeral)
- }
-}
-
-function ConvertTo-Casing {
- param(
- [Parameter(ValueFromPipeline=$true)]
- [string]$Target,
- [ValidateSet("Title","AllCaps","LowerCase","Sentence")]
- $Case="Title"
- )
-
- Process {
- [Humanizer.CasingExtensions]::ApplyCase($Target, $Case)
-
- }
-}
-
-function ConvertTo-HumanDate {
- param(
- [Parameter(ValueFromPipeline=$true)]
- [datetime]$Date=(Get-Date)
- )
-
- Process {
- [Humanizer.DateHumanizeExtensions]::Humanize( $Date , $false )
- }
-}
-
-function ConvertTo-Ordinal {
- param(
- [Parameter(ValueFromPipeline=$true)]
- [int]$Target
- )
-
- Process {
- [Humanizer.OrdinalizeExtensions]::Ordinalize($Target)
- }
-}
-
-function ConvertTo-OrdinalWords {
- param(
- [Parameter(ValueFromPipeline=$true)]
- [int]$Target
- )
-
- Process {
- [Humanizer.NumberToWordsExtension]::ToOrdinalWords($Target)
- }
-}
-
-function ConvertTo-Plural {
- param(
- [Parameter(ValueFromPipeline=$true)]
- $Word
- )
-
- Process {
- [Humanizer.InflectorExtensions]::Pluralize($word)
- }
-}
-
-function ConvertTo-Quantity {
- param(
- [string]$string,
-
- [Parameter(ValueFromPipeline=$true)]
- [int]$quantity,
-
- [ValidateSet("None","Numeric","Words")]
- $showQuantityAs="Numeric"
- )
-
- Process {
- [Humanizer.ToQuantityExtensions]::ToQuantity($string, $quantity, $showQuantityAs)
- }
-}
-
-
-function ConvertTo-RomanNumeral {
- param(
- [Parameter(ValueFromPipeline=$true)]
- [int]$Number
- )
-
- Process {
- [Humanizer.RomanNumeralExtensions]::ToRoman($Number)
- }
-}
-
-function ConvertTo-Singular {
- param(
- [Parameter(ValueFromPipeline=$true)]
- $Word
- )
-
- Process {
- [Humanizer.InflectorExtensions]::Singularize($word)
- }
-}
-
-function ConvertTo-Words {
- param(
- [Parameter(ValueFromPipeline=$true)]
- [int]$number
- )
-
- Process {
- [Humanizer.NumberToWordsExtension]::ToWords($number)
- }
-}
-
-function ConvertTo-HyphenatedString {
- param(
- [Parameter(ValueFromPipeline=$true)]
- $TitleString
- )
-
- Process {
- [Humanizer.InflectorExtensions]::Dasherize($TitleString.Underscore())
- }
-}
-
-
diff --git a/PublishToGallery.ps1 b/PublishToGallery.ps1
deleted file mode 100644
index 162d6d4..0000000
--- a/PublishToGallery.ps1
+++ /dev/null
@@ -1,7 +0,0 @@
-$p = @{
- Name = "PowerShellHumanizer"
- NuGetApiKey = $NuGetApiKey
- ReleaseNote = "Updated dependency, added Pester tests and more"
-}
-
-Publish-Module @p
\ No newline at end of file
diff --git a/README.md b/README.md
index 06588d7..ec1dee3 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,3 @@
-
-
-
# PowerShell Humanizer
@@ -9,8 +6,11 @@ This PowerShell module wraps [Mehdi Khalili's .NET Humanizer](https://github.com
> Humanizer meets all your .NET needs for manipulating and displaying strings, enums, dates, times, timespans, numbers and quantities [http://humanizr.net](http://humanizr.net)
-Install
--
+
+[](https://www.powershellgallery.com/packages/PowerShellHumanizer)
+
+## Install
+
To install grab it from the [Powershell Gallery](https://www.powershellgallery.com/packages/PowerShellHumanizer)
```powershell
@@ -18,6 +18,13 @@ Install-Module -Name PowerShellHumanizer
```
## What's new
+
+5/29/2024
+
+No new functionality.
+The Humanizer library has been updated to 3.0.0-beta13.
+Documentation has been added for each command.
+
4/24/2016
Check out how to call the `Humanize` capabilities.
diff --git a/__tests__/PSHumanizer.tests.ps1 b/__tests__/PSHumanizer.tests.ps1
deleted file mode 100644
index 9bbaf21..0000000
--- a/__tests__/PSHumanizer.tests.ps1
+++ /dev/null
@@ -1,7 +0,0 @@
-Import-Module $PSScriptRoot\..\PowerShellHumanizer.psd1 -Force
-
-Describe "Test Humanizer" {
- It "Flight test should be true" {
- $true | Should Be $true
- }
-}
\ No newline at end of file
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
deleted file mode 100644
index 6a25765..0000000
--- a/azure-pipelines.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-# https://developercommunity.visualstudio.com/content/problem/400181/pwsh-true-exports-but-fails-on-import.html
-# resources:
-# - repo: self
-# queue:
-# name: Hosted VS2017
-
-jobs:
-- job: Windows
- pool:
- vmImage: 'vs2017-win2016'
- steps:
- - powershell: .\DoTests.ps1
- displayName: 'Invoke Tests - Windows PowerShell'
- - powershell: .\DoTests.ps1 -UsePSCore
- displayName: 'Invoke Tests - PowerShell Core'
-
-trigger:
- paths:
- exclude:
- - README.md
\ No newline at end of file
diff --git a/build.ps1 b/build.ps1
new file mode 100644
index 0000000..65cc242
--- /dev/null
+++ b/build.ps1
@@ -0,0 +1,245 @@
+#! /usr/bin/pwsh
+
+[CmdletBinding()]
+param (
+ [Parameter(Position = 0)]
+ [ValidateSet('clean', 'build', 'test', 'publish', 'docs')]
+ [string[]]
+ $Task,
+
+ [Parameter(Position = 1)]
+ [int]
+ $Major,
+
+ [Parameter(Position = 2)]
+ [int]
+ $Minor,
+
+ [Parameter(Position = 3)]
+ [int]
+ $Build,
+
+ [Parameter(Position = 4)]
+ [int]
+ $Revision,
+
+ [Parameter(Position = 5)]
+ [string]
+ $Prerelease
+)
+
+if ( (Get-Command 'nbgv' -CommandType Application -ErrorAction SilentlyContinue) ) {
+ if (!$PSBoundParameters.ContainsKey('Major')) { $Major = $(nbgv get-version -v VersionMajor) }
+ if (!$PSBoundParameters.ContainsKey('Minor')) { $Minor = $(nbgv get-version -v VersionMinor) }
+ if (!$PSBoundParameters.ContainsKey('Build')) { $Build = $(nbgv get-version -v BuildNumber) }
+ if (!$PSBoundParameters.ContainsKey('Revision')) { $Revision = $(nbgv get-version -v VersionRevision) }
+}
+
+$module = 'PowerShellHumanizer'
+$parent = $PSScriptRoot
+$parent = if ([string]::IsNullOrEmpty($parent)) { $pwd.Path } else { $parent }
+$src = Join-Path $parent -ChildPath "src"
+$docs = Join-Path $parent -ChildPath "docs"
+$publish = [System.IO.Path]::Combine($parent, "publish", $module)
+$csproj = [System.IO.Path]::Combine($src, "dotnet", "dependencies.csproj")
+$bin = [System.IO.Path]::Combine($src, "dotnet", "bin")
+$obj = [System.IO.Path]::Combine($src, "dotnet", "obj")
+$lib = [System.IO.Path]::Combine($publish, "lib")
+
+Write-Host "src: $src"
+Write-Host "docs: $docs"
+Write-Host "publish: $publish"
+Write-Host "lib: $lib"
+Write-Host "dotnet: $([Environment]::Version)"
+Write-Host "ps: $($PSVersionTable.PSVersion)"
+
+$manifest = @{
+ Path = Join-Path -Path $publish -ChildPath "$module.psd1"
+ Author = 'Douglas Finke and Chris Hunt'
+ CompanyName = 'No Company'
+ Copyright = 'c 2024 All rights reserved.'
+ CompatiblePSEditions = @("Desktop", "Core")
+ Description = 'PowerShell Humanizer wraps Humanizer: meets all your .NET needs for manipulating and displaying strings, enums, dates, times, timespans, numbers and quantities'
+ GUID = '6dc9be51-eb93-4355-8648-0c725c0ac988'
+
+ FunctionsToExport = @()
+ ModuleVersion = [version]::new($Major, $Minor, $Build, $Revision)
+ PowerShellVersion = '5.1'
+ ProjectUri = "https://github.com/dfinke/PowerShellHumanizer"
+ LicenseUri = "https://github.com/dfinke/PowerShellHumanizer/blob/master/LICENSE.txt"
+ RootModule = "$module.psm1"
+ Tags = @('PowerShell', 'Humanizer', 'strings', 'enums', 'dates', 'times', 'timespans', 'numbers', 'quantities')
+
+ #RequiredModules = @( )
+ #CmdletsToExport = ''
+ #VariablesToExport = ''
+ AliasesToExport = @('ConvertTo-DateWord','Kabab','Pluralize')
+
+}
+
+function Clean {
+ param ()
+
+ if (Test-Path $publish) {
+ Remove-Item -Path $publish -Recurse -Force
+ }
+}
+
+function Dependencies {
+ param ()
+
+ Foreach ($mod in $manifest.RequiredModules) {
+ if ($null -eq (Get-Module -Name $mod.ModuleName -ListAvailable | Where-Object { [version]$_.Version -ge [version]$mod.ModuleVersion })) {
+ Install-Module $mod.ModuleName -RequiredVersion $mod.ModuleVersion -Scope CurrentUser -Confirm:$false -Force
+ }
+ }
+}
+
+function Build {
+ param ()
+
+ New-Item -Path $publish -ItemType Directory -ErrorAction SilentlyContinue | Out-Null
+
+ dotnet publish $csproj -o $lib
+ Get-ChildItem -Path $lib -filter "*.json" | Remove-Item -Force -ErrorAction SilentlyContinue
+ Get-ChildItem -Path $lib -filter "*.pdb" | Remove-Item -Force -ErrorAction SilentlyContinue
+ Get-ChildItem -Path $lib -filter "System.Management.Automation.dll" | Remove-Item -Force -ErrorAction SilentlyContinue
+ Get-ChildItem -Path $lib -filter "dependencies.dll" | Remove-Item -Force -ErrorAction SilentlyContinue
+
+ Copy-Item -Path "$src/$module.psm1" -Destination $publish
+ Copy-Item -Path @("$parent/README.md") -Destination $publish -ErrorAction SilentlyContinue
+
+ $publicFunctions = Get-ChildItem -Path "$src/public/*.ps1"
+ $privateFunctions = Get-ChildItem -Path "$src/private/*.ps1" -ErrorAction SilentlyContinue
+ $types = Get-ChildItem -Path "$src/types/*.ps1xml"
+ $formats = Get-ChildItem -Path "$src/formats/*.ps1xml"
+
+ New-Item -Path "$publish/types" -ItemType Directory -ErrorAction SilentlyContinue | Out-Null
+ foreach ($type in $types) {
+ Copy-Item -Path $type.FullName -Destination "$publish/types/$($type.Name)"
+ 'Update-TypeData -PrependPath "$PSSCriptRoot/types/{0}"' -f $type.Name | Add-Content "$publish/$module.psm1"
+ }
+
+ New-Item -Path "$publish/formats" -ItemType Directory -ErrorAction SilentlyContinue | Out-Null
+ foreach ($format in $formats) {
+ Copy-Item -Path $format.FullName -Destination "$publish/formats/$($format.Name)"
+ #'Update-FormatData -PrependPath "$PSSCriptRoot/formats/{0}"' -f $format.Name | Add-Content "$publish/$module.psm1"
+ }
+
+ New-Item -Path "$publish/private" -ItemType Directory -ErrorAction SilentlyContinue | Out-Null
+ foreach ($function in $privateFunctions) {
+ Copy-Item -Path $function.FullName -Destination "$publish/private/$($function.Name)"
+ '. "$PSSCriptRoot/private/{0}"' -f $function.Name | Add-Content "$publish/$module.psm1"
+ }
+
+ New-Item -Path "$publish/public" -ItemType Directory -ErrorAction SilentlyContinue | Out-Null
+ foreach ($function in $publicFunctions) {
+ Copy-Item -Path $function.FullName -Destination "$publish/public/$($function.Name)"
+ '. "$PSSCriptRoot/public/{0}"' -f $function.Name | Add-Content "$publish/$module.psm1"
+ $manifest.FunctionsToExport += $function.BaseName
+ }
+
+ Copy-Item -Path "$src/en-US" -Destination "$publish" -Recurse
+
+ if ($PSBoundParameters.ContainsKey('Prerelease')) {
+ $manifest.Add('Prerelease', $PreRelease)
+ }
+
+ New-ModuleManifest @manifest
+
+}
+
+function Test {
+ param ()
+
+ if ($null -eq (Get-Module Pester -ListAvailable | Where-Object { [version]$_.Version -ge [version]"5.5.0" })) {
+ Install-Module -Name Pester -MinimumVersion 5.5.0 -Confirm:$false -Force
+ }
+
+ $config = New-PesterConfiguration -Hashtable @{
+ Run = @{
+ Path = "tests"
+ Exit = if ($true -eq $env:CI) { $ture } else { $false }
+ }
+ TestResult = @{
+ Enabled = $true
+ OutputFormat = "NUnitXml"
+ }
+ Output = @{ Verbosity = "Detailed" }
+ }
+
+ Invoke-Pester -Configuration $config
+
+}
+
+
+function Publish {
+ param ()
+
+ $repo = if ($env:PSPublishRepo) { $env:PSPublishRepo } else { 'PSGallery' }
+
+ Publish-Module -Path $publish -Repository $repo -NuGetApiKey $env:PSPublishApiKey
+}
+
+function Docs {
+ param ()
+
+ if ($null -eq (Get-Module Build-Docs -ListAvailable | Where-Object { [version]$_.Version -ge [version]"0.2.0" })) {
+ Install-Module -Name Build-Docs -MinimumVersion 0.2.0 -Confirm:$false -Force
+ }
+
+ Import-Module Build-Docs
+ Import-Module $publish -Force
+
+ $help = Get-HelpModuleData $module
+ $aliases = Get-Alias | Where-Object Source -eq $module
+
+ # docs/README.md
+ $help | New-HelpDoc |
+ Add-ModuleProperty Name -H1 |
+ Add-ModuleProperty Description |
+ Add-HelpDocText "Commands" -H2 |
+ Add-ModuleCommand -AsLinks |
+ Add-HelpDocText "Aliases" -H2 |
+ Out-HelpDoc -Path 'docs/README.md'
+
+
+ $aliases | ForEach-Object {
+ '- `{0}` -> `{1}`' -f $_.Name, $_.Definition | Add-Content -Path 'docs/README.md'
+ }
+
+ # Individual Commands
+ foreach ($command in $help.Commands) {
+ $name = $command.Name
+ $doc = New-HelpDoc -HelpModuleData $help
+ $doc.Text = $command.ToMD()
+ $doc | Out-HelpDoc -Path "docs/$name.md"
+ }
+}
+
+switch ($Task) {
+ { $_ -contains 'clean' } {
+ Clean
+ }
+ { $_ -contains 'build' } {
+ Clean
+ Dependencies
+ Build
+ }
+ { $_ -contains 'test' } {
+ Dependencies
+ Test
+ }
+ { $_ -contains 'publish' } {
+ Dependencies
+ Publish
+ }
+ { $_ -contains 'docs' } {
+ Dependencies
+ Docs
+ }
+ Default {
+ Clean
+ Build
+ }
+}
\ No newline at end of file
diff --git a/docs/ConvertFrom-RomanNumeral.md b/docs/ConvertFrom-RomanNumeral.md
new file mode 100644
index 0000000..1a7e14c
--- /dev/null
+++ b/docs/ConvertFrom-RomanNumeral.md
@@ -0,0 +1,24 @@
+# ConvertFrom-RomanNumeral
+
+Convert a Roman Numeral String to an Int.
+
+## Parameters
+
+### Parameter Set 1
+
+- `[String[]]` **RomanNumeral** _One or more Roman Numeral Strings to convert._ Mandatory, ValueFromPipeline
+
+## Examples
+
+### Example 1
+
+
+
+```powershell
+ConvertFrom-RomanNumeral IV
+4
+```
+
+## Outputs
+
+- `int`
diff --git a/docs/ConvertTo-Casing.md b/docs/ConvertTo-Casing.md
new file mode 100644
index 0000000..91a214d
--- /dev/null
+++ b/docs/ConvertTo-Casing.md
@@ -0,0 +1,25 @@
+# ConvertTo-Casing
+
+Format the given string with the given case. Options are Title, AllCaps, LowerCase, and Sentence.
+
+## Parameters
+
+### Parameter Set 1
+
+- `[String[]]` **Target** _One or more strings to format._ Mandatory, ValueFromPipeline
+- `[Switch]` **Case** _The target casing. Options are Title, AllCaps, LowerCase, and Sentence. Default is Title._
+
+## Examples
+
+### Example 1
+
+
+
+```powershell
+"the powershell gallery" | ConvertTo-Casing -Case Title
+the Powershell Gallery
+```
+
+## Outputs
+
+- `string`
diff --git a/docs/ConvertTo-HumanDate.md b/docs/ConvertTo-HumanDate.md
new file mode 100644
index 0000000..7a22d5d
--- /dev/null
+++ b/docs/ConvertTo-HumanDate.md
@@ -0,0 +1,40 @@
+# ConvertTo-HumanDate
+
+Return a string representing time relative a given Date.
+
+## Parameters
+
+### Parameter Set 1
+
+- `[DateTime]` **Date** _A DateTime object. Default is Now._ ValueFromPipeline
+
+## Examples
+
+### Example 1
+
+
+
+```powershell
+ConvertTo-HumanDate
+now
+```
+### Example 2
+
+
+
+```powershell
+ConvertTo-HumanDate (Get-Date).AddDays(-1)
+yesterday
+```
+### Example 3
+
+
+
+```powershell
+ConvertTo-HumanDate (Get-Date).AddDays(-12)
+12 days ago
+```
+
+## Outputs
+
+- `string`
diff --git a/docs/ConvertTo-HyphenatedString.md b/docs/ConvertTo-HyphenatedString.md
new file mode 100644
index 0000000..52ce3a5
--- /dev/null
+++ b/docs/ConvertTo-HyphenatedString.md
@@ -0,0 +1,36 @@
+# ConvertTo-HyphenatedString
+
+Convert a string to a Hyphenated string.
+
+## Parameters
+
+### Parameter Set 1
+
+- `[String]` **String** _A string to convert._ Mandatory, ValueFromPipeline
+
+## Examples
+
+### Example 1
+
+
+
+```powershell
+ConvertTo-HyphenatedString "verb noun"
+verb-noun
+```
+### Example 2
+
+
+
+```powershell
+ConvertTo-HyphenatedString PowerShellHumanizer
+power-shell-humanizer
+```
+
+## Notes
+
+This requires the input string to have some word sepration. Either whitespace or Title case.
+
+## Outputs
+
+- `string`
diff --git a/docs/ConvertTo-Ordinal.md b/docs/ConvertTo-Ordinal.md
new file mode 100644
index 0000000..38c4eda
--- /dev/null
+++ b/docs/ConvertTo-Ordinal.md
@@ -0,0 +1,24 @@
+# ConvertTo-Ordinal
+
+Convert an int to an ordinal number with the correct suffix.
+
+## Parameters
+
+### Parameter Set 1
+
+- `[Int32]` **Target** _An int to convert._ Mandatory, ValueFromPipeline
+
+## Examples
+
+### Example 1
+
+
+
+```powershell
+ConvertTo-Ordinal 1
+1st
+```
+
+## Outputs
+
+- `string`
diff --git a/docs/ConvertTo-OrdinalWord.md b/docs/ConvertTo-OrdinalWord.md
new file mode 100644
index 0000000..7871037
--- /dev/null
+++ b/docs/ConvertTo-OrdinalWord.md
@@ -0,0 +1,24 @@
+# ConvertTo-OrdinalWord
+
+Convert an int to an ordinal word. First, Second, etc.
+
+## Parameters
+
+### Parameter Set 1
+
+- `[Int32]` **Target** _An int to convert._ ValueFromPipeline
+
+## Examples
+
+### Example 1
+
+
+
+```powershell
+ConvertTo-OrdinalWord 2
+second
+```
+
+## Outputs
+
+- `string`
diff --git a/docs/ConvertTo-Plural.md b/docs/ConvertTo-Plural.md
new file mode 100644
index 0000000..0b7ca09
--- /dev/null
+++ b/docs/ConvertTo-Plural.md
@@ -0,0 +1,24 @@
+# ConvertTo-Plural
+
+Convert the string to the pural form.
+
+## Parameters
+
+### Parameter Set 1
+
+- `[Object]` **Word** _A string to convert._ Mandatory, ValueFromPipeline
+
+## Examples
+
+### Example 1
+
+
+
+```powershell
+"dog" | ConvertTo-Plural
+dogs
+```
+
+## Outputs
+
+- `string`
diff --git a/docs/ConvertTo-Quantity.md b/docs/ConvertTo-Quantity.md
new file mode 100644
index 0000000..eab8708
--- /dev/null
+++ b/docs/ConvertTo-Quantity.md
@@ -0,0 +1,50 @@
+# ConvertTo-Quantity
+
+Return the correct plurality of a string for a given quantity.
+
+## Parameters
+
+### Parameter Set 1
+
+- `[String]` **String** _A string to convert._ Mandatory, ValueFromPipeline
+- `[Int32]` **Quantity** _A quantity of $String._ Mandatory
+- `[Switch]` **ShowQuantityAs** _The format $Quantity should be displayed in. Options are None, Numeric, and Words. Default is Numeric._
+
+## Examples
+
+### Example 1
+
+
+
+```powershell
+ConvertTo-Quantity -Quantity 2 -String "widget" -ShowQuantityAs "Words"
+two widgets
+```
+### Example 2
+
+
+
+```powershell
+ConvertTo-Quantity -Quantity 1 -String "widget" -ShowQuantityAs "Words"
+one widget
+```
+### Example 3
+
+
+
+```powershell
+ConvertTo-Quantity -Quantity 2 -String "widget"
+2 widgets
+```
+### Example 4
+
+
+
+```powershell
+ConvertTo-Quantity -Quantity 2 -String "widget" -ShowQuantityAs "None"
+widgets
+```
+
+## Outputs
+
+- `string`
diff --git a/docs/ConvertTo-RomanNumeral.md b/docs/ConvertTo-RomanNumeral.md
new file mode 100644
index 0000000..9f7bf34
--- /dev/null
+++ b/docs/ConvertTo-RomanNumeral.md
@@ -0,0 +1,24 @@
+# ConvertTo-RomanNumeral
+
+Convert an Int to a Roman Numeral String.
+
+## Parameters
+
+### Parameter Set 1
+
+- `[Int32[]]` **Number** _One or more Ints to convert._ Mandatory, ValueFromPipeline
+
+## Examples
+
+### Example 1
+
+
+
+```powershell
+ConvertTo-RomanNumeral 12
+XII
+```
+
+## Outputs
+
+- `string`
diff --git a/docs/ConvertTo-Singular.md b/docs/ConvertTo-Singular.md
new file mode 100644
index 0000000..c108c3e
--- /dev/null
+++ b/docs/ConvertTo-Singular.md
@@ -0,0 +1,24 @@
+# ConvertTo-Singular
+
+Convert the string to the singular form.
+
+## Parameters
+
+### Parameter Set 1
+
+- `[String[]]` **Word** _One or more Strings to convert._ Mandatory, ValueFromPipeline
+
+## Examples
+
+### Example 1
+
+
+
+```powershell
+"cats" | ConvertTo-Singular
+cat
+```
+
+## Outputs
+
+- `string`
diff --git a/docs/ConvertTo-Word.md b/docs/ConvertTo-Word.md
new file mode 100644
index 0000000..cc82f4b
--- /dev/null
+++ b/docs/ConvertTo-Word.md
@@ -0,0 +1,24 @@
+# ConvertTo-Word
+
+Convert an Int to a String of one or more words.
+
+## Parameters
+
+### Parameter Set 1
+
+- `[Int32[]]` **Number** _One or more Ints to convert._ Mandatory, ValueFromPipeline
+
+## Examples
+
+### Example 1
+
+
+
+```powershell
+1337 | ConvertTo-Word
+one thousand three hundred and thirty-seven
+```
+
+## Outputs
+
+- `string`
diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 0000000..332e70c
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1,23 @@
+# PowerShellHumanizer
+
+PowerShell Humanizer wraps Humanizer: meets all your .NET needs for manipulating and displaying strings, enums, dates, times, timespans, numbers and quantities
+
+## Commands
+
+- [ConvertFrom-RomanNumeral](ConvertFrom-RomanNumeral.md) _Convert a Roman Numeral String to an Int._
+- [ConvertTo-Casing](ConvertTo-Casing.md) _Format the given string with the given case._
+- [ConvertTo-HumanDate](ConvertTo-HumanDate.md) _Return a string representing time relative a given Date._
+- [ConvertTo-HyphenatedString](ConvertTo-HyphenatedString.md) _Convert a string to a Hyphenated string._
+- [ConvertTo-Ordinal](ConvertTo-Ordinal.md) _Convert an int to an ordinal number._
+- [ConvertTo-OrdinalWord](ConvertTo-OrdinalWord.md) _Convert an int to an ordinal word._
+- [ConvertTo-Plural](ConvertTo-Plural.md) _Convert the string to the pural form._
+- [ConvertTo-Quantity](ConvertTo-Quantity.md) _Return the correct plurality of a string for a given quantity._
+- [ConvertTo-RomanNumeral](ConvertTo-RomanNumeral.md) _Convert an Int to a Roman Numeral String._
+- [ConvertTo-Singular](ConvertTo-Singular.md) _Convert the string to the singular form._
+- [ConvertTo-Word](ConvertTo-Word.md) _Convert an Int to a String of one or more words._
+## Aliases
+
+
+- `ConvertTo-DateWord` -> `ConvertTo-HumanDate`
+- `Kabab` -> `ConvertTo-HyphenatedString`
+- `Pluralize` -> `ConvertTo-Plural`
diff --git a/docs/about_PowerShellHumanizer.md b/docs/about_PowerShellHumanizer.md
new file mode 100644
index 0000000..eb6f857
--- /dev/null
+++ b/docs/about_PowerShellHumanizer.md
@@ -0,0 +1,51 @@
+# Topic
+
+about_PowerShellHumanizer
+
+## Short Description
+
+This PowerShell module wraps [Mehdi Khalili's .NET Humanizer](https://github.com/MehdiK/Humanizer).
+
+## Long Description
+
+Humanizer meets all your .NET needs for manipulating and displaying strings, enums, dates, times, timespans, numbers and quantities [http://humanizr.net](http://humanizr.net)
+
+## String Extension Methods
+
+- `.Humanize()`
+- `.Humanize([Humanizer.LetterCasing]LetterCasing <"AllCaps","Sentence","Title","LowerCase">)`
+- `.Transform([string]Case <"SentenceCase","TitleCase","LowerCase","UpperCase">)`
+- `.ToSentenceCase()`
+- `.ToTitleCase()`
+- `.ToQuantity([int]Count)`
+- `.ToQuantity([int]Count, [Humanizer.ShowQuantityAs]ShowQuantityAs <"Numeric","Word">)`
+- `.Dehumanize()`
+- `.Underscore()`
+- `.FromRoman()`
+- `.Truncate([int]Length)`
+- `.Truncate([int]Length, [string]Truncator <"Characters","Words">)`
+- `.Truncate([int]Length, [string]Truncator <"Characters","Words">, [string]TruncationString)`
+- `.Truncate([int]Length, [string]Truncator <"Characters","Words">, [string]TruncationString, [Humanizer.TruncateFrom]From <"Left","Right">)`
+
+## Integer Extension Methods
+
+- `.Ordinalize()`
+- `.ToWords()`
+- `.ToRoman()`
+
+## Integer Extension Properties
+
+- `.Weeks`
+- `.Days`
+- `.Hours`
+- `.Minutes`
+- `.Seconds`
+- `.Milliseconds`
+
+## Timespan Extension Methods
+
+- `.Humanize([int]Precision)`
+
+## Datetime Extension Methods
+
+- `.Humanize([bool]UTC)`
diff --git a/DemoDateTime.ps1 b/example/DemoDateTime.ps1
similarity index 100%
rename from DemoDateTime.ps1
rename to example/DemoDateTime.ps1
diff --git a/DemoFormats.ps1 b/example/DemoFormats.ps1
similarity index 100%
rename from DemoFormats.ps1
rename to example/DemoFormats.ps1
diff --git a/DemoInts.ps1 b/example/DemoInts.ps1
similarity index 100%
rename from DemoInts.ps1
rename to example/DemoInts.ps1
diff --git a/DemoStrings.ps1 b/example/DemoStrings.ps1
similarity index 100%
rename from DemoStrings.ps1
rename to example/DemoStrings.ps1
diff --git a/src/PowerShellHumanizer.psm1 b/src/PowerShellHumanizer.psm1
new file mode 100644
index 0000000..8c870ac
--- /dev/null
+++ b/src/PowerShellHumanizer.psm1
@@ -0,0 +1,21 @@
+# Load dlls
+if ($PSVersionTable.PSVersion -lt [version]"7.4.6") {
+ Add-Type -Path "$PSScriptRoot/lib/Humanizer.dll"
+}
+
+if ($PSCulture -ne 'en-US') {
+ if (Test-Path "$PSScriptRoot/lib/$PSCulture") {
+ Add-Type -Path "$PSScriptRoot/lib/$PSCulture/Humanizer.resources.dll"
+ } else {
+ Write-Warning "Humanizer doesn't currently support '$PSCulture'."
+ }
+}
+
+if (Get-Module -Name Terminal-Icons -ListAvailable -ErrorAction SilentlyContinue) {
+ Update-FormatData -PrependPath "$PSSCriptRoot/formats/FileInfoIcons.format.ps1xml"
+} else {
+ Update-FormatData -PrependPath "$PSSCriptRoot/formats/FileInfo.format.ps1xml"
+}
+
+Update-FormatData -PrependPath "$PSSCriptRoot/formats/TimeSpan.format.ps1xml"
+
diff --git a/src/dotnet/dependencies.csproj b/src/dotnet/dependencies.csproj
new file mode 100644
index 0000000..d926ab6
--- /dev/null
+++ b/src/dotnet/dependencies.csproj
@@ -0,0 +1,12 @@
+
+
+
+ netstandard2.0
+ 2.14.1
+
+
+
+
+
+
+
diff --git a/en-US/about_PowerShellHumanizer.help.txt b/src/en-US/about_PowerShellHumanizer.help.txt
similarity index 86%
rename from en-US/about_PowerShellHumanizer.help.txt
rename to src/en-US/about_PowerShellHumanizer.help.txt
index cba572e..b71cea1 100644
--- a/en-US/about_PowerShellHumanizer.help.txt
+++ b/src/en-US/about_PowerShellHumanizer.help.txt
@@ -1,60 +1,60 @@
TOPIC
- SampleModule 1.0.0
+ about_PowerShellHumanizer
SHORT DESCRIPTION
This PowerShell module wraps [Mehdi Khalili's .NET Humanizer](https://github.com/MehdiK/Humanizer).
LONG DESCRIPTION
- Humanizer meets all your .NET needs for manipulating and displaying strings, enums,
+ Humanizer meets all your .NET needs for manipulating and displaying strings, enums,
dates, times, timespans, numbers and quantities [http://humanizr.net](http://humanizr.net)
STRING EXTENSION METHODS
.Humanize()
.Humanize([Humanizer.LetterCasing]LetterCasing <"AllCaps","Sentence","Title","LowerCase">)
-
+
.Transform([string]Case <"SentenceCase","TitleCase","LowerCase","UpperCase">)
-
+
.ToSentenceCase()
-
+
.ToTitleCase()
-
+
.ToQuantity([int]Count)
.ToQuantity([int]Count, [Humanizer.ShowQuantityAs]ShowQuantityAs <"Numeric","Word">)
-
+
.Dehumanize()
-
+
.Underscore()
-
+
.FromRoman()
-
+
.Truncate([int]Length)
.Truncate([int]Length, [string]Truncator <"Characters","Words">)
.Truncate([int]Length, [string]Truncator <"Characters","Words">, [string]TruncationString)
- .Truncate([int]Length, [string]Truncator <"Characters","Words">, [string]TruncationString,
+ .Truncate([int]Length, [string]Truncator <"Characters","Words">, [string]TruncationString,
[Humanizer.TruncateFrom]From <"Left","Right">)
INTEGER EXTENSION METHODS
.Ordinalize()
-
+
.ToWords()
-
+
.ToRoman()
-
+
INTEGER EXTENSION PROPERTIES
.Weeks
-
+
.Days
-
+
.Hours
-
+
.Minutes
-
+
.Seconds
-
+
.Milliseconds
-
+
TIMESPAN EXTENSION METHODS
.Humanize([int]Precision)
-
+
DATETIME EXTENSION METHODS
- .Humanize([bool]UTC)
\ No newline at end of file
+ .Humanize([bool]UTC)
\ No newline at end of file
diff --git a/FileInfo.format.ps1xml b/src/formats/FileInfo.format.ps1xml
similarity index 100%
rename from FileInfo.format.ps1xml
rename to src/formats/FileInfo.format.ps1xml
diff --git a/src/formats/FileInfoIcons.format.ps1xml b/src/formats/FileInfoIcons.format.ps1xml
new file mode 100644
index 0000000..48c60c3
--- /dev/null
+++ b/src/formats/FileInfoIcons.format.ps1xml
@@ -0,0 +1,231 @@
+
+
+
+
+
+
+ FileSystemTypes
+
+ System.IO.DirectoryInfo
+ System.IO.FileInfo
+
+
+
+
+
+
+ FileSystemTypes-GroupingFormat
+
+
+
+
+
+ 4
+
+
+
+
+ $_.PSParentPath.Replace("Microsoft.PowerShell.Core\FileSystem::", "")
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ children
+
+ FileSystemTypes
+
+
+ PSParentPath
+ FileSystemTypes-GroupingFormat
+
+
+
+
+
+ 7
+ left
+
+
+
+ 25
+ right
+
+
+
+ 14
+ right
+
+
+
+
+
+
+
+
+
+
+ Mode
+
+
+
+ [Humanizer.DateHumanizeExtensions]::Humanize($_.LastWriteTime,$false)
+
+
+
+
+ if (-not $_.PSIsContainer) { [Humanizer.ByteSizeExtensions]::bytes($_.Length).ToString(0.00)}
+
+
+
+
+ Terminal-Icons\Format-TerminalIcons $_
+
+
+
+
+
+
+
+
+ children
+
+ FileSystemTypes
+
+
+ PSParentPath
+ FileSystemTypes-GroupingFormat
+
+
+
+
+
+ System.IO.FileInfo
+
+
+
+
+
+ Terminal-Icons\Format-TerminalIcons $_
+
+
+
+
+ if (-not $_.PSIsContainer) { [Humanizer.ByteSizeExtensions]::bytes($_.Length).ToString(0.00)}
+
+
+
+
+ [Humanizer.DateHumanizeExtensions]::Humanize($_.CreationTime,$false)
+
+
+
+
+ [Humanizer.DateHumanizeExtensions]::Humanize($_.LastWriteTime,$false)
+
+
+
+
+ [Humanizer.DateHumanizeExtensions]::Humanize($_.LastAccessTime,$false)
+
+
+
+ Mode
+
+
+ LinkType
+
+
+
+
+ Terminal-Icons\Format-TerminalIcons $_
+
+
+
+
+
+
+
+
+
+
+ Terminal-Icons\Format-TerminalIcons $_
+
+
+
+
+ [Humanizer.DateHumanizeExtensions]::Humanize($_.CreationTime,$false)
+
+
+
+
+ [Humanizer.DateHumanizeExtensions]::Humanize($_.LastWriteTime,$false)
+
+
+
+
+ [Humanizer.DateHumanizeExtensions]::Humanize($_.LastAccessTime,$false)
+
+
+
+ Mode
+
+
+ LinkType
+
+
+
+
+ Terminal-Icons\Format-TerminalIcons $_
+
+
+
+
+
+
+
+
+ children
+
+ FileSystemTypes
+
+
+ PSParentPath
+ FileSystemTypes-GroupingFormat
+
+
+
+
+
+
+ Terminal-Icons\Format-TerminalIcons $_
+
+
+
+
+
+ System.IO.DirectoryInfo
+
+
+
+ Terminal-Icons\Format-TerminalIcons $_
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TimeSpan.format.ps1xml b/src/formats/TimeSpan.format.ps1xml
similarity index 100%
rename from TimeSpan.format.ps1xml
rename to src/formats/TimeSpan.format.ps1xml
diff --git a/src/public/ConvertFrom-RomanNumeral.ps1 b/src/public/ConvertFrom-RomanNumeral.ps1
new file mode 100644
index 0000000..1fa8960
--- /dev/null
+++ b/src/public/ConvertFrom-RomanNumeral.ps1
@@ -0,0 +1,25 @@
+<#
+.SYNOPSIS
+ Convert a Roman Numeral String to an Int.
+.DESCRIPTION
+ Convert a Roman Numeral String to an Int.
+.PARAMETER RomanNumeral
+ One or more Roman Numeral Strings to convert.
+.EXAMPLE
+ ConvertFrom-RomanNumeral IV
+ 4
+#>
+function ConvertFrom-RomanNumeral {
+ [CmdletBinding()]
+ [OutputType('int')]
+ param(
+ [Parameter(Mandatory, Position = 0, ValueFromPipeline)]
+ [string[]]$RomanNumeral
+ )
+
+ Process {
+ foreach ($rn in $RomanNumeral) {
+ [Humanizer.RomanNumeralExtensions]::FromRoman($rn)
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/public/ConvertTo-Casing.ps1 b/src/public/ConvertTo-Casing.ps1
new file mode 100644
index 0000000..73c315d
--- /dev/null
+++ b/src/public/ConvertTo-Casing.ps1
@@ -0,0 +1,31 @@
+<#
+.SYNOPSIS
+ Format the given string with the given case.
+.DESCRIPTION
+ Format the given string with the given case. Options are Title, AllCaps, LowerCase, and Sentence.
+.PARAMETER Target
+ One or more strings to format.
+.PARAMETER Case
+ The target casing. Options are Title, AllCaps, LowerCase, and Sentence. Default is Title.
+.EXAMPLE
+ "the powershell gallery" | ConvertTo-Casing -Case Title
+ the Powershell Gallery
+#>
+function ConvertTo-Casing {
+ [CmdletBinding()]
+ [OutputType('string')]
+ param(
+ [Parameter(Mandatory, Position = 0, ValueFromPipeline)]
+ [string[]]$Target,
+
+ [Parameter()]
+ [Humanizer.LetterCasing]
+ $Case = "Title"
+ )
+
+ Process {
+ foreach ($t in $Target) {
+ [Humanizer.CasingExtensions]::ApplyCase($t, $Case)
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/public/ConvertTo-HumanDate.ps1 b/src/public/ConvertTo-HumanDate.ps1
new file mode 100644
index 0000000..0f134de
--- /dev/null
+++ b/src/public/ConvertTo-HumanDate.ps1
@@ -0,0 +1,30 @@
+<#
+.SYNOPSIS
+ Return a string representing time relative a given Date.
+.DESCRIPTION
+ Return a string representing time relative a given Date.
+.PARAMETER Date
+ A DateTime object. Default is Now.
+.EXAMPLE
+ ConvertTo-HumanDate
+ now
+.EXAMPLE
+ ConvertTo-HumanDate (Get-Date).AddDays(-1)
+ yesterday
+.EXAMPLE
+ ConvertTo-HumanDate (Get-Date).AddDays(-12)
+ 12 days ago
+#>
+function ConvertTo-HumanDate {
+ [CmdletBinding()]
+ [Alias('ConvertTo-DateWord')]
+ [OutputType('string')]
+ param(
+ [Parameter(Position = 0, ValueFromPipeline)]
+ [datetime]$Date = (Get-Date)
+ )
+
+ Process {
+ [Humanizer.DateHumanizeExtensions]::Humanize( $Date , $false )
+ }
+}
\ No newline at end of file
diff --git a/src/public/ConvertTo-HyphenatedString.ps1 b/src/public/ConvertTo-HyphenatedString.ps1
new file mode 100644
index 0000000..fb9b499
--- /dev/null
+++ b/src/public/ConvertTo-HyphenatedString.ps1
@@ -0,0 +1,30 @@
+<#
+.SYNOPSIS
+ Convert a string to a Hyphenated string.
+.DESCRIPTION
+ Convert a string to a Hyphenated string.
+.PARAMETER String
+ A string to convert.
+.NOTES
+ This requires the input string to have some word sepration. Either whitespace or Title case.
+.EXAMPLE
+ ConvertTo-HyphenatedString "verb noun"
+ verb-noun
+.EXAMPLE
+ ConvertTo-HyphenatedString PowerShellHumanizer
+ power-shell-humanizer
+#>
+function ConvertTo-HyphenatedString {
+ [CmdletBinding()]
+ [Alias('Kabab')]
+ [OutputType('string')]
+ param(
+ [Parameter(Mandatory, Position = 0, ValueFromPipeline)]
+ [string]
+ $String
+ )
+
+ Process {
+ [Humanizer.InflectorExtensions]::Dasherize($String.Underscore())
+ }
+}
\ No newline at end of file
diff --git a/src/public/ConvertTo-Ordinal.ps1 b/src/public/ConvertTo-Ordinal.ps1
new file mode 100644
index 0000000..7d79c64
--- /dev/null
+++ b/src/public/ConvertTo-Ordinal.ps1
@@ -0,0 +1,23 @@
+<#
+.SYNOPSIS
+ Convert an int to an ordinal number.
+.DESCRIPTION
+ Convert an int to an ordinal number with the correct suffix.
+.PARAMETER Target
+ An int to convert.
+.EXAMPLE
+ ConvertTo-Ordinal 1
+ 1st
+#>
+function ConvertTo-Ordinal {
+ [CmdletBinding()]
+ [OutputType('string')]
+ param(
+ [Parameter(Mandatory, Position = 0, ValueFromPipeline)]
+ [int]$Target
+ )
+
+ Process {
+ [Humanizer.OrdinalizeExtensions]::Ordinalize($Target)
+ }
+}
diff --git a/src/public/ConvertTo-OrdinalWord.ps1 b/src/public/ConvertTo-OrdinalWord.ps1
new file mode 100644
index 0000000..b0a49d3
--- /dev/null
+++ b/src/public/ConvertTo-OrdinalWord.ps1
@@ -0,0 +1,23 @@
+<#
+.SYNOPSIS
+ Convert an int to an ordinal word.
+.DESCRIPTION
+ Convert an int to an ordinal word. First, Second, etc.
+.PARAMETER Target
+ An int to convert.
+.EXAMPLE
+ ConvertTo-OrdinalWord 2
+ second
+#>
+function ConvertTo-OrdinalWord {
+ [CmdletBinding()]
+ [OutputType('string')]
+ param(
+ [Parameter(ValueFromPipeline = $true)]
+ [int]$Target
+ )
+
+ Process {
+ [Humanizer.NumberToWordsExtension]::ToOrdinalWords($Target)
+ }
+}
\ No newline at end of file
diff --git a/src/public/ConvertTo-Plural.ps1 b/src/public/ConvertTo-Plural.ps1
new file mode 100644
index 0000000..8021088
--- /dev/null
+++ b/src/public/ConvertTo-Plural.ps1
@@ -0,0 +1,25 @@
+<#
+.SYNOPSIS
+ Convert the string to the pural form.
+.DESCRIPTION
+ Convert the string to the pural form.
+.PARAMETER Word
+ A string to convert.
+.EXAMPLE
+ "dog" | ConvertTo-Plural
+ dogs
+#>
+function ConvertTo-Plural {
+ [CmdletBinding()]
+ [Alias('Pluralize')]
+ [OutputType('string')]
+ param(
+ [Parameter(Mandatory, Position = 0, ValueFromPipeline)]
+ [Alias('String', 'Target')]
+ $Word
+ )
+
+ Process {
+ [Humanizer.InflectorExtensions]::Pluralize($word)
+ }
+}
\ No newline at end of file
diff --git a/src/public/ConvertTo-Quantity.ps1 b/src/public/ConvertTo-Quantity.ps1
new file mode 100644
index 0000000..fe0b724
--- /dev/null
+++ b/src/public/ConvertTo-Quantity.ps1
@@ -0,0 +1,44 @@
+<#
+.SYNOPSIS
+ Return the correct plurality of a string for a given quantity.
+.DESCRIPTION
+ Return the correct plurality of a string for a given quantity.
+.PARAMETER String
+ A string to convert.
+.PARAMETER Quantity
+ A quantity of $String.
+.PARAMETER ShowQuantityAs
+ The format $Quantity should be displayed in. Options are None, Numeric, and Words. Default is Numeric.
+.EXAMPLE
+ ConvertTo-Quantity -Quantity 2 -String "widget" -ShowQuantityAs "Words"
+ two widgets
+.EXAMPLE
+ ConvertTo-Quantity -Quantity 1 -String "widget" -ShowQuantityAs "Words"
+ one widget
+.EXAMPLE
+ ConvertTo-Quantity -Quantity 2 -String "widget"
+ 2 widgets
+.EXAMPLE
+ ConvertTo-Quantity -Quantity 2 -String "widget" -ShowQuantityAs "None"
+ widgets
+#>
+function ConvertTo-Quantity {
+ [CmdletBinding()]
+ [OutputType('string')]
+ param(
+ [Parameter(Mandatory, Position = 0, ValueFromPipeline)]
+ [string]$String,
+
+ [Parameter(Mandatory, Position = 1)]
+ [Alias('Count')]
+ [int]$Quantity,
+
+ [Parameter(Position = 2)]
+ [Humanizer.ShowQuantityAs]
+ $ShowQuantityAs = [Humanizer.ShowQuantityAs]::Numeric
+ )
+
+ Process {
+ [Humanizer.ToQuantityExtensions]::ToQuantity($String, $Quantity, $ShowQuantityAs)
+ }
+}
\ No newline at end of file
diff --git a/src/public/ConvertTo-RomanNumeral.ps1 b/src/public/ConvertTo-RomanNumeral.ps1
new file mode 100644
index 0000000..4517aa9
--- /dev/null
+++ b/src/public/ConvertTo-RomanNumeral.ps1
@@ -0,0 +1,25 @@
+<#
+.SYNOPSIS
+ Convert an Int to a Roman Numeral String.
+.DESCRIPTION
+ Convert an Int to a Roman Numeral String.
+.PARAMETER Number
+ One or more Ints to convert.
+.EXAMPLE
+ ConvertTo-RomanNumeral 12
+ XII
+#>
+function ConvertTo-RomanNumeral {
+ [CmdletBinding()]
+ [OutputType('string')]
+ param(
+ [Parameter(Mandatory, Position = 0, ValueFromPipeline)]
+ [int[]]$Number
+ )
+
+ Process {
+ foreach ($n in $Number) {
+ [Humanizer.RomanNumeralExtensions]::ToRoman($n)
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/public/ConvertTo-Singular.ps1 b/src/public/ConvertTo-Singular.ps1
new file mode 100644
index 0000000..ed7a247
--- /dev/null
+++ b/src/public/ConvertTo-Singular.ps1
@@ -0,0 +1,27 @@
+<#
+.SYNOPSIS
+ Convert the string to the singular form.
+.DESCRIPTION
+ Convert the string to the singular form.
+.PARAMETER Word
+ One or more Strings to convert.
+.EXAMPLE
+ "cats" | ConvertTo-Singular
+ cat
+#>
+function ConvertTo-Singular {
+ [CmdletBinding()]
+ [OutputType('string')]
+ param(
+ [Parameter(Mandatory, Position = 0, ValueFromPipeline)]
+ [Alias('String', 'Target')]
+ [string[]]
+ $Word
+ )
+
+ Process {
+ foreach ($w in $Word) {
+ [Humanizer.InflectorExtensions]::Singularize($w)
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/public/ConvertTo-Word.ps1 b/src/public/ConvertTo-Word.ps1
new file mode 100644
index 0000000..24eee6f
--- /dev/null
+++ b/src/public/ConvertTo-Word.ps1
@@ -0,0 +1,26 @@
+<#
+.SYNOPSIS
+ Convert an Int to a String of one or more words.
+.DESCRIPTION
+ Convert an Int to a String of one or more words.
+.PARAMETER Number
+ One or more Ints to convert.
+.EXAMPLE
+ 1337 | ConvertTo-Word
+ one thousand three hundred and thirty-seven
+#>
+function ConvertTo-Word {
+ [CmdletBinding()]
+ [OutputType('string')]
+ param(
+ [Parameter(Mandatory, Position = 0, ValueFromPipeline)]
+ [int[]]
+ $Number
+ )
+
+ Process {
+ foreach ($n in $Number) {
+ [Humanizer.NumberToWordsExtension]::ToWords($n)
+ }
+ }
+}
\ No newline at end of file
diff --git a/CmdletInfo.types.ps1xml b/src/types/CmdletInfo.types.ps1xml
similarity index 100%
rename from CmdletInfo.types.ps1xml
rename to src/types/CmdletInfo.types.ps1xml
diff --git a/DateTime.types.ps1xml b/src/types/DateTime.types.ps1xml
similarity index 100%
rename from DateTime.types.ps1xml
rename to src/types/DateTime.types.ps1xml
diff --git a/Int.types.ps1xml b/src/types/Int.types.ps1xml
similarity index 100%
rename from Int.types.ps1xml
rename to src/types/Int.types.ps1xml
diff --git a/String.types.ps1xml b/src/types/String.types.ps1xml
similarity index 100%
rename from String.types.ps1xml
rename to src/types/String.types.ps1xml
diff --git a/TimeSpan.types.ps1xml b/src/types/TimeSpan.types.ps1xml
similarity index 100%
rename from TimeSpan.types.ps1xml
rename to src/types/TimeSpan.types.ps1xml
diff --git a/tests/PowerShellHumanizer.Tests.ps1 b/tests/PowerShellHumanizer.Tests.ps1
new file mode 100644
index 0000000..33045ac
--- /dev/null
+++ b/tests/PowerShellHumanizer.Tests.ps1
@@ -0,0 +1,168 @@
+
+Describe 'Functions' {
+ BeforeAll {
+ Import-Module "$PSScriptRoot/../publish/PowerShellHumanizer" -Force
+ }
+
+ AfterAll {
+ Remove-Module PowerShellHumanizer
+ }
+
+ Context 'Pluralize' {
+ It 'Should convert man to men' {
+ ConvertTo-Plural man | Should -Be 'men'
+ }
+ It 'Should convert an array' {
+ $output = Write-Output person man woman | ConvertTo-Plural
+ $output[0] | Should -Be 'people'
+ $output[1] | Should -Be 'men'
+ $output[2] | Should -Be 'women'
+ }
+ }
+
+ Context 'Singularize' {
+ It 'Should convert to ' -ForEach @(
+ @{given = 'people'; expect = 'person' }
+ @{given = 'men'; expect = 'man' }
+ @{given = 'women'; expect = 'woman' }
+ @{given = 'geese'; expect = 'goose' }
+ @{given = 'indicies'; expect = 'indicy' }
+ @{given = 'oxen'; expect = 'ox' }
+ @{given = 'knives'; expect = 'knife' }
+ ) {
+ $result = $given | ConvertTo-Singular
+ $result | Should -Be $expect
+ }
+
+ }
+
+ Context 'Hyphenate' {
+ It 'Should convert to a hyphenated string' {
+
+ "Continuing To Make Powershell A Bit More Human" |
+ ConvertTo-HyphenatedString |
+ Should -Be 'continuing-to-make-powershell-a-bit-more-human'
+ }
+
+ }
+
+ Context 'Number to ordinal words' {
+ It 'Should convert to words' {
+ ConvertTo-OrdinalWord 121 | Should -Be 'hundred and twenty-first'
+ }
+ It 'Should convert a range to words' {
+ $output = 120..122 | ConvertTo-OrdinalWord
+ $output[0] | Should -Be 'hundred and twentieth'
+ $output[1] | Should -Be 'hundred and twenty-first'
+ $output[2] | Should -Be 'hundred and twenty-second'
+ }
+ }
+
+ Context 'Quantity' {
+ It 'Should return "" with -quantity -string ""' -ForEach @(
+ @{quant = 1; string = 'widgets'; expected = 'one widget' }
+ @{quant = 2; string = 'widgets'; expected = 'two widgets' }
+ ) {
+ $result = ConvertTo-Quantity -quantity $quant -string $string -showQuantityAs "Words"
+ $result | Should -Be $expected
+ }
+ }
+}
+
+Describe 'Type Extension Methods' {
+
+ Context 'Strings' {
+
+ It 'Should transform to Upper Case' {
+ 'then add nodes under it.'.Transform("UpperCase") | Should -Be 'THEN ADD NODES UNDER IT.'
+ }
+ It 'Should convert to Title Case' {
+ 'then add nodes under it.'.ToTitleCase() | Should -Be 'Then Add Nodes Under It.'
+ }
+ It 'Should convert from Title Case' {
+ 'FromTitleCase'.Underscore() | Should -Be 'from_title_case'
+ }
+ It 'Should truncate words' {
+ 'then add nodes under it.'.Truncate(3, "Words") | Should -Match 'then add nodes\W$'
+ }
+ It 'Should truncate characters' {
+ 'then add nodes under it.'.Truncate(3, "Characters") | Should -Match 'th\W$'
+ }
+ It 'Should truncate with optional character' {
+ 'then add nodes under it.'.Truncate(7, "Characters", '-') | Should -Be 'then ad-'
+ }
+ It 'Should Dehumanize' {
+ 'then add nodes under it.'.Dehumanize() | Should -Be 'ThenAddNodesUnderIt'
+ }
+ It 'Should provide quanity: # word' {
+ 'string'.ToQuantity(50) | Should -Be '50 strings'
+ }
+ It 'Should provide quantity: words' {
+ 'string'.ToQuantity(50, "Words") | Should -Be 'fifty strings'
+ }
+ It 'Should convert Year to roman numerals' {
+ (Get-Date -Year 2024 ).Year.ToRoman() | Should -Be 'MMXXIV'
+ }
+ }
+
+ Context 'Integers' {
+ It 'Should ordanalize' {
+ (3).Ordinalize() | Should -Be '3rd'
+ }
+ It 'Should convert to word' {
+ (3).ToWords() | Should -Be 'three'
+ }
+ It 'Should do math in weeks' {
+ (Get-Date 2/13/2016) + (3).Weeks -eq (Get-Date 3/5/2016) | Should -Be $true
+ }
+ }
+
+ Context 'TimeSpan' {
+ BeforeAll {
+ $past = (Get-Date 2/13/2016).AddMinutes(-1).AddSeconds(-20)
+ $time = (Get-Date 2/13/2016) - $past
+ }
+
+ It 'Should simplify TimeSpan objects' {
+ $time.Humanize() | Should -Be '1 minute'
+ }
+ It 'Should simplify TimeSpan objects with selectable precision' {
+ $time.Humanize(2) | Should -Be '1 minute, 20 seconds'
+ }
+ }
+
+ Context 'DateTime' {
+ It 'Should display Now as now when UTC is false' {
+ (Get-Date).Humanize() | Should -Be 'now'
+ }
+ It 'Should display Now as hours ago when UTC is true' -Skip:($env:CI -eq 'True') {
+ (Get-Date).Humanize($true) | Should -Match 'hours'
+ }
+ }
+}
+
+Describe 'Custom Formats' {
+
+ Context 'TimeSpan' {
+ It 'Should display 1 hour' {
+ (([TimeSpan]::new(1, 0, 0)) | Out-String).trim() | Should -Be '1 hour'
+ }
+ }
+
+ Context 'FileSystem' {
+ BeforeAll {
+
+ $listAlphaLower = for ($i = 97; $i -le 122 ; $i++) { [char]$i }
+ $listAlphaUpper = for ($i = 65; $i -le 90 ; $i++) { [char]$i }
+ $listNumber = for ($i = 0; $i -le 9 ; $i++) { $i }
+ $charset = $listAlphaLower + $listAlphaUpper + $listNumber
+
+ $content = (1..(1kb)).ForEach({ Get-Random $charset })
+ -join $content | Set-Content TestDrive:\testfile.txt
+ $testData = Get-Item TestDrive:\testfile.txt | Out-String
+ }
+ It 'Should display 1 KB' {
+ $testData | Should -Match '1 KB .? {0,2}testfile\.txt'
+ }
+ }
+}
\ No newline at end of file
diff --git a/version.json b/version.json
new file mode 100644
index 0000000..8eb8b7c
--- /dev/null
+++ b/version.json
@@ -0,0 +1,9 @@
+{
+ "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/main/src/NerdBank.GitVersioning/version.schema.json",
+ "version": "4.0",
+ "cloudBuild": {
+ "buildNumber": {
+ "enabled": true
+ }
+ }
+}
\ No newline at end of file