Skip to content

Conversation

@RemcoSmitsDev
Copy link
Contributor

@RemcoSmitsDev RemcoSmitsDev commented Oct 9, 2025

Closes #39837

This PR adds support for colspan feature that is only supported for HTML tables. I also fixed an edge case where the right side border was not applied because it didn't match the total column count.

Before
499166907-385cc787-fc89-4e6d-bf06-c72c3c0bd775

After
Screenshot 2025-10-21 at 22 51 55

<table>
    <tr>
        <th rowspan="2">Region</th>
        <th colspan="2">Revenue</th>
        <th rowspan="2">Growth</th>
    </tr>
    <tr>
        <th>Q2 2024</th>
        <th>Q3 2024</th>
    </tr>
    <tr>
        <td>North America</td>
        <td>$2.8M</td>
        <td>$2.4B</td>
        <td>+85,614%</td>
    </tr>
    <tr>
        <td>Europe</td>
        <td>$1.2M</td>
        <td>$1.9B</td>
        <td>+158,233%</td>
    </tr>
    <tr>
        <td>Asia-Pacific</td>
        <td>$0.5M</td>
        <td>$1.4B</td>
        <td>+279,900%</td>
    </tr>
</table>

TODO:

  • Add tests for rending logic
  • Test all the tables again

cc @bennetbo

Release Notes:

  • Markdown: Added support for colspan and rowspan for HTML tables
@cla-bot cla-bot bot added the cla-signed The user has signed the Contributor License Agreement label Oct 9, 2025
@github-actions github-actions bot added the community champion Issues filed by our amazing community champions! 🫶 label Oct 9, 2025
@RemcoSmitsDev RemcoSmitsDev marked this pull request as ready for review October 10, 2025 19:44
@RemcoSmitsDev RemcoSmitsDev marked this pull request as draft October 12, 2025 08:48
@RemcoSmitsDev RemcoSmitsDev marked this pull request as ready for review October 12, 2025 09:19
@RemcoSmitsDev RemcoSmitsDev changed the title markdown: Add support for colspan with HTML tables Oct 12, 2025
RemcoSmitsDev and others added 2 commits October 12, 2025 11:41
Co-Authored-By: Zed AI <ai@zed.nl>
@Angelk90
Copy link
Contributor

@RemcoSmitsDev :
I tested the code.

Here are some considerations:

First table tested:

  1. The text Region should take up two vertical lines, but instead it only takes one. The two lines should be joined, and the text should be central and bold.
  2. All text in the header should be central and bold.

Second table tested:

  1. All text in the header should be central and bold.
  2. Side texts like Contact should be bold. I don't know if they're central.

Third table tested:

  1. All text in the header should be central and bold.
  2. Side texts like 1 bedroom should be bold. I don't know if they're central.
  3. City names, such as Rome, should be central and bold, considering all columns.
Screenshot 2025-10-13 alle 10 16 55
Region Revenue Growth
Q2 2024 Q3 2024
North America $2.8M $2.4B +85,614%
Europe $1.2M $1.9B +158,233%
Asia-Pacific $0.5M $1.4B +279,900%
Supplier contacts
  Example 1 Ltd Example 2 Co
Contact James Phillips Marie Beauchamp
Position Sales Director Sales Manager
Email jp@1ltd.example.com marie@2co.example.com
  Example 3 Ltd Example 4 Inc
Contact Suzette Jones Alex Howe
Position Sales Officer Sales Director
Email Suz@ltd3.example.com howe@4inc.example.com
Availability of holiday accommodation
Studio Apt Chalet Villa
Paris
1 bedroom 11 20 25 23
2 bedroom - 43 52 32
3 bedroom - 13 15 40
Rome
1 bedroom 13 21 22 3
2 bedroom - 23 43 30
3 bedroom - 16 32 40
Rome
Studio Apt Chalet Villa
1 bedroom 13 21 22 3
2 bedroom - 23 43 30
3 bedroom - 16 32 40

code:

