Skip to content

PowerShell Format-Table HTML parser splits wide values across columns #2

@eosfor

Description

@eosfor

Summary

The PowerShell HTML table renderer can split a value across adjacent columns when rendering explicit Format-Table output.

Repro

In a PowerShell cell:

Get-Module PSQuickGraph, PSGraphView |
    Select-Object Name, Version, ModuleBase |
    Format-Table -AutoSize

The raw Out-String table is valid:

Name         Version ModuleBase
----         ------- ----------
PSGraphView  0.1.0   /Users/...
PSQuickGraph 2.5.0   /Users/...

But the rendered HTML table can show:

Name      Version
PSGraphV  iew  0.1.0
PSQuickG  raph 2.5.0

This was observed in the local sample notebook:

samples/Notebooks/powershell/micrograd/micrograd-ps.verso

Suspected Cause

RunspaceManager.Invoke detects PowerShell format objects, renders them with Out-String -Width 200, then ParseTextTableToHtml converts the fixed-width text table to HTML.

ParseTextTableToHtml infers extraction bounds from dash groups in the separator line:

Name         Version ModuleBase
----         ------- ----------

The dash group under Name is only as wide as the header text, not as wide as values like PSGraphView. The midpoint-based boundary then falls inside the value and splits it across columns.

Format-Table Metadata

Format-Table does not output ordinary table text directly. It emits PowerShell internal formatting records, for example:

FormatStartData
GroupStartData
FormatEntryData
FormatEntryData
GroupEndData
FormatEndData

The useful table metadata is still present in these objects:

  • FormatStartData.shapeInfo is a TableHeaderInfo.
  • TableHeaderInfo.tableColumnInfoList contains column metadata:
    • propertyName = Name
    • propertyName = Version
    • propertyName = ModuleBase
    • plus label, alignment, and width fields.
  • Each FormatEntryData.formatEntryInfo is a TableRowEntry.
  • TableRowEntry.formatPropertyFieldList contains row values:
    • propertyValue = PSGraphView
    • propertyValue = 0.1.0
    • propertyValue = /Users/.../PSGraphView

These types are internal PowerShell implementation types under:

Microsoft.PowerShell.Commands.Internal.Format

So they should not be referenced as public compile-time API, but they can be inspected by reflection if we want to render explicit Format-Table output structurally.

Preferred Fix

Preferred approach: render Format-Table directly from PowerShell format object metadata instead of rendering through Out-String and parsing fixed-width text.

Implementation direction:

  • Detect FormatStartData with table shape metadata (TableHeaderInfo).
  • Reflect shapeInfo.tableColumnInfoList to get column labels/property names/alignment.
  • Reflect each FormatEntryData.formatEntryInfo.formatPropertyFieldList to get row cell values.
  • Render those rows as HTML table cells.
  • If the format records are not a simple table shape, fall back to Out-String rendered as <pre>.

This avoids guessing column boundaries from dashes and preserves values that are wider than the header text.

Branch Strategy

Make the clean fix branch from pr/powershell-host-streaming, not from pr/powershell-net10.

Prepared branches in this fork:

fix/powershell-format-table-rendering        # clean code-fix branch from pr/powershell-host-streaming, currently at cce2332
work/f5-upstream-pr48-net10-notebooks        # validation branch with PR48 + .NET 10 + notebooks, currently at 4aa692c

Recommended agent workflow:

  1. Implement the renderer fix on fix/powershell-format-table-rendering.
  2. Keep the branch clean: code and focused tests only; do not merge notebook commits into this branch.
  3. After the fix is ready, merge or cherry-pick the fix commit into work/f5-upstream-pr48-net10-notebooks.
  4. Use work/f5-upstream-pr48-net10-notebooks only for local F5/notebook validation against the .NET 10 integration setup.
  5. If the agent can only work from the validation branch, make the code fix there, then create the final upstreamable branch by cherry-picking only the code/test commits back onto fix/powershell-format-table-rendering.

Reason:

Workaround

Avoid explicit Format-Table and let the kernel use the object-to-HTML path:

Get-Module PSQuickGraph, PSGraphView |
    Select-Object Name, Version, ModuleBase

Alternative Fixes

  • Compute column boundaries from header start positions rather than dash group widths. This is better than the current midpoint heuristic, but still a text parsing heuristic.
  • Render explicit Format-Table output as <pre> instead of trying to parse fixed-width text into HTML. This is safe, but loses structured HTML table rendering.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions