jdhitsolutions / PSScriptTools

:wrench: :hammer: A set of PowerShell functions you might use to enhance your own functions and scripts or to facilitate working in the console. Most should work in both Windows PowerShell and PowerShell 7, even cross-platform. Any operating system limitations should be handled on a per command basis. The Samples folder contains demonstration script files

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

ConvertTo-Markdown -AsTable processing of some characters seems to prematurely end the table

mdcaddic opened this issue · comments

Describe the bug
A clear and concise description of what the bug is.

To Reproduce
Steps to reproduce the behavior:

  1. Connect to ExchangeOnline
  2. $rules = Get-TransportRule
  3. $rules | Select-Object Name, Priority, Description | ConvertTo-Markdown -AsTable | Out-File -Encoding utf8 rules.md
  4. View output in vscode

Expected behavior
Complete table.

Screenshots
If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

  • Windows 10
  • Module Version 2.32.0
  • 5.1.19041.546

Additional context
This is the output from the convertto-markdown

Name Priority Description
Block executable content 0 If the message:
includes an attachment with executable content

Take the following actions:
reject the message and include the explanation 'The email contains an attachment that is not allowed' with the status code: '5.7.1'
|
| Block External Forwarding | 1 | If the message:
Is sent to 'Outside the organization'
and Is message type 'Auto-forward'
and Is received from 'Inside the organization'
Take the following actions:
reject the message and include the explanation 'AutoForward to External Recipients is not allowed' with the status code: '5.7.1'
|
| encrypt_external_emails | 2 | If the message:
Is sent to 'Outside the organization'
Take the following actions:
rights protect message with RMS template: 'Encrypt'
|

Can you export a sample rule using Export-Clixml and copy and paste the XML here? I can then import that rule and test. But I'm guessing there is an issue with the apostrophes and/or colons.

You might need to modify the Width. The default is 80. Try ConvertTo-Markdown with something like -width 150.

I think you need to adjust the output of the command before you convert and/or extend the width. I think that's why you are seeing things cut off. I had to make a number of adjustments to get this to work:

get-netfirewallrule | select -first 10 -Property Name,description,enabled,group | Format-List -Group Name -property Description,Enabled,Group | ConvertTo-Markdown -Title "FireWall Rules" -PreContent "This is from the localhost" -width 100 | out-file c:\work\fw.md -Encoding utf8

I was able to re-construct your problem. The issue is that the description has returns. And this is only an issue when creating a table I may have to see about changing

If the message:
    Is sent to 'Outside the organization'
    And Is message type 'Auto-forward'
    And Is received from 'Inside the organization'
    Take the following actions:
    reject the message and include the explanation 'AutoForward to External Recipients is not allowed' with the status code: '5.7.1'

to this

If the message:\n    Is sent to 'Outside the organization'\n    And Is message type 'Auto-forward'\n    And Is received from 'Inside the organization'\n    Take the following actions:\n    reject the message and include the explanation 'AutoForward to External Recipients is not allowed' with the status code: '5.7.1'
```. 

I might be on to something. If I replace line returns with <br> this seems to work.

# My result

| Name | Priority | Description |
| ---- | -------- | ----------- |
| block executable content | 0 | If the message:includes an attachment with executable content Take the following actions:reject the message and include the explanation 'The email contains an attachment that is not allowed' with the status code: '5.7.1' |
| block external forwarding | 1 | If the message:<br>    Is sent to 'Outside the organization'<br>    And Is message type 'Auto-forward'<br>    And Is received from 'Inside the organization'<br>    Take the following actions:<br>    reject the message and include the explanation 'AutoForward to External Recipients is not allowed' with the status code: '5.7.1' |

My result

Name Priority Description
block executable content 0 If the message:includes an attachment with executable content Take the following actions:reject the message and include the explanation 'The email contains an attachment that is not allowed' with the status code: '5.7.1'
block external forwarding 1 If the message:
Is sent to 'Outside the organization'
And Is message type 'Auto-forward'
And Is received from 'Inside the organization'
Take the following actions:
reject the message and include the explanation 'AutoForward to External Recipients is not allowed' with the status code: '5.7.1'

The first row is my test with the line breaks removed.

I think I have this working. Copy and save this version of the function. Then test it with your data and let me know. The function has a different name to avoid conflicts.

Function ConvertTo-MDTest {

[cmdletbinding()]
    [outputtype([string[]])]
    [alias('ctm')]

    Param(
        [Parameter(Position = 0, ValueFromPipeline)]
        [object]$Inputobject,
        [Parameter()]
        [string]$Title,
        [string[]]$PreContent,
        [string[]]$PostContent,
        [ValidateScript( {$_ -ge 10})]
        [int]$Width = 80,
        #display results as a markdown table
        [switch]$AsTable
    )

    Begin {
        Write-Verbose "[BEGIN  ] Starting $($myinvocation.MyCommand)"
        #initialize an array to hold incoming data
        $data = @()

        #initialize an empty here string for markdown text
        $Text = @"

"@
        If ($title) {
            Write-Verbose "[BEGIN  ] Adding Title: $Title"
            $Text += "# $Title`n`n"
        }
        If ($precontent) {
            Write-Verbose "[BEGIN  ] Adding Precontent"
            $Text += $precontent
            $text += "`n`n"
        }

    } #begin
    Process {
        #add incoming objects to data array
        Write-Verbose "[PROCESS] Adding processed object"
        $data += $Inputobject

    } #process
    End {
        #add the data to the text
        if ($data) {
            if ($AsTable) {
                Write-Verbose "[END    ] Formatting as a table"
                $names = $data[0].psobject.Properties.name
                $head = "| $($names -join " | ") |"
                $text += $head
                $text += "`n"

                $bars = "| $(($names -replace '.','-') -join " | ") |"

                $text += $bars
                $text += "`n"

                foreach ($item in $data) {
                    $line = "| "
                    $values = @()
                    for ($i = 0; $i -lt $names.count; $i++) {
                        
                        #if an item value contains return and new line replace them with <br> Issue #97
                        if ($item.($names[$i]) -match "`n") {
                            Write-Verbose "[END    ] Replacing line returns for property $($names[$i])"
                            [string]$val = $($item.($names[$i])).replace("`r`n","<br>") -join ""
                            Write-Verbose $val
                        }
                        else {
                            [string]$val = $item.($names[$i])
                        }
                        
                        $values += $val
                    }
                    $line += $values -join " | "
                    $line += " |"
                    $text += $line
                    $text += "`r"
                }
            }
            else {
                #convert data to strings and trim each line
                Write-Verbose "[END    ] Converting data to strings"
                [string]$trimmed = (($data | Out-String -Width $width).split("`n")).ForEach({ "$($_.trim())`n" })
                Write-Verbose "[END    ] Adding to markdown"
                $clean = $($trimmed.trimend())
                $text += @"
``````text
$clean

"@

        } #else as text
    } #if $data
    If ($postcontent) {
        Write-Verbose "[END    ] Adding postcontent"
        $text += "`n"
        $text += $postcontent
    }

    #write the markdown to the pipeline
    $text.TrimEnd()
    Write-Verbose "[END    ] Ending $($myinvocation.MyCommand)"
} #end

}

Haven't forgotten. Seems to work to produce standard markdown but that doesn't convert neatly using pandoc. I'll keep working on it. Converting the new markdown using pandoc results in tables with a single row

I got your issues mixed up. From all of my testing this works. Although, if you want to upload a clixml file as I suggested earlier I can test with that. LIke the caption issue, you may need to come up with your own version of this function too create Pandoc-compatible output.

A new version of this command has been released in v2.33.0 of the module.