<table>
    <tr>
        <th rowspan="2">Region</th>
        <th colspan="2">Revenue</th>
        <th rowspan="2">Growth</th>
    </tr>
    <tr>
        <th>Q2 2024</th>
        <th>Q3 2024</th>
    </tr>
    <tr>
        <td>North America</td>
        <td>$2.8M</td>
        <td>$2.4B</td>
        <td>+85,614%</td>
    </tr>
    <tr>
        <td>Europe</td>
        <td>$1.2M</td>
        <td>$1.9B</td>
        <td>+158,233%</td>
    </tr>
    <tr>
        <td>Asia-Pacific</td>
        <td>$0.5M</td>
        <td>$1.4B</td>
        <td>+279,900%</td>
    </tr>
</table>

<table>
  <caption>
    Supplier contacts
  </caption>
  <tr>
    <th id="blank">&nbsp;</th>
    <th id="co1" headers="blank">Example 1 Ltd</th>
    <th id="co2" headers="blank">Example 2 Co</th>
  </tr>
  <tr>
    <th id="c1" headers="blank">Contact</th>
    <td headers="co1 c1">James Phillips</td>
    <td headers="co2 c1">Marie Beauchamp</td>
  </tr>
  <tr>
    <th id="p1"  headers="blank">Position</th>
    <td headers="co1 p1">Sales Director</td>
    <td headers="co2 p1">Sales Manager</td>
  </tr>
  <tr>
    <th id="e1"  headers="blank">Email</th>
    <td headers="co1 e1">jp@1ltd.example.com</td>
    <td headers="co2 e1">marie@2co.example.com</td>
  </tr>
  <tr>
    <th>&nbsp;</th>
    <th id="co3" headers="blank">Example 3 Ltd</th>
    <th id="co4" headers="blank">Example 4 Inc</th>
  </tr>
  <tr>
    <th id="c2"  headers="blank">Contact</th>
    <td headers="co3 c2">Suzette Jones</td>
    <td headers="co4 c2">Alex Howe</td>
  </tr>
  <tr>
    <th id="p2" headers="blank">Position</th>
    <td headers="co3 p2">Sales Officer</td>
    <td headers="co4 p2">Sales Director</td>
  </tr>
  <tr>
    <th id="e2" headers="blank">Email</th>
    <td headers="co3 e2">Suz@ltd3.example.com</td>
    <td headers="co4 e2">howe@4inc.example.com</td>
  </tr>
</table>

<table summary="Column one has the location and size of accommodation, other columns show the type and number of properties available">
<caption>
    Availability of holiday accommodation
</caption>
<thead>
    <tr>
        <td></td>
        <th id="stud" scope="col">
            Studio
        </th>
        <th id="apt" scope="col">
            <abbr title="Apartment">Apt</abbr>
        </th>
        <th id="chal" scope="col">
            Chalet
        </th>
        <th id="villa" scope="col">
            Villa
        </th>
    </tr>
</thead>
<tbody>
    <tr>
        <th id="par" class="span" colspan="5" scope="colgroup">
            Paris
        </th>
    </tr>
    <tr>
        <th headers="par" id="pbed1">
            1 bedroom
        </th>
        <td headers="par pbed1 stud">
            11
        </td>
        <td headers="par pbed1 apt">
            20
        </td>
        <td headers="par pbed1 chal">
            25
        </td>
        <td headers="par pbed1 villa">
            23
        </td>
    </tr>
    <tr>
        <th headers="par" id="pbed2">
            2 bedroom
        </th>
        <td headers="par pbed2 stud">
            -
        </td>
        <td headers="par pbed2 apt">
            43
        </td>
        <td headers="par pbed2 chal">
            52
        </td>
        <td headers="par pbed2 villa">
            32
        </td>
    </tr>
    <tr>
        <th headers="par" id="pbed3">
            3 bedroom
        </th>
        <td headers="par pbed3 stud">
            -
        </td>
        <td headers="par pbed3 apt">
            13
        </td>
        <td headers="par pbed3 chal">
            15
        </td>
        <td headers="par pbed3 villa">
            40
        </td>
    </tr>
    <tr>
        <th id="rome" class="span" colspan="5" scope="colgroup">
            Rome
        </th>
    </tr>
    <tr>
        <th id="rbed1" headers="rome">
            1 bedroom
        </th>
        <td headers="rome rbed1 stud">
            13
        </td>
        <td headers="rome rbed1 apt">
            21
        </td>
        <td headers="rome rbed1 chal">
            22
        </td>
        <td headers="rome rbed1 villa">
            3
        </td>
    </tr>
    <tr>
        <th id="rbed2" headers="rome">
            2 bedroom
        </th>
        <td headers="rome rbed2 stud">
            -
        </td>
        <td headers="rome rbed2 apt">
            23
        </td>
        <td headers="rome rbed2 chal">
            43
        </td>
        <td headers="rome rbed2 villa">
            30
        </td>
    </tr>
    <tr>
        <th id="rbed3" headers="rome">
            3 bedroom
        </th>
        <td headers="rome rbed3 stud">
            -
        </td>
        <td headers="rome rbed3 apt">
            16
        </td>
        <td headers="rome rbed3 chal">
            32
        </td>
        <td headers="rome rbed3 villa">
            40
        </td>
    </tr>
