Skip to content

Optional table column-width control (emit <colgroup> in Confluence storage output) #804

Description

@cacack

Summary

mark renders Markdown tables to a bare <table>, so Confluence auto-sizes every column to roughly equal width. There's no way to influence column widths without hand-writing a raw HTML table. This proposes an opt-in way to set widths while keeping the source as Markdown.

This revisits #188, which predates the goldmark switch and closed with "wrap it in a <div> / write raw HTML." A <div> sizes the whole table, not columns, and raw HTML sacrifices Markdown readability (and the plain-Markdown render for those of us publishing the same source to GitLab/GitHub too).

Current behavior

| Field | Value |
|-------|-------|
| Status | Draft |

mark --compile-only (v15.3.0) emits a bare table with no width hints, so Field/Value renders ~50/50 even though the label column wants to be narrow:

compiled storage output
<table>
<thead>
<tr>
<th>Field</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr>
<td>Status</td>
<td>Draft</td>
</tr>
</tbody>
</table>

Why this isn't a goldmark gap

  • goldmark's table extension does alignment only (TableCellAlignMethod). Column width isn't in the CommonMark/GFM table spec, so it won't come from upstream.
  • mark has custom renderers for headings, links, images, code, admonitions, etc. — but none for tables, so they fall through to goldmark's stock output. The implementation locus is mark's renderer, not goldmark.

Confluence storage does support per-column widths via a colgroup, which mark passes through today when hand-written:

colgroup mark already passes through
<table data-layout="default">
  <colgroup>
    <col style="width: 160.0px;" />
    <col style="width: 720.0px;" />
  </colgroup>
  ...
</table>

Proposed solution

A custom table renderer that emits a <colgroup>, opt-in so default output stays the bare <table> and existing pages are unaffected. Two modes:

1. Explicit widths — author-supplied, e.g. via goldmark's attribute plumbing. Syntax is TBD; illustrative only:

| Field | Value |
|-------|-------|
| Status | Draft |
{widths="160,720"}

Percentages (widths="20%,80%") and a data-layout control (layout="full-width") are natural follow-ons.

2. Content-proportional ("auto") widths — since mark has the cell text at build time, it can size columns from content, approximating the browser/GitLab behavior that prompted this. Viewport-independent heuristic: per column, take the max cell length (header included) and emit percentage widths proportional to those maxima (width_i% = maxlen_i / Σ maxlen), with optional min/max clamps. Percentages keep the table within its container, so the "content exceeds page width" case degrades gracefully — columns keep their proportional share and long cells wrap instead of forcing a horizontal scroll.

Caveat: character count is a proxy for rendered width (proportional fonts, inline markup, CJK, multi-line cells all skew it), so this is a better default than equal columns, not a pixel-perfect browser clone. Whether "auto" ever becomes the default vs. staying opt-in is a maintainer call.

Alternatives considered

Environment

mark v15.3.0 · goldmark v1.8.4

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions