PSParseHTML.psm1

Function ConvertFrom-HtmlTable {
    [cmdletbinding()]
    param ([Parameter(Mandatory = $true)]
        [string]$Content)
    Begin { $HTMLParser = [AngleSharp.Html.Parser.HtmlParser]::new() }
    Process {
        $ParsedDocument = $HTMLParser.ParseDocument($content)
        [Array] $Tables = $ParsedDocument.GetElementsByTagName('table')
        :table foreach ($table in $tables) {
            $headers = $table.Rows[0].Cells.TextContent.Trim() | Where-Object { $_ }
            if ($null -ne $headers) {
                [Array] $output = foreach ($row in $table.Rows | Select-Object -Skip 0) {
                    if (@($row.Cells).count -ne $headers.count) {
                        Write-Verbose 'Unsupported table.'
                        Continue table
                    }
                    $obj = [ordered]@{ }
                    for ($x = 0; $x -lt $headers.count; $x++) { $obj["$($headers[$x])"] = $row.Cells[$x].TextContent.Trim() }
                    [PSCustomObject] $obj
                }
                if ($output.count -ge 1) { @(, $output) } else { Write-Verbose 'Table has no rows' }
            }
        }
    }
    End { }
}
function Convert-HTMLToText {
    [CmdletBinding()]
    param([string] $File,
        [string] $OutputFile,
        [string] $Content)
    if ($File) {
        if (Test-Path -LiteralPath $File) { $Content = [IO.File]::ReadAllText($File) } else {
            Write-Warning "Convert-HTMLToText - File doesn't exists"
            return
        }
    } elseif ($Content) { } else {
        Write-Warning 'Convert-HTMLToText - No choice file or Content. Termninated.'
        return
    }
    $Output = Convert-InternalHTMLToText -Content $Content
    if ($OutputFile) { [IO.File]::WriteAllText($OutputFile, $Output) } else { $Output }
}
function Convert-InternalHTMLToText {
    [CmdletBinding()]
    param([string] $Content)
    $Output = [NUglify.Uglify]::HtmlToText($Content)
    if ($Output.HasErrors) { Write-Warning "Convert-HTMLToText -Errors: $($Output.Errors)" }
    $Output.Code
}
function Format-CSS {
    [CmdletBinding()]
    param([string] $File,
        [string] $OutputFile,
        [string] $Content)
    if ($File) {
        if (Test-Path -LiteralPath $File) { $Content = [IO.File]::ReadAllText($File) } else {
            Write-Warning "Format-CSS - File doesn't exists"
            return
        }
    } elseif ($Content) { } else {
        Write-Warning 'Format-CSS - No choice file or Content. Termninated.'
        return
    }
    $Output = Format-InternalCSS -Content $Content
    if ($OutputFile) { [IO.File]::WriteAllText($OutputFile, $Output) } else { $Output }
}
function Format-HTML {
    [CmdletBinding()]
    param([string] $File,
        [string] $OutputFile,
        [string] $Content)
    if ($File) {
        if (Test-Path -LiteralPath $File) { $Content = [IO.File]::ReadAllText($File) } else {
            Write-Warning "Format-HTML - File doesn't exists"
            return
        }
    } elseif ($Content) { } else {
        Write-Warning 'Format-HTML - No choice file or Content. Termninated.'
        return
    }
    $Output = Format-InternalHTML -Content $Content
    if ($OutputFile) { [IO.File]::WriteAllText($OutputFile, $Output) } else { $Output }
}
function Format-InternalCSS {
    [CmdletBinding()]
    param([string] $Content)
    $CssParser = [AngleSharp.Css.Parser.CssParser]::new()
    $ParsedDocument = $CssParser.ParseStyleSheet($Content)
    $StringWriter = [System.IO.StringWriter]::new()
    $PrettyMarkupFormatter = [AngleSharp.Css.CssStyleFormatter]::new()
    $ParsedDocument.ToCss($StringWriter, $PrettyMarkupFormatter)
    $StringWriter.ToString()
}
function Format-InternalHTML {
    [CmdletBinding()]
    param([string] $Content)
    $HTMLParser = [AngleSharp.Html.Parser.HtmlParser]::new()
    $ParsedDocument = $HTMLParser.ParseDocument($Content)
    $StringWriter = [System.IO.StringWriter]::new()
    $PrettyMarkupFormatter = [AngleSharp.Html.PrettyMarkupFormatter]::new()
    $ParsedDocument.ToHtml($StringWriter, $PrettyMarkupFormatter)
    $StringWriter.ToString()
}
function Format-InternalJS {
    [CmdletBinding()]
    param([string] $Content,
        [int] $IndentSize = 4,
        [string] $IndentChar = ' ',
        [bool] $IndentWithTabs = $false,
        [bool] $PreserveNewlines = $true,
        [double] $MaxPreserveNewlines = 10.0,
        [bool] $JslintHappy = $false,
        [Jsbeautifier.BraceStyle] $BraceStyle = [Jsbeautifier.BraceStyle]::Collapse,
        [bool] $KeepArrayIndentation = $false,
        [bool] $KeepFunctionIndentation = $false,
        [bool] $EvalCode = $false,
        [int] $WrapLineLength = 0,
        [bool] $BreakChainedMethods = $false)
    $Jsbeautifier = [Jsbeautifier.Beautifier]::new()
    $Jsbeautifier.Opts.IndentSize = $IndentSize
    $Jsbeautifier.Opts.IndentChar = $IndentChar
    $Jsbeautifier.Opts.IndentWithTabs = $IndentWithTabs
    $Jsbeautifier.Opts.PreserveNewlines = $PreserveNewlines
    $Jsbeautifier.Opts.MaxPreserveNewlines = $MaxPreserveNewlines
    $Jsbeautifier.Opts.JslintHappy = $JslintHappy
    $Jsbeautifier.Opts.BraceStyle = $BraceStyle
    $Jsbeautifier.Opts.KeepArrayIndentation = $KeepArrayIndentation
    $Jsbeautifier.Opts.KeepFunctionIndentation = $KeepFunctionIndentation
    $Jsbeautifier.Opts.EvalCode = $EvalCode
    $Jsbeautifier.Opts.WrapLineLength = $WrapLineLength
    $Jsbeautifier.Opts.BreakChainedMethods = $BreakChainedMethods
    $FormattedJS = $Jsbeautifier.Beautify($Content)
    $FormattedJS
}
function Format-JavaScript {
    [alias('Format-JS')]
    [CmdletBinding()]
    param([string] $File,
        [string] $OutputFile,
        [alias('FileContent')][string] $Content)
    if ($File) {
        if (Test-Path -LiteralPath $File) { $Content = [IO.File]::ReadAllText($File) } else {
            Write-Warning "Format-JavaScript - File doesn't exists"
            return
        }
    } elseif ($Content) { } else {
        Write-Warning 'Format-JavaScript - No choice file or Content. Termninated.'
        return
    }
    [int] $IndentSize = 4
    [string] $IndentChar = ' '
    [bool] $IndentWithTabs = $false
    [bool] $PreserveNewlines = $true
    [double] $MaxPreserveNewlines = 10.0
    [bool] $JslintHappy = $false
    [Jsbeautifier.BraceStyle] $BraceStyle = [Jsbeautifier.BraceStyle]::Collapse
    [bool] $KeepArrayIndentation = $false
    [bool] $KeepFunctionIndentation = $false
    [bool] $EvalCode = $false
    [int] $WrapLineLength = 0
    [bool] $BreakChainedMethods = $false
    $SplatJS = @{IndentSize = $IndentSize
        IndentChar = $IndentChar
        IndentWithTabs = $IndentWithTabs
        PreserveNewlines = $PreserveNewlines
        MaxPreserveNewlines = $MaxPreserveNewlines
        JslintHappy = $JslintHappy
        BraceStyle = $BraceStyle
        KeepArrayIndentation = $KeepArrayIndentation
        KeepFunctionIndentation = $KeepFunctionIndentation
        EvalCode = $EvalCode
        WrapLineLength = $WrapLineLength
        BreakChainedMethods = $BreakChainedMethods
    }
    $Output = Format-InternalJS -Content $Content @SplatJS
    if ($OutputFile) { [IO.File]::WriteAllText($OutputFile, $Output) } else { $Output }
}
function Optimize-CSS {
    [CmdletBinding()]
    param([string] $File,
        [string] $OutputFile,
        [string] $Content)
    if ($File) {
        if (Test-Path -LiteralPath $File) { $Content = [IO.File]::ReadAllText($File) } else {
            Write-Warning "Optimize-CSS - File doesn't exists"
            return
        }
    } elseif ($Content) { } else {
        Write-Warning 'Optimize-CSS - No choice file or Content. Termninated.'
        return
    }
    $Output = Optimize-InternalCSS -Content $Content
    if ($OutputFile) { [IO.File]::WriteAllText($OutputFile, $Output) } else { $Output }
}
function Optimize-HTML {
    [CmdletBinding()]
    param([string] $File,
        [string] $OutputFile,
        [string] $Content)
    if ($File) {
        if (Test-Path -LiteralPath $File) { $Content = [IO.File]::ReadAllText($File) } else {
            Write-Warning "Optimize-HTML - File doesn't exists"
            return
        }
    } elseif ($Content) { } else {
        Write-Warning 'Optimize-HTML - No choice file or Content. Termninated.'
        return
    }
    [bool] $ShouldKeepAttributeQuotes = $true
    [bool] $ShouldKeepComments = $true
    [bool] $ShouldKeepEmptyAttributes = $true
    [bool] $ShouldKeepImpliedEndTag = $true
    [bool] $ShouldKeepStandardElements = $true
    $Output = Optimize-InternalUglifyHTML -Content $Content
    if ($OutputFile) { [IO.File]::WriteAllText($OutputFile, $Output) } else { $Output }
}
function Optimize-InternalCSS {
    [CmdletBinding()]
    param([string] $Content)
    $CSSParser = [AngleSharp.Css.Parser.CssParser]::new()
    $ParsedDocument = $CSSParser.ParseStyleSheet($Content)
    $StringWriter = [System.IO.StringWriter]::new()
    $PrettyMarkupFormatter = [AngleSharp.Css.MinifyStyleFormatter]::new()
    $ParsedDocument.ToCss($StringWriter, $PrettyMarkupFormatter)
    $StringWriter.ToString()
}
function Optimize-InternalUglifyCSS {
    [CmdletBinding()]
    param([string] $Content)
    [NUglify.Uglify]::Css($Content).Code
}
function Optimize-InternalUglifyHTML {
    [CmdletBinding()]
    param([string] $Content)
    $Settings = [NUglify.Html.HtmlSettings]::new()
    $Settings.RemoveOptionalTags = $false
    [NUglify.Uglify]::Html($HTMLContentFormatted, $Settings).Code
}
function Optimize-InternalUglifyJS {
    [CmdletBinding()]
    param([string] $Content)
    [NUglify.Uglify]::Js($Content).Code
}
function Optimize-JavaScript {
    [CmdletBinding()]
    param([string] $File,
        [string] $OutputFile,
        [string] $Content)
    if ($File) {
        if (Test-Path -LiteralPath $File) { $Content = [IO.File]::ReadAllText($File) } else {
            Write-Warning "Optimize-JavaScript - File doesn't exists"
            return
        }
    } elseif ($Content) { } else {
        Write-Warning 'Optimize-JavaScript - No choice file or Content. Termninated.'
        return
    }
    $Output = Optimize-InternalUglifyJS -Content $Content
    if ($OutputFile) { [IO.File]::WriteAllText($OutputFile, $Output) } else { $Output }
}
if ($PSEdition -eq 'Core') {
    Add-Type -Path $PSScriptRoot\Lib\Core\AngleSharp.Css.dll
    Add-Type -Path $PSScriptRoot\Lib\Core\AngleSharp.dll
    Add-Type -Path $PSScriptRoot\Lib\Core\jint.dll
    Add-Type -Path $PSScriptRoot\Lib\Core\Jsbeautifier.dll
    Add-Type -Path $PSScriptRoot\Lib\Core\NUglify.dll
} else {
    Add-Type -Path $PSScriptRoot\Lib\Default\AngleSharp.Css.dll
    Add-Type -Path $PSScriptRoot\Lib\Default\AngleSharp.dll
    Add-Type -Path $PSScriptRoot\Lib\Default\jint.dll
    Add-Type -Path $PSScriptRoot\Lib\Default\Jsbeautifier.dll
    Add-Type -Path $PSScriptRoot\Lib\Default\NUglify.dll
    Add-Type -Path $PSScriptRoot\Lib\Default\System.Text.Encoding.CodePages.dll
}
Export-ModuleMember -Function @('ConvertFrom-HtmlTable', 'Convert-HTMLToText', 'Format-CSS', 'Format-HTML', 'Format-JavaScript', 'Optimize-CSS', 'Optimize-HTML', 'Optimize-JavaScript') -Alias @('Format-JS')