quarto-dev / quarto-dev/quarto-cli
Table Attr (id, classes, attributes) is silently dropped when tbl-colwidths triggers a SimpleTable round-trip
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 6k
- Forks
- 458
- Avg merge
- 1d 9h
- Merged PRs (30d)
- 41
Description
I have:
- searched the issue tracker for similar issues
- installed the latest version of Quarto CLI
- formatted my issue following the Bug Reports guide
Bug description
Bug description
resolve_table_colwidths_scoped (in share/filters/modules/tablecolwidths.lua) applies column widths by round-tripping the table through pandoc.utils.to_simple_table / from_simple_table. SimpleTable has no Attr, so the rebuilt table loses its identifier, classes and attributes.
This is invisible for tables labelled the normal Quarto way ({#tbl-x} in the caption), because crossref carries the id on a wrapping div. It bites when a user Lua filter sets el.identifier (or el.attr) on a Table: the attribute is present in the AST until the pre-scope-resolution step and gone right after it.
With the HTML default tbl-colwidths: auto, the round-trip is triggered by the mere presence of a Link anywhere in the table — the auto branch scans for links and, if it finds one, zeroes the computed widths. So the symptom looks arbitrary from the outside: tables with links lose their id, tables without links keep it.
With tbl-colwidths: false or an explicit list, the attributes are lost for every table, link or no link.
Notes
Related but not the same:
- #7072 (closed):
{#tbl-x tbl-colwidths="[…]"}declared in the caption of a book project. - #13776 (closed by #14096): the same
to_simple_table/from_simple_tableround-trip, losing a different thing — merged cells. The fix added anis_simple(tbl)guard that bails out when the table has spans, but the round-trip is still lossy forAttron every other table, so the guard doesn't cover this case.
A guard for spans and a silentAttrloss suggest the round-trip itself is the wrong tool here; setting the widths ontbl.colspecsdirectly would avoid both.
Steps to reproduce
filter.lua:
function Table(el)
el.attr = pandoc.Attr("my-id", {"my-class"}, {{"data-mine", "1"}})
return el
end
_quarto.yml:
project:
type: default
filters:
- filter.lua
format:
html:
toc: false
with-link.qmd:
---
title: With link
---
| A | B |
|---|---|
| one | [two](https://example.org) |
: Caption.
without-link.qmd — the same file, with the cell two instead of the link.
Then quarto render with-link.qmd without-link.qmd --to html.
Actual behavior
<!-- without-link.html -->
<table id="my-id" class="my-class caption-top table" data-mine="1">
<!-- with-link.html -->
<table class="caption-top table">
QUARTO_TRACE_FILTERS=trace quarto render with-link.qmd shows the Attr intact through pre-output-location and empty at pre-scope-resolution, which is where resolve_scoped_elements runs resolve_table_colwidths_scoped.
Setting tbl-colwidths: true keeps the Attr in both files — that branch returns nil and never rebuilds the table. Setting tbl-colwidths: false or [50,50] loses it in both.
Expected behavior
Applying column widths should preserve the table's Attr. Something like reassigning result.attr = tbl.attr after from_simple_table, or setting the widths on tbl.colspecs directly instead of going through SimpleTable.
Your environment
Quarto 1.10.18 (also reproduced on 1.5.57)
- macOS
- Not R/Python specific: plain
.qmd, no engine.
Quarto check output
❯ quarto check
Quarto 1.10.18
[✓] Checking environment information...
Quarto cache location: /Volumes/macmini external ssd/eukeni_external/Library/Caches/quarto
[✓] Checking versions of quarto binary dependencies...
Pandoc version 3.10.0: OK
Dart Sass version 1.101.0: OK
Deno version 2.7.14: OK
Typst version 0.15.1: OK
[✓] Checking versions of quarto dependencies......OK
[✓] Checking Quarto installation......OK
Version: 1.10.18
Path: /Applications/quarto/bin
[✓] Checking tools....................OK
TinyTeX: (not installed)
Chrome Headless Shell: (not installed)
VeraPDF: (not installed)
[✓] Checking LaTeX....................OK
Using: Installation From Path
Path: /Library/TeX/texbin
Version: 2025
[✓] Checking Chrome Headless....................OK
Using: Chrome found on system
Path: /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
Source: MacOS known location
[✓] Checking basic markdown render....OK
[✓] Checking R installation...........(None)
Unable to locate an installed version of R.
Install R from https://cloud.r-project.org/
[✓] Checking Python 3 installation....OK
Version: 3.14.6
Path: /opt/homebrew/opt/python@3.14/bin/python3.14
Jupyter: (None)
Jupyter is not available in this Python installation.
Install with python3 -m pip install jupyter
[✓] Checking Julia installation...
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in share/filters/modules/tablecolwidths.lua at resolve_table_colwidths_scoped and trace the to_simple_table/from_simple_table round-trip used for tbl-colwidths. Reproduce the issue with filter.lua and the with-link.qmd and without-link.qmd examples, then verify that rendered tables preserve their identifier, classes, and attributes across the affected tbl-colwidths settings.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- lua
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 76/100