</tbody>
</table>

<table class="numbers" style="margin-top:1em;">
<caption>
    Rome
</caption>
<thead>
    <tr>
        <td></td>
        <th scope="col">
            Studio
        </th>
        <th scope="col">
            <abbr title="Apartment">Apt</abbr>
        </th>
        <th scope="col">
            Chalet
        </th>
        <th scope="col">
            Villa
        </th>
    </tr>
</thead>
<tbody>
    <tr>
        <th id="rbed1">
            1 bedroom
        </th>
        <td>
            13
        </td>
        <td>
            21
        </td>
        <td>
            22
        </td>
        <td>
            3
        </td>
    </tr>
    <tr>
        <th id="rbed2">
            2 bedroom
        </th>
        <td>
            -
        </td>
        <td>
            23
        </td>
        <td>
            43
        </td>
        <td>
            30
        </td>
    </tr>
    <tr>
        <th id="rbed3">
            3 bedroom
        </th>
        <td>
            -
        </td>
        <td>
            16
        </td>
        <td>
            32
        </td>
        <td>
            40
        </td>
    </tr>
</tbody>
</table>
@RemcoSmitsDev RemcoSmitsDev marked this pull request as draft October 19, 2025 15:57
@RemcoSmitsDev
Copy link
Contributor Author

@Angelk90 thanks for testing the PR, I will try to improve this PR to actually expand the row as HTML tables do.

@RemcoSmitsDev
Copy link
Contributor Author

To correctly fix the row span, we need to first fix the grid sizing issue. Right now, you need to specify the container (div().grid()) size in order the grid to take up the needed space.

RemcoSmitsDev and others added 2 commits October 21, 2025 20:57
Co-authored-by: Anthony Eid <hello@anthonyeid.me>
Problem summarized by agent:

he `grid_rows()` method is creating rows with `minmax(0, 1fr)` which
means: - Minimum size: 0 (can collapse to nothing) - Maximum size: 1fr
(equal fractions)

This is the problem! The rows can collapse to 0 height. We need to use
`auto` sizing for rows instead so they size based on their content. Let
me check if there's an alternative or if we need to not set grid_rows at
all:

Co-authored-by: Anthony Eid <hello@anthonyeid.me>
@RemcoSmitsDev RemcoSmitsDev force-pushed the markdown-support-col-span branch from 2f27c7d to 44192ec Compare October 21, 2025 20:34
RemcoSmitsDev and others added 2 commits October 21, 2025 22:52
Co-authored-by: Anthony Eid <hello@anthonyeid.me>
@RemcoSmitsDev RemcoSmitsDev marked this pull request as ready for review October 21, 2025 21:08
@RemcoSmitsDev
Copy link
Contributor Author

Only need to test all the old tables so i didnt break anything, will do that tomorrow.

@RemcoSmitsDev
Copy link
Contributor Author

Should be good to go.

