Skip to content

Preserve crossref divs nested in layout-ncol#234

Merged
cwickham merged 2 commits into
mainfrom
fix/crossref-in-layout-ncol
May 8, 2026
Merged

Preserve crossref divs nested in layout-ncol#234
cwickham merged 2 commits into
mainfrom
fix/crossref-in-layout-ncol

Conversation

@cwickham
Copy link
Copy Markdown
Collaborator

@cwickham cwickham commented May 7, 2026

Summary

  • Run the layout filter at pre-quarto so it transforms layout-ncol divs before Quarto's PanelLayout filter consumes them.
  • In collect_cells, only unwrap bare wrapper Divs (no id, no classes, no attributes). Crossref/float divs that the Quarto preprocessor has converted into custom-AST nodes (carrying __quarto_custom_type="FloatRefTarget" markers) are now kept whole so the crossref resolver can still find them.

Scope

This PR fixes a real bug: @tbl-foo / @fig-foo references whose target div sits inside layout-ncol used to render as ?@tbl-foo (Quarto's "unresolved" marker) because our collect_cells was destroying the FloatRefTarget marker on the inner Div before the crossref resolver could see it. After this PR, references resolve correctly and the target gets a working id="..." anchor.

It does not close #186. That issue is broader: Quarto's hugo-md writer also flattens crossref targets (image-as-figure, image-as-table) into a bare <img id="..." alt="Label N: caption"> block — the caption is baked into the alt attribute and never rendered as a visible <figcaption>. That's a hugo-md writer limitation, independent of layout, and applies equally to bare crossref divs at the top level. We'll address it in a follow-up (likely a small post-processing Lua filter that wraps these flat <img> blocks as proper <figure>+<figcaption> HTML).

Test plan

  • Re-rendered three existing layout-ncol posts (2023-04-26-1.3-release, 2024-10-15-conf-workshops-materials, 2025-07-24-parameterized-reports-python) — .md outputs are byte-identical to before, no regressions.
  • Confirmed in a minimal test that a tbl- crossref div nested inside layout-ncol now resolves through to a working anchor (used to emit ?@tbl-foo).
  • Reviewer: spot-check Netlify preview for any post that uses layout-ncol.

Quarto cross-references like `@tbl-foo` failed to resolve when the
target div was nested inside a `layout-ncol` block. Two reasons:

1. The layout filter ran at the default (post-quarto) stage, so
   Quarto's PanelLayout filter had already consumed the `layout-ncol`
   Div before our filter could transform it — the inner crossref Div
   was stripped along the way.

2. Even running earlier, `collect_cells` unwrapped *any* Div via
   `cells:insert(el.content)`. Quarto's preprocessor turns crossref
   divs into custom-AST nodes that look like Divs but carry
   `__quarto_custom_type="FloatRefTarget"` markers; unwrapping
   destroyed those markers, and the crossref resolver could no longer
   find the target.

Fixes:
- `_extension.yml`: register the filter at `pre-quarto` so it
  transforms the layout div before Quarto's PanelLayout filter sees it.
- `layout.lua`: only unwrap *bare* Divs (no id, no classes, no
  attributes). Divs that carry identity — including FloatRefTarget
  custom-AST nodes — are kept whole so the crossref resolver can
  still find them.

Also: in 2024-01-24-1.4-release, replace the raw-HTML `@tbl-table`
workaround with a real `::: {#tbl-table}` crossref div, fix the
image path, and convert the second hard-coded link to `@tbl-table`.

Closes #186
@netlify
Copy link
Copy Markdown

netlify Bot commented May 7, 2026

Deploy Preview for posit-open-source canceled.

Name Link
🔨 Latest commit 44e7ffa
🔍 Latest deploy log https://app.netlify.com/projects/posit-open-source/deploys/69fe5662f513d900084ce283

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 7, 2026

Publishing checklist

  • Get a review — request at least one reviewer on this PR
  • Check your post — once the deploy preview is ready, a comment will appear with direct links to your post
  • Check the blog listing — confirm your post appears with the correct title, image, and description
  • Merge — once everything looks good and you have an approving review, merge to main

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 7, 2026

Blog YAML Checks

✅ All 1 posts passed.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 7, 2026

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 7, 2026

The filter changes in the prior commit fix a real bug — Quarto crossref
divs nested inside `layout-ncol` no longer have their FloatRefTarget
markers destroyed, so `@tbl-foo` references resolve correctly.

But on hugo-md the *target* of a crossref div containing an image still
renders as a flat `<img id="..." alt="Label N: caption">` with no visible
caption — the caption is baked into the alt text. That's a hugo-md
writer limitation, separate from the layout/filter issue, and applies
equally to bare crossref divs outside any layout wrapper.

So the layout filter fix stands as a real improvement, but it doesn't
get this specific post to a better-looking state than the prior raw-HTML
workaround. Restore the workaround until we decide how to address the
caption issue more broadly.
@cwickham cwickham changed the title Fix Quarto crossrefs nested in layout-ncol blocks Preserve crossref divs nested in layout-ncol May 8, 2026
@cwickham cwickham merged commit 0cab3ed into main May 8, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Resolve quarto cross-references

1 participant