Private/CaseConversion.ps1

<#
.SYNOPSIS
    Internal helpers shared by ConvertTo-CamelCase, ConvertTo-PascalCase, ConvertTo-SnakeCase
    and ConvertTo-KebabCase.

.NOTES
    Private helpers for the tcs.core module. Unicode categories (\p{Lu}, \p{Ll}, \p{Nd}) are
    used so that letters outside A-Z, such as 'Ä' or 'É', split words too.
#>


# Word boundaries: spaces, underscores and hyphens; lower -> upper ('helloWorld');
# the last capital of an acronym before a capitalised word ('XMLHttp'); and digit -> upper
# ('Version2Update', 'user2FA'). Digits stay with the word before them ('utf8', 'Version2').
$script:CaseWordPattern = '[\s_\-]+|(?<=\p{Ll})(?=\p{Lu})|(?<=\p{Lu})(?=\p{Lu}\p{Ll})|(?<=\p{Nd})(?=\p{Lu})'

function Split-CaseWord {
    <#
    .SYNOPSIS
        Splits an identifier or phrase into words.
    #>

    [CmdletBinding()]
    [OutputType([string[]])]
    param(
        [AllowEmptyString()]
        [string]$Value
    )

    # @() keeps a single word as an array instead of a string
    return , @([regex]::Split($Value, $script:CaseWordPattern) | Where-Object { $_ -ne '' })
}

function Test-CaseAcronym {
    <#
    .SYNOPSIS
        Returns $true for an all-capitals word with at least two capital letters, such as
        'XML', 'FA' or 'HTML5'.
    #>

    [CmdletBinding()]
    [OutputType([bool])]
    param(
        [AllowEmptyString()]
        [string]$Word
    )

    return ($Word -cmatch '^[\p{Lu}\p{Nd}]+$' -and ([regex]::Matches($Word, '\p{Lu}')).Count -ge 2)
}

function ConvertTo-CapitalisedWord {
    <#
    .SYNOPSIS
        Capitalises a word ('hello' -> 'Hello'), or keeps an acronym as it is with -PreserveAcronyms.
    #>

    [CmdletBinding()]
    [OutputType([string])]
    param(
        [AllowEmptyString()]
        [string]$Word,

        [switch]$PreserveAcronyms
    )

    if ($Word.Length -eq 0) {
        return $Word
    }
    if ($PreserveAcronyms -and (Test-CaseAcronym -Word $Word)) {
        return $Word
    }
    return $Word.Substring(0, 1).ToUpperInvariant() + $Word.Substring(1).ToLowerInvariant()
}