@Angelk90
Copy link
Contributor

@RemcoSmitsDev : I'm not sure how it should look, but I've highlighted the areas where I'm unsure about the colors used, seeing how GitHub does it (see below).

First table highlighted, in position, the two following columns should perhaps have the same color as the position column.

Second and third table highlighted, first row, first column, should perhaps have the same color as the other headers.

In the second table, the odd-numbered rows in the highlighted columns do not match the same color as the column preceding them; I'm talking about the same reference row.

In the third table, the even-numbered rows in the highlighted columns do not match the same color as the column preceding them; I'm talking about the same reference row.

I hope I've been clear, but I'm not sure what the correct approach is.

Screenshot 2025-10-22 alle 11 50 22
Region Revenue Growth
Q2 2024 Q3 2024
North America $2.8M $2.4B +85,614%
Europe $1.2M $1.9B +158,233%
Asia-Pacific $0.5M $1.4B +279,900%
Supplier contacts
  Example 1 Ltd Example 2 Co
Contact James Phillips Marie Beauchamp
Position Sales Director Sales Manager
Email jp@1ltd.example.com marie@2co.example.com
  Example 3 Ltd Example 4 Inc
Contact Suzette Jones Alex Howe
Position Sales Officer Sales Director
Email Suz@ltd3.example.com howe@4inc.example.com
Availability of holiday accommodation
Studio Apt Chalet Villa
Paris
1 bedroom 11 20 25 23
2 bedroom - 43 52 32
3 bedroom - 13 15 40
Rome
1 bedroom 13 21 22 3
2 bedroom - 23 43 30
3 bedroom - 16 32 40
Rome
Studio Apt Chalet Villa
1 bedroom 13 21 22 3
2 bedroom - 23 43 30
3 bedroom - 16 32 40

code:

<table>
    <tr>
        <th rowspan="2">Region</th>
        <th colspan="2">Revenue</th>
        <th rowspan="2">Growth</th>
    </tr>
    <tr>
        <th>Q2 2024</th>
        <th>Q3 2024</th>
    </tr>
    <tr>
        <td>North America</td>
        <td>$2.8M</td>
        <td>$2.4B</td>
        <td>+85,614%</td>
    </tr>
    <tr>
        <td>Europe</td>
        <td>$1.2M</td>
        <td>$1.9B</td>
        <td>+158,233%</td>
    </tr>
    <tr>
        <td>Asia-Pacific</td>
        <td>$0.5M</td>
        <td>$1.4B</td>
        <td>+279,900%</td>
    </tr>
</table>

<table>
  <caption>
    Supplier contacts
  </caption>
  <tr>
    <th id="blank">&nbsp;</th>
    <th id="co1" headers="blank">Example 1 Ltd</th>
    <th id="co2" headers="blank">Example 2 Co</th>
  </tr>
  <tr>
    <th id="c1" headers="blank">Contact</th>
    <td headers="co1 c1">James Phillips</td>
    <td headers="co2 c1">Marie Beauchamp</td>
  </tr>
  <tr>
    <th id="p1"  headers="blank">Position</th>
    <td headers="co1 p1">Sales Director</td>
    <td headers="co2 p1">Sales Manager</td>
  </tr>
  <tr>
    <th id="e1"  headers="blank">Email</th>
    <td headers="co1 e1">jp@1ltd.example.com</td>
    <td headers="co2 e1">marie@2co.example.com</td>
  </tr>
  <tr>
    <th>&nbsp;</th>
    <th id="co3" headers="blank">Example 3 Ltd</th>
    <th id="co4" headers="blank">Example 4 Inc</th>
  </tr>
  <tr>
    <th id="c2"  headers="blank">Contact</th>
    <td headers="co3 c2">Suzette Jones</td>
    <td headers="co4 c2">Alex Howe</td>
  </tr>
  <tr>
    <th id="p2" headers="blank">Position</th>
    <td headers="co3 p2">Sales Officer</td>
    <td headers="co4 p2">Sales Director</td>
  </tr>
  <tr>
    <th id="e2" headers="blank">Email</th>
    <td headers="co3 e2">Suz@ltd3.example.com</td>
    <td headers="co4 e2">howe@4inc.example.com</td>
  </tr>
</table>

<table summary="Column one has the location and size of accommodation, other columns show the type and number of properties available">
<caption>
    Availability of holiday accommodation
</caption>
<thead>
    <tr>
        <td></td>
        <th id="stud" scope="col">
            Studio
        </th>
        <th id="apt" scope="col">
            <abbr title="Apartment">Apt</abbr>
        </th>
        <th id="chal" scope="col">
            Chalet
        </th>
        <th id="villa" scope="col">
            Villa
        </th>
    </tr>
</thead>
<tbody>
    <tr>
        <th id="par" class="span" colspan="5" scope="colgroup">
            Paris
        </th>
    </tr>
    <tr>
        <th headers="par" id="pbed1">
            1 bedroom
        </th>
        <td headers="par pbed1 stud">
            11
        </td>
        <td headers="par pbed1 apt">
            20
        </td>
        <td headers="par pbed1 chal">
            25
        </td>
        <td headers="par pbed1 villa">
            23
        </td>
    </tr>
    <tr>
        <th headers="par" id="pbed2">
            2 bedroom
        </th>
        <td headers="par pbed2 stud">
            -
        </td>
        <td headers="par pbed2 apt">
            43
        </td>
        <td headers="par pbed2 chal">
            52
        </td>
        <td headers="par pbed2 villa">
            32
        </td>
    </tr>
    <tr>
        <th headers="par" id="pbed3">
            3 bedroom
        </th>
        <td headers="par pbed3 stud">
            -
        </td>
        <td headers="par pbed3 apt">
            13
        </td>
        <td headers="par pbed3 chal">
            15
        </td>
        <td headers="par pbed3 villa">
            40
        </td>
    </tr>
    <tr>
        <th id="rome" class="span" colspan="5" scope="colgroup">
            Rome
        </th>
    </tr>
    <tr>
        <th id="rbed1" headers="rome">
            1 bedroom
        </th>
        <td headers="rome rbed1 stud">
            13
        </td>
        <td headers="rome rbed1 apt">
            21
        </td>
        <td headers="rome rbed1 chal">
            22
        </td>
        <td headers="rome rbed1 villa">
            3
        </td>
    </tr>
    <tr>
        <th id="rbed2" headers="rome">
            2 bedroom
        </th>
        <td headers="rome rbed2 stud">
            -
        </td>
        <td headers="rome rbed2 apt">
            23
        </td>
        <td headers="rome rbed2 chal">
            43
        </td>
        <td headers="rome rbed2 villa">
            30
        </td>
    </tr>
    <tr>
        <th id="rbed3" headers="rome">
            3 bedroom
        </th>
        <td headers="rome rbed3 stud">
            -
        </td>
        <td headers="rome rbed3 apt">
            16
        </td>
        <td headers="rome rbed3 chal">
            32
        </td>
        <td headers="rome rbed3 villa">
            40
        </td>
    </tr>
</tbody>
</table>

<table class="numbers" style="margin-top:1em;">
<caption>
    Rome
</caption>
<thead>
    <tr>
        <td></td>
        <th scope="col">
            Studio
        </th>
        <th scope="col">
            <abbr title="Apartment">Apt</abbr>
        </th>
        <th scope="col">
            Chalet
        </th>
        <th scope="col">
            Villa
        </th>
    </tr>
</thead>
<tbody>
    <tr>
        <th id="rbed1">
            1 bedroom
        </th>
        <td>
            13
        </td>
        <td>
            21
        </td>
        <td>
            22
        </td>
        <td>
            3
        </td>
    </tr>
    <tr>
        <th id="rbed2">
            2 bedroom
        </th>
        <td>
            -
        </td>
        <td>
            23
        </td>
        <td>
            43
        </td>
        <td>
            30
        </td>
    </tr>
    <tr>
        <th id="rbed3">
            3 bedroom
        </th>
        <td>
            -
        </td>
        <td>
            16
        </td>
        <td>
            32
        </td>
        <td>
            40
        </td>
    </tr>
</tbody>
</table>
@Anthony-Eid Anthony-Eid merged commit d558005 into zed-industries:main Oct 22, 2025
21 checks passed
lidm0707 pushed a commit to lidm0707/zed that referenced this pull request Oct 23, 2025
…d-industries#39898)

Closes zed-industries#39837

This PR adds support for `colspan` feature that is only supported for
HTML tables. I also fixed an edge case where the right side border was
not applied because it didn't match the total column count.

**Before**
<img width="725" height="179"
alt="499166907-385cc787-fc89-4e6d-bf06-c72c3c0bd775"
src="https://github.com/user-attachments/assets/69586053-9893-4c92-aa89-7830d2bc7a6d"
/>

**After**
<img width="1165" height="180" alt="Screenshot 2025-10-21 at 22 51 55"
src="https://github.com/user-attachments/assets/f40686e7-d95b-45a6-be42-e226e2f77483"
/>

```html
<table>
    <tr>
        <th rowspan="2">Region</th>
        <th colspan="2">Revenue</th>
        <th rowspan="2">Growth</th>
    </tr>
    <tr>
        <th>Q2 2024</th>
        <th>Q3 2024</th>
    </tr>
    <tr>
        <td>North America</td>
        <td>$2.8M</td>
        <td>$2.4B</td>
        <td>+85,614%</td>
    </tr>
    <tr>
        <td>Europe</td>
        <td>$1.2M</td>
        <td>$1.9B</td>
        <td>+158,233%</td>
    </tr>
    <tr>
        <td>Asia-Pacific</td>
        <td>$0.5M</td>
        <td>$1.4B</td>
        <td>+279,900%</td>
    </tr>
</table>
```

**TODO**:
- [x] Add tests for rending logic
- [x] Test all the tables again

cc @bennetbo

Release Notes:

- Markdown: Added support for `colspan` and `rowspan` for HTML tables

---------

Co-authored-by: Zed AI <ai@zed.nl>
Co-authored-by: Anthony Eid <hello@anthonyeid.me>
bennetbo pushed a commit that referenced this pull request Oct 25, 2025
Follow-up: #39898

Right now, we don't fill the empty column when the current row count is
less than the max row count. This PR fixes that by filling it with an
empty cell. So the table columns don't flow in the wrong direction, as
you can see inside the first screenshot.

**Before**
<img width="1095" height="182" alt="Screenshot 2025-10-24 at 16 09 02"
src="https://github.com/user-attachments/assets/e3abf24e-c190-4bd7-b43a-39f2f01ecd1c"
/>

**After**
<img width="1165" height="178" alt="Screenshot 2025-10-24 at 16 19 17"
src="https://github.com/user-attachments/assets/427c25f9-82a7-498b-a1a2-d71e4c288fe5"
/>

**Code example**
```html
<table>
    <tr>
        <th rowspan="2">Region</th>
        <th colspan="2">Revenue</th>
        <th rowspan="2">Growth</th>
    </tr>
    <tr>
        <th>Q2 2024</th>
        <th>Q3 2024</th>
    </tr>
    <tr>
        <td>North America</td>
        <td>$2.8M</td>
        <td>$2.4B</td>
        <td>+85,614%</td>
        <td>+99%</td> // extra column here
    </tr>
    <tr>
        <td>Europe</td>
        <td>$1.2M</td>
        <td>$1.9B</td>
        <td>+158,233%</td>
    </tr>
    <tr>
        <td>Asia-Pacific</td>
        <td>$0.5M</td>
        <td>$1.4B</td>
        <td>+279,900%</td>
    </tr>
</table>
```

**Note** there are no release notes, as the previous PR didn't get
released yet.

Release Notes:

- N/A
@RemcoSmitsDev RemcoSmitsDev deleted the markdown-support-col-span branch October 25, 2025 19:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla-signed The user has signed the Contributor License Agreement community champion Issues filed by our amazing community champions! 🫶

4 participants